pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
Consistently use palloc_object() and palloc_array()
29+ messages / 6 participants
[nested] [flat]

* Consistently use palloc_object() and palloc_array()
@ 2025-11-26 22:09 David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-27 00:24 ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-11-27 02:53 ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  0 siblings, 3 replies; 29+ messages in thread

From: David Geier @ 2025-11-26 22:09 UTC (permalink / raw)
  To: pgsql-hackers

Hi hackers,

I've changed all code to use the "new" palloc_object(), palloc_array(),
palloc0_object(), palloc0_array, repalloc_array() and repalloc0_array()
macros. This makes the code more readable and more consistent.

The patch is pretty big but potential merge conflicts should be easy to
resolve. If preferred, I can also further split up the patch, e.g.
directory by directory or high impact files first.

The patch is passing "meson test" and I've additionally wrote a script
that parses the patch file and verifies that every two corresponding +
and - lines match (e.g. palloc0() replaced by palloc0_array() or
palloc0_object(), the same for palloc() and repalloc(), additionally
some checks to make sure the conversion to the _array() variant is
correct).

--
David Geier

Attachments:

  [text/x-patch] v1-0001-Consistently-use-palloc_object-and-palloc_array.patch (634.1K, ../../ad0748d4-3080-436e-b0bc-ac8f86a3466a@gmail.com/2-v1-0001-Consistently-use-palloc_object-and-palloc_array.patch)
  download | inline diff:
From 341b2e967ddc95283c0631ae10996022965ab38d Mon Sep 17 00:00:00 2001
From: David Geier <geidav.pg@gmail.com>
Date: Wed, 26 Nov 2025 10:11:58 +0100
Subject: [PATCH] Consistently use palloc_object() and palloc_array()

---
 contrib/amcheck/verify_gin.c                  | 12 +--
 contrib/amcheck/verify_heapam.c               |  2 +-
 contrib/amcheck/verify_nbtree.c               |  2 +-
 .../basebackup_to_shell/basebackup_to_shell.c |  2 +-
 contrib/bloom/blinsert.c                      |  2 +-
 contrib/bloom/blscan.c                        |  4 +-
 contrib/bloom/blutils.c                       |  2 +-
 contrib/bloom/blvacuum.c                      |  4 +-
 contrib/btree_gin/btree_gin.c                 | 20 ++--
 contrib/btree_gist/btree_bool.c               |  2 +-
 contrib/btree_gist/btree_cash.c               |  2 +-
 contrib/btree_gist/btree_date.c               |  2 +-
 contrib/btree_gist/btree_enum.c               |  2 +-
 contrib/btree_gist/btree_float4.c             |  2 +-
 contrib/btree_gist/btree_float8.c             |  2 +-
 contrib/btree_gist/btree_inet.c               |  6 +-
 contrib/btree_gist/btree_int2.c               |  2 +-
 contrib/btree_gist/btree_int4.c               |  2 +-
 contrib/btree_gist/btree_int8.c               |  2 +-
 contrib/btree_gist/btree_interval.c           |  8 +-
 contrib/btree_gist/btree_macaddr.c            |  2 +-
 contrib/btree_gist/btree_macaddr8.c           |  2 +-
 contrib/btree_gist/btree_oid.c                |  2 +-
 contrib/btree_gist/btree_time.c               |  6 +-
 contrib/btree_gist/btree_ts.c                 | 10 +-
 contrib/btree_gist/btree_utils_num.c          |  4 +-
 contrib/btree_gist/btree_utils_var.c          |  8 +-
 contrib/btree_gist/btree_uuid.c               |  4 +-
 contrib/cube/cube.c                           |  2 +-
 contrib/dict_int/dict_int.c                   |  4 +-
 contrib/dict_xsyn/dict_xsyn.c                 |  8 +-
 contrib/file_fdw/file_fdw.c                   |  4 +-
 contrib/fuzzystrmatch/fuzzystrmatch.c         |  4 +-
 contrib/hstore/hstore_gin.c                   |  6 +-
 contrib/hstore/hstore_gist.c                  |  6 +-
 contrib/hstore/hstore_io.c                    |  2 +-
 contrib/hstore/hstore_op.c                    | 18 ++--
 contrib/intarray/_int_bool.c                  |  8 +-
 contrib/intarray/_int_gin.c                   |  4 +-
 contrib/intarray/_int_gist.c                  | 12 +--
 contrib/intarray/_intbig_gist.c               |  6 +-
 contrib/jsonb_plperl/jsonb_plperl.c           |  2 +-
 contrib/jsonb_plpython/jsonb_plpython.c       |  2 +-
 contrib/ltree/_ltree_gist.c                   |  6 +-
 contrib/ltree/_ltree_op.c                     |  2 +-
 contrib/ltree/ltree_gist.c                    |  6 +-
 contrib/ltree/ltree_io.c                      |  6 +-
 contrib/ltree/ltree_op.c                      |  2 +-
 contrib/ltree/ltxtquery_io.c                  |  8 +-
 contrib/pageinspect/brinfuncs.c               |  2 +-
 contrib/pageinspect/btreefuncs.c              |  6 +-
 contrib/pageinspect/ginfuncs.c                |  2 +-
 contrib/pageinspect/hashfuncs.c               |  2 +-
 contrib/pageinspect/heapfuncs.c               |  4 +-
 contrib/pg_buffercache/pg_buffercache_pages.c |  8 +-
 contrib/pg_overexplain/pg_overexplain.c       |  2 +-
 contrib/pg_trgm/trgm_gin.c                    |  8 +-
 contrib/pg_trgm/trgm_gist.c                   | 10 +-
 contrib/pg_trgm/trgm_op.c                     | 20 ++--
 contrib/pg_trgm/trgm_regexp.c                 | 22 ++---
 contrib/pg_visibility/pg_visibility.c         |  2 +-
 contrib/pg_walinspect/pg_walinspect.c         |  5 +-
 contrib/pgcrypto/mbuf.c                       |  8 +-
 contrib/pgcrypto/openssl.c                    |  4 +-
 contrib/pgcrypto/pgp-cfb.c                    |  2 +-
 contrib/pgcrypto/pgp-compress.c               |  4 +-
 contrib/pgcrypto/pgp-decrypt.c                |  4 +-
 contrib/pgcrypto/pgp-encrypt.c                |  4 +-
 contrib/pgcrypto/pgp-pgsql.c                  |  6 +-
 contrib/pgcrypto/pgp-pubkey.c                 |  2 +-
 contrib/pgcrypto/px-hmac.c                    |  2 +-
 contrib/pgcrypto/px.c                         |  2 +-
 contrib/postgres_fdw/postgres_fdw.c           | 22 ++---
 contrib/seg/seg.c                             | 10 +-
 contrib/sepgsql/label.c                       |  4 +-
 contrib/sepgsql/uavc.c                        |  2 +-
 contrib/spi/refint.c                          |  2 +-
 contrib/sslinfo/sslinfo.c                     |  2 +-
 contrib/tablefunc/tablefunc.c                 |  4 +-
 contrib/test_decoding/test_decoding.c         |  2 +-
 contrib/tsm_system_rows/tsm_system_rows.c     |  2 +-
 contrib/tsm_system_time/tsm_system_time.c     |  2 +-
 contrib/unaccent/unaccent.c                   |  8 +-
 contrib/xml2/xpath.c                          |  3 +-
 contrib/xml2/xslt_proc.c                      |  2 +-
 doc/src/sgml/gist.sgml                        |  8 +-
 doc/src/sgml/xfunc.sgml                       |  2 +-
 doc/src/sgml/xtypes.sgml                      |  2 +-
 src/backend/access/brin/brin.c                |  8 +-
 src/backend/access/brin/brin_minmax_multi.c   |  4 +-
 src/backend/access/brin/brin_revmap.c         |  2 +-
 src/backend/access/brin/brin_tuple.c          | 14 +--
 src/backend/access/common/attmap.c            |  4 +-
 src/backend/access/common/heaptuple.c         |  8 +-
 src/backend/access/common/printtup.c          |  2 +-
 src/backend/access/common/reloptions.c        |  6 +-
 src/backend/access/common/tidstore.c          |  8 +-
 src/backend/access/common/toast_internals.c   |  2 +-
 src/backend/access/common/tupconvert.c        | 20 ++--
 src/backend/access/common/tupdesc.c           |  2 +-
 src/backend/access/gin/ginbtree.c             |  6 +-
 src/backend/access/gin/ginbulk.c              |  5 +-
 src/backend/access/gin/gindatapage.c          | 14 +--
 src/backend/access/gin/ginentrypage.c         |  4 +-
 src/backend/access/gin/ginget.c               |  4 +-
 src/backend/access/gin/gininsert.c            | 16 ++--
 src/backend/access/gin/ginscan.c              | 13 +--
 src/backend/access/gin/ginutil.c              | 10 +-
 src/backend/access/gin/ginvacuum.c            |  8 +-
 src/backend/access/gist/gist.c                | 22 ++---
 src/backend/access/gist/gistbuild.c           | 10 +-
 src/backend/access/gist/gistbuildbuffers.c    | 14 +--
 src/backend/access/gist/gistproc.c            | 26 ++---
 src/backend/access/gist/gistscan.c            |  6 +-
 src/backend/access/gist/gistsplit.c           |  8 +-
 src/backend/access/gist/gistutil.c            |  4 +-
 src/backend/access/gist/gistvacuum.c          |  4 +-
 src/backend/access/hash/hash.c                |  9 +-
 src/backend/access/hash/hashsort.c            |  2 +-
 src/backend/access/heap/heapam.c              | 14 +--
 src/backend/access/heap/heapam_handler.c      |  6 +-
 src/backend/access/heap/rewriteheap.c         |  2 +-
 src/backend/access/heap/vacuumlazy.c          |  6 +-
 src/backend/access/index/amvalidate.c         |  2 +-
 src/backend/access/index/genam.c              | 14 +--
 src/backend/access/nbtree/nbtdedup.c          |  8 +-
 src/backend/access/nbtree/nbtinsert.c         |  2 +-
 src/backend/access/nbtree/nbtpage.c           |  2 +-
 src/backend/access/nbtree/nbtree.c            |  9 +-
 src/backend/access/nbtree/nbtsearch.c         |  2 +-
 src/backend/access/nbtree/nbtsort.c           | 32 +++----
 src/backend/access/nbtree/nbtsplitloc.c       |  2 +-
 src/backend/access/nbtree/nbtxlog.c           |  2 +-
 src/backend/access/spgist/spgdoinsert.c       | 33 ++++---
 src/backend/access/spgist/spginsert.c         |  2 +-
 src/backend/access/spgist/spgkdtreeproc.c     | 14 +--
 src/backend/access/spgist/spgproc.c           |  4 +-
 src/backend/access/spgist/spgquadtreeproc.c   | 22 ++---
 src/backend/access/spgist/spgscan.c           | 29 +++---
 src/backend/access/spgist/spgtextproc.c       | 19 ++--
 src/backend/access/spgist/spgutils.c          |  2 +-
 src/backend/access/spgist/spgvacuum.c         |  6 +-
 src/backend/access/spgist/spgxlog.c           |  2 +-
 src/backend/access/tablesample/bernoulli.c    |  2 +-
 src/backend/access/tablesample/system.c       |  2 +-
 src/backend/access/transam/multixact.c        |  3 +-
 src/backend/access/transam/parallel.c         |  7 +-
 src/backend/access/transam/timeline.c         |  8 +-
 src/backend/access/transam/twophase.c         | 10 +-
 src/backend/access/transam/xact.c             |  2 +-
 src/backend/access/transam/xlog.c             |  4 +-
 src/backend/access/transam/xlogfuncs.c        |  2 +-
 src/backend/access/transam/xlogprefetcher.c   |  2 +-
 src/backend/access/transam/xlogrecovery.c     |  6 +-
 src/backend/access/transam/xlogutils.c        |  2 +-
 src/backend/backup/basebackup.c               |  6 +-
 src/backend/backup/basebackup_copy.c          |  2 +-
 src/backend/backup/basebackup_gzip.c          |  2 +-
 src/backend/backup/basebackup_incremental.c   |  6 +-
 src/backend/backup/basebackup_lz4.c           |  2 +-
 src/backend/backup/basebackup_progress.c      |  2 +-
 src/backend/backup/basebackup_server.c        |  2 +-
 src/backend/backup/basebackup_target.c        |  4 +-
 src/backend/backup/basebackup_throttle.c      |  2 +-
 src/backend/backup/basebackup_zstd.c          |  2 +-
 src/backend/backup/walsummary.c               |  2 +-
 src/backend/bootstrap/bootstrap.c             |  6 +-
 src/backend/catalog/dependency.c              |  8 +-
 src/backend/catalog/heap.c                    |  8 +-
 src/backend/catalog/index.c                   |  8 +-
 src/backend/catalog/namespace.c               |  4 +-
 src/backend/catalog/objectaddress.c           |  4 +-
 src/backend/catalog/pg_constraint.c           |  2 +-
 src/backend/catalog/pg_depend.c               |  2 +-
 src/backend/catalog/pg_enum.c                 |  6 +-
 src/backend/catalog/pg_publication.c          |  6 +-
 src/backend/catalog/pg_shdepend.c             |  4 +-
 src/backend/catalog/pg_subscription.c         |  4 +-
 src/backend/catalog/storage.c                 | 10 +-
 src/backend/commands/analyze.c                |  6 +-
 src/backend/commands/cluster.c                |  4 +-
 src/backend/commands/copy.c                   |  2 +-
 src/backend/commands/copyfrom.c               |  4 +-
 src/backend/commands/copyto.c                 |  4 +-
 src/backend/commands/createas.c               |  2 +-
 src/backend/commands/dbcommands.c             |  2 +-
 src/backend/commands/event_trigger.c          | 24 ++---
 src/backend/commands/explain.c                |  2 +-
 src/backend/commands/explain_dr.c             |  2 +-
 src/backend/commands/explain_state.c          |  7 +-
 src/backend/commands/extension.c              |  4 +-
 src/backend/commands/functioncmds.c           |  2 +-
 src/backend/commands/matview.c                |  4 +-
 src/backend/commands/opclasscmds.c            | 12 +--
 src/backend/commands/policy.c                 |  6 +-
 src/backend/commands/publicationcmds.c        |  6 +-
 src/backend/commands/seclabel.c               |  2 +-
 src/backend/commands/subscriptioncmds.c       |  4 +-
 src/backend/commands/tablecmds.c              | 36 +++----
 src/backend/commands/trigger.c                |  8 +-
 src/backend/commands/tsearchcmds.c            |  8 +-
 src/backend/commands/typecmds.c               |  4 +-
 src/backend/commands/user.c                   |  4 +-
 src/backend/commands/vacuumparallel.c         |  6 +-
 src/backend/executor/execExpr.c               | 94 +++++++++----------
 src/backend/executor/execGrouping.c           |  2 +-
 src/backend/executor/execIndexing.c           |  4 +-
 src/backend/executor/execMain.c               | 18 ++--
 src/backend/executor/execParallel.c           |  2 +-
 src/backend/executor/execPartition.c          | 28 +++---
 src/backend/executor/execReplication.c        |  8 +-
 src/backend/executor/execTuples.c             |  4 +-
 src/backend/executor/functions.c              |  4 +-
 src/backend/executor/nodeAgg.c                | 42 ++++-----
 src/backend/executor/nodeAppend.c             |  2 +-
 src/backend/executor/nodeFunctionscan.c       |  2 +-
 src/backend/executor/nodeGatherMerge.c        |  6 +-
 src/backend/executor/nodeHashjoin.c           |  5 +-
 src/backend/executor/nodeIndexonlyscan.c      |  3 +-
 src/backend/executor/nodeIndexscan.c          |  8 +-
 src/backend/executor/nodeMemoize.c            |  4 +-
 src/backend/executor/nodeMergeAppend.c        |  6 +-
 src/backend/executor/nodeModifyTable.c        | 13 +--
 src/backend/executor/nodeProjectSet.c         |  6 +-
 src/backend/executor/nodeSamplescan.c         |  2 +-
 src/backend/executor/nodeTableFuncscan.c      |  4 +-
 src/backend/executor/nodeTidrangescan.c       |  2 +-
 src/backend/executor/nodeTidscan.c            |  2 +-
 src/backend/executor/nodeWindowAgg.c          | 12 +--
 src/backend/executor/spi.c                    | 21 ++---
 src/backend/executor/tqueue.c                 |  4 +-
 src/backend/executor/tstoreReceiver.c         |  2 +-
 src/backend/foreign/foreign.c                 | 10 +-
 src/backend/jit/llvm/llvmjit.c                |  6 +-
 src/backend/jit/llvm/llvmjit_deform.c         | 12 +--
 src/backend/jit/llvm/llvmjit_expr.c           | 10 +-
 src/backend/lib/bipartite_match.c             |  2 +-
 src/backend/lib/dshash.c                      |  4 +-
 src/backend/lib/integerset.c                  |  2 +-
 src/backend/lib/pairingheap.c                 |  2 +-
 src/backend/lib/rbtree.c                      |  2 +-
 src/backend/libpq/auth-oauth.c                |  8 +-
 src/backend/libpq/auth-scram.c                |  2 +-
 src/backend/libpq/hba.c                       | 10 +-
 src/backend/libpq/pqcomm.c                    |  2 +-
 src/backend/nodes/nodeFuncs.c                 |  2 +-
 src/backend/nodes/queryjumblefuncs.c          |  2 +-
 src/backend/nodes/tidbitmap.c                 |  4 +-
 src/backend/optimizer/geqo/geqo_erx.c         |  2 +-
 src/backend/optimizer/geqo/geqo_eval.c        |  2 +-
 src/backend/optimizer/geqo/geqo_pmx.c         |  8 +-
 src/backend/optimizer/geqo/geqo_pool.c        | 10 +-
 .../optimizer/geqo/geqo_recombination.c       |  2 +-
 src/backend/optimizer/path/clausesel.c        |  2 +-
 src/backend/optimizer/path/costsize.c         |  4 +-
 src/backend/optimizer/path/indxpath.c         |  7 +-
 src/backend/optimizer/path/joinrels.c         |  3 +-
 src/backend/optimizer/plan/analyzejoins.c     |  3 +-
 src/backend/optimizer/plan/createplan.c       | 34 +++----
 src/backend/optimizer/plan/initsplan.c        |  6 +-
 src/backend/optimizer/plan/planagg.c          |  2 +-
 src/backend/optimizer/plan/planner.c          |  5 +-
 src/backend/optimizer/plan/setrefs.c          |  6 +-
 src/backend/optimizer/prep/prepjointree.c     |  7 +-
 src/backend/optimizer/prep/prepunion.c        |  2 +-
 src/backend/optimizer/util/appendinfo.c       |  3 +-
 src/backend/optimizer/util/clauses.c          |  6 +-
 src/backend/optimizer/util/extendplan.c       | 15 +--
 src/backend/optimizer/util/plancat.c          | 45 +++++----
 src/backend/optimizer/util/predtest.c         |  4 +-
 src/backend/optimizer/util/relnode.c          | 14 +--
 src/backend/optimizer/util/tlist.c            | 12 +--
 src/backend/parser/analyze.c                  |  5 +-
 src/backend/parser/gram.y                     | 92 +++++++++---------
 src/backend/parser/parse_clause.c             |  4 +-
 src/backend/parser/parse_expr.c               |  4 +-
 src/backend/parser/parse_node.c               |  2 +-
 src/backend/parser/parse_param.c              |  4 +-
 src/backend/parser/parse_relation.c           | 10 +-
 src/backend/parser/parse_type.c               |  2 +-
 src/backend/partitioning/partbounds.c         | 53 +++++------
 src/backend/partitioning/partdesc.c           |  2 +-
 src/backend/partitioning/partprune.c          | 24 ++---
 src/backend/postmaster/autovacuum.c           |  6 +-
 src/backend/postmaster/bgworker.c             |  2 +-
 src/backend/postmaster/checkpointer.c         |  2 +-
 src/backend/postmaster/launch_backend.c       |  2 +-
 src/backend/postmaster/pgarch.c               |  4 +-
 src/backend/postmaster/postmaster.c           |  2 +-
 src/backend/postmaster/syslogger.c            |  2 +-
 src/backend/postmaster/walsummarizer.c        |  3 +-
 .../libpqwalreceiver/libpqwalreceiver.c       |  4 +-
 .../replication/logical/applyparallelworker.c |  2 +-
 src/backend/replication/logical/launcher.c    |  2 +-
 src/backend/replication/logical/logical.c     |  2 +-
 .../replication/logical/logicalfuncs.c        |  2 +-
 src/backend/replication/logical/proto.c       |  8 +-
 src/backend/replication/logical/relation.c    |  8 +-
 .../replication/logical/reorderbuffer.c       | 17 ++--
 src/backend/replication/logical/slotsync.c    |  2 +-
 src/backend/replication/logical/snapbuild.c   |  5 +-
 src/backend/replication/logical/syncutils.c   |  2 +-
 src/backend/replication/logical/worker.c      |  6 +-
 src/backend/replication/pgoutput/pgoutput.c   |  4 +-
 src/backend/replication/syncrep.c             |  9 +-
 src/backend/replication/walreceiver.c         |  4 +-
 src/backend/replication/walsender.c           |  2 +-
 src/backend/rewrite/rewriteHandler.c          |  2 +-
 src/backend/rewrite/rewriteManip.c            |  6 +-
 src/backend/snowball/dict_snowball.c          |  4 +-
 src/backend/statistics/dependencies.c         | 26 +++--
 src/backend/statistics/extended_stats.c       | 15 ++-
 src/backend/statistics/mcv.c                  | 24 ++---
 src/backend/statistics/mvdistinct.c           | 14 +--
 src/backend/storage/buffer/bufmgr.c           |  8 +-
 src/backend/storage/file/buffile.c            | 10 +-
 src/backend/storage/ipc/procarray.c           |  8 +-
 src/backend/storage/ipc/shm_mq.c              |  2 +-
 src/backend/storage/ipc/shmem.c               |  6 +-
 src/backend/storage/lmgr/lock.c               | 16 ++--
 src/backend/storage/lmgr/predicate.c          |  8 +-
 src/backend/storage/smgr/bulk_write.c         |  2 +-
 src/backend/storage/smgr/md.c                 |  2 +-
 src/backend/storage/smgr/smgr.c               |  2 +-
 src/backend/storage/sync/sync.c               |  2 +-
 src/backend/tcop/pquery.c                     |  2 +-
 src/backend/tsearch/dict.c                    |  2 +-
 src/backend/tsearch/dict_ispell.c             |  2 +-
 src/backend/tsearch/dict_simple.c             |  6 +-
 src/backend/tsearch/dict_synonym.c            |  8 +-
 src/backend/tsearch/dict_thesaurus.c          | 26 ++---
 src/backend/tsearch/spell.c                   | 22 ++---
 src/backend/tsearch/to_tsany.c                | 14 +--
 src/backend/tsearch/ts_parse.c                |  2 +-
 src/backend/tsearch/ts_selfuncs.c             |  2 +-
 src/backend/tsearch/ts_typanalyze.c           |  6 +-
 src/backend/tsearch/ts_utils.c                |  4 +-
 src/backend/tsearch/wparser.c                 | 16 ++--
 src/backend/tsearch/wparser_def.c             | 12 +--
 src/backend/utils/activity/pgstat_relation.c  |  2 +-
 src/backend/utils/activity/wait_event.c       |  2 +-
 src/backend/utils/adt/acl.c                   |  6 +-
 src/backend/utils/adt/array_selfuncs.c        |  8 +-
 src/backend/utils/adt/array_typanalyze.c      |  7 +-
 src/backend/utils/adt/array_userfuncs.c       | 12 +--
 src/backend/utils/adt/arrayfuncs.c            | 12 +--
 src/backend/utils/adt/arraysubs.c             |  2 +-
 src/backend/utils/adt/date.c                  | 24 ++---
 src/backend/utils/adt/datetime.c              | 10 +-
 src/backend/utils/adt/formatting.c            |  2 +-
 src/backend/utils/adt/geo_ops.c               | 94 +++++++++----------
 src/backend/utils/adt/geo_spgist.c            | 40 ++++----
 src/backend/utils/adt/int.c                   |  2 +-
 src/backend/utils/adt/int8.c                  |  2 +-
 src/backend/utils/adt/json.c                  |  6 +-
 src/backend/utils/adt/jsonb.c                 | 12 +--
 src/backend/utils/adt/jsonb_gin.c             | 19 ++--
 src/backend/utils/adt/jsonb_util.c            | 20 ++--
 src/backend/utils/adt/jsonfuncs.c             | 64 ++++++-------
 src/backend/utils/adt/jsonpath_exec.c         | 27 +++---
 src/backend/utils/adt/jsonpath_gram.y         |  4 +-
 src/backend/utils/adt/lockfuncs.c             |  2 +-
 src/backend/utils/adt/mac.c                   | 14 +--
 src/backend/utils/adt/mac8.c                  | 18 ++--
 src/backend/utils/adt/mcxtfuncs.c             |  2 +-
 src/backend/utils/adt/misc.c                  |  2 +-
 src/backend/utils/adt/multirangetypes.c       |  8 +-
 .../utils/adt/multirangetypes_selfuncs.c      |  4 +-
 src/backend/utils/adt/multixactfuncs.c        |  2 +-
 src/backend/utils/adt/network.c               | 24 ++---
 src/backend/utils/adt/network_gist.c          | 10 +-
 src/backend/utils/adt/network_spgist.c        |  6 +-
 src/backend/utils/adt/numeric.c               | 13 ++-
 src/backend/utils/adt/orderedsetaggs.c        |  4 +-
 src/backend/utils/adt/pg_locale_libc.c        |  6 +-
 src/backend/utils/adt/rangetypes.c            |  2 +-
 src/backend/utils/adt/rangetypes_gist.c       | 15 ++-
 src/backend/utils/adt/rangetypes_selfuncs.c   |  4 +-
 src/backend/utils/adt/rangetypes_spgist.c     | 18 ++--
 src/backend/utils/adt/rangetypes_typanalyze.c |  8 +-
 src/backend/utils/adt/regexp.c                | 20 ++--
 src/backend/utils/adt/rowtypes.c              | 24 ++---
 src/backend/utils/adt/ruleutils.c             |  8 +-
 src/backend/utils/adt/selfuncs.c              |  4 +-
 src/backend/utils/adt/skipsupport.c           |  2 +-
 src/backend/utils/adt/tid.c                   |  6 +-
 src/backend/utils/adt/timestamp.c             | 46 +++++----
 src/backend/utils/adt/tsginidx.c              | 10 +-
 src/backend/utils/adt/tsgistidx.c             | 10 +-
 src/backend/utils/adt/tsquery.c               | 12 +--
 src/backend/utils/adt/tsquery_cleanup.c       |  2 +-
 src/backend/utils/adt/tsquery_gist.c          |  4 +-
 src/backend/utils/adt/tsquery_op.c            | 14 +--
 src/backend/utils/adt/tsquery_util.c          | 18 ++--
 src/backend/utils/adt/tsrank.c                | 13 ++-
 src/backend/utils/adt/tsvector.c              |  4 +-
 src/backend/utils/adt/tsvector_op.c           | 10 +-
 src/backend/utils/adt/tsvector_parser.c       |  6 +-
 src/backend/utils/adt/uuid.c                  |  4 +-
 src/backend/utils/adt/varlena.c               |  2 +-
 src/backend/utils/adt/xml.c                   |  6 +-
 src/backend/utils/cache/catcache.c            |  4 +-
 src/backend/utils/cache/evtcache.c            |  2 +-
 src/backend/utils/cache/inval.c               |  2 +-
 src/backend/utils/cache/lsyscache.c           |  6 +-
 src/backend/utils/cache/partcache.c           | 24 ++---
 src/backend/utils/cache/plancache.c           | 15 ++-
 src/backend/utils/cache/relcache.c            | 30 +++---
 src/backend/utils/cache/typcache.c            |  2 +-
 src/backend/utils/error/elog.c                |  2 +-
 src/backend/utils/fmgr/funcapi.c              |  2 +-
 src/backend/utils/init/postinit.c             |  2 +-
 src/backend/utils/mb/mbutils.c                |  4 +-
 src/backend/utils/misc/conffiles.c            |  2 +-
 src/backend/utils/misc/guc-file.l             |  4 +-
 src/backend/utils/misc/guc.c                  |  4 +-
 src/backend/utils/misc/injection_point.c      |  2 +-
 src/backend/utils/misc/queryenvironment.c     |  2 +-
 src/backend/utils/misc/tzparser.c             |  2 +-
 src/backend/utils/mmgr/dsa.c                  |  4 +-
 src/backend/utils/mmgr/mcxt.c                 |  5 +
 src/backend/utils/sort/logtape.c              |  6 +-
 src/backend/utils/sort/sharedtuplestore.c     |  4 +-
 src/backend/utils/sort/tuplesort.c            |  2 +-
 src/backend/utils/sort/tuplesortvariants.c    | 12 +--
 src/backend/utils/sort/tuplestore.c           |  2 +-
 src/backend/utils/time/snapmgr.c              |  2 +-
 src/bin/pg_basebackup/astreamer_inject.c      |  2 +-
 src/bin/pg_combinebackup/load_manifest.c      |  2 +-
 src/bin/pg_dump/common.c                      |  2 +-
 src/bin/pg_dump/dumputils.c                   |  2 +-
 src/bin/pg_verifybackup/astreamer_verify.c    |  2 +-
 src/bin/pg_verifybackup/pg_verifybackup.c     |  2 +-
 src/bin/scripts/vacuuming.c                   |  2 +-
 src/common/blkreftable.c                      | 21 ++---
 src/common/parse_manifest.c                   |  4 +-
 src/common/pgfnames.c                         |  5 +-
 src/common/rmtree.c                           |  2 +-
 src/common/stringinfo.c                       |  2 +-
 src/fe_utils/astreamer_file.c                 |  4 +-
 src/fe_utils/astreamer_gzip.c                 |  4 +-
 src/fe_utils/astreamer_lz4.c                  |  4 +-
 src/fe_utils/astreamer_tar.c                  |  6 +-
 src/fe_utils/astreamer_zstd.c                 |  4 +-
 src/include/lib/radixtree.h                   |  8 +-
 src/pl/plperl/plperl.c                        | 12 +--
 src/pl/plpgsql/src/pl_comp.c                  | 32 +++----
 src/pl/plpgsql/src/pl_exec.c                  |  9 +-
 src/pl/plpgsql/src/pl_gram.y                  | 92 +++++++++---------
 src/pl/plpython/plpy_procedure.c              |  6 +-
 src/pl/plpython/plpy_spi.c                    |  4 +-
 src/pl/plpython/plpy_typeio.c                 | 12 +--
 src/pl/tcl/pltcl.c                            |  4 +-
 .../modules/dummy_index_am/dummy_index_am.c   |  2 +-
 .../modules/spgist_name_ops/spgist_name_ops.c | 10 +-
 .../modules/test_bitmapset/test_bitmapset.c   |  2 +-
 .../modules/test_integerset/test_integerset.c |  2 +-
 .../test_json_parser_incremental.c            |  2 +-
 src/test/modules/test_parser/test_parser.c    |  4 +-
 .../modules/test_radixtree/test_radixtree.c   |  2 +-
 src/test/modules/test_rbtree/test_rbtree.c    |  2 +-
 src/test/modules/test_regex/test_regex.c      | 14 ++-
 .../test_resowner/test_resowner_many.c        |  2 +-
 .../modules/test_rls_hooks/test_rls_hooks.c   |  4 +-
 src/test/modules/worker_spi/worker_spi.c      |  2 +-
 src/test/regress/regress.c                    |  2 +-
 src/timezone/pgtz.c                           |  2 +-
 src/tutorial/complex.c                        |  6 +-
 src/tutorial/funcs.c                          |  2 +-
 469 files changed, 1777 insertions(+), 1889 deletions(-)

diff --git a/contrib/amcheck/verify_gin.c b/contrib/amcheck/verify_gin.c
index 5c3eb4d0fd4..696a1176a63 100644
--- a/contrib/amcheck/verify_gin.c
+++ b/contrib/amcheck/verify_gin.c
@@ -117,7 +117,7 @@ ginReadTupleWithoutState(IndexTuple itup, int *nitems)
 	}
 	else
 	{
-		ipd = (ItemPointer) palloc(sizeof(ItemPointerData) * nipd);
+		ipd = palloc_array(ItemPointerData, nipd);
 		memcpy(ipd, ptr, sizeof(ItemPointerData) * nipd);
 	}
 	*nitems = nipd;
@@ -152,7 +152,7 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
 	leafdepth = -1;
 
 	/* Start the scan at the root page */
-	stack = (GinPostingTreeScanItem *) palloc0(sizeof(GinPostingTreeScanItem));
+	stack = palloc0_object(GinPostingTreeScanItem);
 	stack->depth = 0;
 	ItemPointerSetInvalid(&stack->parentkey);
 	stack->parentblk = InvalidBlockNumber;
@@ -354,7 +354,7 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
 									stack->blkno, i)));
 
 				/* This is an internal page, recurse into the child. */
-				ptr = (GinPostingTreeScanItem *) palloc(sizeof(GinPostingTreeScanItem));
+				ptr = palloc_object(GinPostingTreeScanItem);
 				ptr->depth = stack->depth + 1;
 
 				/*
@@ -412,7 +412,7 @@ gin_check_parent_keys_consistency(Relation rel,
 	leafdepth = -1;
 
 	/* Start the scan at the root page */
-	stack = (GinScanItem *) palloc0(sizeof(GinScanItem));
+	stack = palloc0_object(GinScanItem);
 	stack->depth = 0;
 	stack->parenttup = NULL;
 	stack->parentblk = InvalidBlockNumber;
@@ -473,7 +473,7 @@ gin_check_parent_keys_consistency(Relation rel,
 
 				elog(DEBUG3, "split detected for blk: %u, parent blk: %u", stack->blkno, stack->parentblk);
 
-				ptr = (GinScanItem *) palloc(sizeof(GinScanItem));
+				ptr = palloc_object(GinScanItem);
 				ptr->depth = stack->depth;
 				ptr->parenttup = CopyIndexTuple(stack->parenttup);
 				ptr->parentblk = stack->parentblk;
@@ -601,7 +601,7 @@ gin_check_parent_keys_consistency(Relation rel,
 			{
 				GinScanItem *ptr;
 
-				ptr = (GinScanItem *) palloc(sizeof(GinScanItem));
+				ptr = palloc_object(GinScanItem);
 				ptr->depth = stack->depth + 1;
 				/* last tuple in layer has no high key */
 				if (i == maxoff && rightlink == InvalidBlockNumber)
diff --git a/contrib/amcheck/verify_heapam.c b/contrib/amcheck/verify_heapam.c
index 4963e9245cb..a090e18c697 100644
--- a/contrib/amcheck/verify_heapam.c
+++ b/contrib/amcheck/verify_heapam.c
@@ -1838,7 +1838,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
 	{
 		ToastedAttribute *ta;
 
-		ta = (ToastedAttribute *) palloc0(sizeof(ToastedAttribute));
+		ta = palloc0_object(ToastedAttribute);
 
 		VARATT_EXTERNAL_GET_POINTER(ta->toast_pointer, attr);
 		ta->blkno = ctx->blkno;
diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c
index 0949c88983a..bd80f86157c 100644
--- a/contrib/amcheck/verify_nbtree.c
+++ b/contrib/amcheck/verify_nbtree.c
@@ -400,7 +400,7 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace,
 	/*
 	 * Initialize state for entire verification operation
 	 */
-	state = palloc0(sizeof(BtreeCheckState));
+	state = palloc0_object(BtreeCheckState);
 	state->rel = rel;
 	state->heaprel = heaprel;
 	state->heapkeyspace = heapkeyspace;
diff --git a/contrib/basebackup_to_shell/basebackup_to_shell.c b/contrib/basebackup_to_shell/basebackup_to_shell.c
index 8720f5a4372..345d3ed895d 100644
--- a/contrib/basebackup_to_shell/basebackup_to_shell.c
+++ b/contrib/basebackup_to_shell/basebackup_to_shell.c
@@ -136,7 +136,7 @@ shell_get_sink(bbsink *next_sink, void *detail_arg)
 	 * We remember the current value of basebackup_to_shell.shell_command to
 	 * be certain that it can't change under us during the backup.
 	 */
-	sink = palloc0(sizeof(bbsink_shell));
+	sink = palloc0_object(bbsink_shell);
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_shell_ops;
 	sink->base.bbs_next = next_sink;
 	sink->target_detail = detail_arg;
diff --git a/contrib/bloom/blinsert.c b/contrib/bloom/blinsert.c
index 7866438122f..c11e06c34ee 100644
--- a/contrib/bloom/blinsert.c
+++ b/contrib/bloom/blinsert.c
@@ -151,7 +151,7 @@ blbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 
 	MemoryContextDelete(buildstate.tmpCtx);
 
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 	result->heap_tuples = reltuples;
 	result->index_tuples = buildstate.indtuples;
 
diff --git a/contrib/bloom/blscan.c b/contrib/bloom/blscan.c
index d072f47fe28..0d71edbe91c 100644
--- a/contrib/bloom/blscan.c
+++ b/contrib/bloom/blscan.c
@@ -29,7 +29,7 @@ blbeginscan(Relation r, int nkeys, int norderbys)
 
 	scan = RelationGetIndexScan(r, nkeys, norderbys);
 
-	so = (BloomScanOpaque) palloc(sizeof(BloomScanOpaqueData));
+	so = (BloomScanOpaque) palloc_object(BloomScanOpaqueData);
 	initBloomState(&so->state, scan->indexRelation);
 	so->sign = NULL;
 
@@ -86,7 +86,7 @@ blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 		/* New search: have to calculate search signature */
 		ScanKey		skey = scan->keyData;
 
-		so->sign = palloc0(sizeof(BloomSignatureWord) * so->state.opts.bloomLength);
+		so->sign = palloc0_array(BloomSignatureWord, so->state.opts.bloomLength);
 
 		for (i = 0; i < scan->numberOfKeys; i++)
 		{
diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c
index 2c0e71eedc6..ba1465c257f 100644
--- a/contrib/bloom/blutils.c
+++ b/contrib/bloom/blutils.c
@@ -86,7 +86,7 @@ makeDefaultBloomOptions(void)
 	BloomOptions *opts;
 	int			i;
 
-	opts = (BloomOptions *) palloc0(sizeof(BloomOptions));
+	opts = palloc0_object(BloomOptions);
 	/* Convert DEFAULT_BLOOM_LENGTH from # of bits to # of words */
 	opts->bloomLength = (DEFAULT_BLOOM_LENGTH + SIGNWORDBITS - 1) / SIGNWORDBITS;
 	for (i = 0; i < INDEX_MAX_KEYS; i++)
diff --git a/contrib/bloom/blvacuum.c b/contrib/bloom/blvacuum.c
index 9e5f0574fad..e90a4bfb178 100644
--- a/contrib/bloom/blvacuum.c
+++ b/contrib/bloom/blvacuum.c
@@ -42,7 +42,7 @@ blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 	GenericXLogState *gxlogState;
 
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 
 	initBloomState(&state, index);
 
@@ -172,7 +172,7 @@ blvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 		return stats;
 
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 
 	/*
 	 * Iterate over the pages: insert deleted pages into FSM and collect
diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c
index 8c477d17e22..aac9b84ea56 100644
--- a/contrib/btree_gin/btree_gin.c
+++ b/contrib/btree_gin/btree_gin.c
@@ -51,7 +51,7 @@ gin_btree_extract_value(FunctionCallInfo fcinfo, bool is_varlena)
 {
 	Datum		datum = PG_GETARG_DATUM(0);
 	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
-	Datum	   *entries = (Datum *) palloc(sizeof(Datum));
+	Datum	   *entries = palloc_object(Datum);
 
 	/* Ensure that values stored in the index are not toasted */
 	if (is_varlena)
@@ -74,9 +74,9 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
 	StrategyNumber strategy = PG_GETARG_UINT16(2);
 	bool	  **partialmatch = (bool **) PG_GETARG_POINTER(3);
 	Pointer   **extra_data = (Pointer **) PG_GETARG_POINTER(4);
-	Datum	   *entries = (Datum *) palloc(sizeof(Datum));
-	QueryInfo  *data = (QueryInfo *) palloc(sizeof(QueryInfo));
-	bool	   *ptr_partialmatch = (bool *) palloc(sizeof(bool));
+	Datum	   *entries = palloc_object(Datum);
+	QueryInfo  *data = palloc_object(QueryInfo);
+	bool	   *ptr_partialmatch = palloc_object(bool);
 	int			btree_strat,
 				rhs_code;
 
@@ -139,7 +139,7 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
 	data->orig_datum = datum;
 	data->entry_datum = entries[0];
 	data->typecmp = cmp_fns[rhs_code];
-	*extra_data = (Pointer *) palloc(sizeof(Pointer));
+	*extra_data = palloc_object(Pointer);
 	**extra_data = (Pointer) data;
 
 	PG_RETURN_POINTER(entries);
@@ -578,7 +578,7 @@ GIN_SUPPORT(time, leftmostvalue_time, time_rhs_is_varlena, NULL, time_cmp_fns)
 static Datum
 leftmostvalue_timetz(void)
 {
-	TimeTzADT  *v = palloc(sizeof(TimeTzADT));
+	TimeTzADT  *v = palloc_object(TimeTzADT);
 
 	v->time = 0;
 	v->zone = -24 * 3600;		/* XXX is that true? */
@@ -638,7 +638,7 @@ GIN_SUPPORT(date, leftmostvalue_date, date_rhs_is_varlena, date_cvt_fns, date_cm
 static Datum
 leftmostvalue_interval(void)
 {
-	Interval   *v = palloc(sizeof(Interval));
+	Interval   *v = palloc_object(Interval);
 
 	INTERVAL_NOBEGIN(v);
 
@@ -656,7 +656,7 @@ GIN_SUPPORT(interval, leftmostvalue_interval, interval_rhs_is_varlena, NULL, int
 static Datum
 leftmostvalue_macaddr(void)
 {
-	macaddr    *v = palloc0(sizeof(macaddr));
+	macaddr    *v = palloc0_object(macaddr);
 
 	return MacaddrPGetDatum(v);
 }
@@ -672,7 +672,7 @@ GIN_SUPPORT(macaddr, leftmostvalue_macaddr, macaddr_rhs_is_varlena, NULL, macadd
 static Datum
 leftmostvalue_macaddr8(void)
 {
-	macaddr8   *v = palloc0(sizeof(macaddr8));
+	macaddr8   *v = palloc0_object(macaddr8);
 
 	return Macaddr8PGetDatum(v);
 }
@@ -909,7 +909,7 @@ leftmostvalue_uuid(void)
 	 * palloc0 will create the UUID with all zeroes:
 	 * "00000000-0000-0000-0000-000000000000"
 	 */
-	pg_uuid_t  *retval = (pg_uuid_t *) palloc0(sizeof(pg_uuid_t));
+	pg_uuid_t  *retval = palloc0_object(pg_uuid_t);
 
 	return UUIDPGetDatum(retval);
 }
diff --git a/contrib/btree_gist/btree_bool.c b/contrib/btree_gist/btree_bool.c
index 344f059c78f..59ad60da5be 100644
--- a/contrib/btree_gist/btree_bool.c
+++ b/contrib/btree_gist/btree_bool.c
@@ -128,7 +128,7 @@ Datum
 gbt_bool_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(boolKEY));
+	void	   *out = palloc_object(boolKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(boolKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_cash.c b/contrib/btree_gist/btree_cash.c
index 282d5c5731f..f84b35f5161 100644
--- a/contrib/btree_gist/btree_cash.c
+++ b/contrib/btree_gist/btree_cash.c
@@ -177,7 +177,7 @@ Datum
 gbt_cash_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(cashKEY));
+	void	   *out = palloc_object(cashKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(cashKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_date.c b/contrib/btree_gist/btree_date.c
index 1f1a3f32b56..8cbfbb19c5a 100644
--- a/contrib/btree_gist/btree_date.c
+++ b/contrib/btree_gist/btree_date.c
@@ -192,7 +192,7 @@ Datum
 gbt_date_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(dateKEY));
+	void	   *out = palloc_object(dateKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(dateKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_enum.c b/contrib/btree_gist/btree_enum.c
index 8f1ffff4696..600e8409e88 100644
--- a/contrib/btree_gist/btree_enum.c
+++ b/contrib/btree_gist/btree_enum.c
@@ -147,7 +147,7 @@ Datum
 gbt_enum_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(oidKEY));
+	void	   *out = palloc_object(oidKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_float4.c b/contrib/btree_gist/btree_float4.c
index d9c859835da..b98503b934f 100644
--- a/contrib/btree_gist/btree_float4.c
+++ b/contrib/btree_gist/btree_float4.c
@@ -171,7 +171,7 @@ Datum
 gbt_float4_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(float4KEY));
+	void	   *out = palloc_object(float4KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(float4KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_float8.c b/contrib/btree_gist/btree_float8.c
index 567beede178..c82f9f82b2d 100644
--- a/contrib/btree_gist/btree_float8.c
+++ b/contrib/btree_gist/btree_float8.c
@@ -179,7 +179,7 @@ Datum
 gbt_float8_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(float8KEY));
+	void	   *out = palloc_object(float8KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(float8KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_inet.c b/contrib/btree_gist/btree_inet.c
index 52bf3e2446e..fe8816ecb60 100644
--- a/contrib/btree_gist/btree_inet.c
+++ b/contrib/btree_gist/btree_inet.c
@@ -97,10 +97,10 @@ gbt_inet_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)
 	{
-		inetKEY    *r = (inetKEY *) palloc(sizeof(inetKEY));
+		inetKEY    *r = palloc_object(inetKEY);
 		bool		failure = false;
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		r->lower = convert_network_to_scalar(entry->key, INETOID, &failure);
 		Assert(!failure);
 		r->upper = r->lower;
@@ -145,7 +145,7 @@ Datum
 gbt_inet_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(inetKEY));
+	void	   *out = palloc_object(inetKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(inetKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_int2.c b/contrib/btree_gist/btree_int2.c
index faf456997bb..3e3b153fd09 100644
--- a/contrib/btree_gist/btree_int2.c
+++ b/contrib/btree_gist/btree_int2.c
@@ -176,7 +176,7 @@ Datum
 gbt_int2_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(int16KEY));
+	void	   *out = palloc_object(int16KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(int16KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_int4.c b/contrib/btree_gist/btree_int4.c
index 0bdb9e58c56..db4971439f1 100644
--- a/contrib/btree_gist/btree_int4.c
+++ b/contrib/btree_gist/btree_int4.c
@@ -174,7 +174,7 @@ Datum
 gbt_int4_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(int32KEY));
+	void	   *out = palloc_object(int32KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(int32KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_int8.c b/contrib/btree_gist/btree_int8.c
index a9a7b569278..5a51f2ddd01 100644
--- a/contrib/btree_gist/btree_int8.c
+++ b/contrib/btree_gist/btree_int8.c
@@ -176,7 +176,7 @@ Datum
 gbt_int8_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(int64KEY));
+	void	   *out = palloc_object(int64KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(int64KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c
index 19eefc60cde..774cad7befe 100644
--- a/contrib/btree_gist/btree_interval.c
+++ b/contrib/btree_gist/btree_interval.c
@@ -150,7 +150,7 @@ gbt_intv_compress(PG_FUNCTION_ARGS)
 	{
 		char	   *r = (char *) palloc(2 * INTERVALSIZE);
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 
 		if (entry->leafkey)
 		{
@@ -190,10 +190,10 @@ gbt_intv_decompress(PG_FUNCTION_ARGS)
 
 	if (INTERVALSIZE != sizeof(Interval))
 	{
-		intvKEY    *r = palloc(sizeof(intvKEY));
+		intvKEY    *r = palloc_object(intvKEY);
 		char	   *key = DatumGetPointer(entry->key);
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		memcpy(&r->lower, key, INTERVALSIZE);
 		memcpy(&r->upper, key + INTERVALSIZE, INTERVALSIZE);
 
@@ -250,7 +250,7 @@ Datum
 gbt_intv_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(intvKEY));
+	void	   *out = palloc_object(intvKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_macaddr.c b/contrib/btree_gist/btree_macaddr.c
index c444a709853..d8503b1366f 100644
--- a/contrib/btree_gist/btree_macaddr.c
+++ b/contrib/btree_gist/btree_macaddr.c
@@ -147,7 +147,7 @@ Datum
 gbt_macad_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc0(sizeof(macKEY));
+	void	   *out = palloc0_object(macKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(macKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_macaddr8.c b/contrib/btree_gist/btree_macaddr8.c
index 6d9837d90a3..4f0d0fb7140 100644
--- a/contrib/btree_gist/btree_macaddr8.c
+++ b/contrib/btree_gist/btree_macaddr8.c
@@ -145,7 +145,7 @@ Datum
 gbt_macad8_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc0(sizeof(mac8KEY));
+	void	   *out = palloc0_object(mac8KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(mac8KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_oid.c b/contrib/btree_gist/btree_oid.c
index b8f2f661076..76d7c55a308 100644
--- a/contrib/btree_gist/btree_oid.c
+++ b/contrib/btree_gist/btree_oid.c
@@ -176,7 +176,7 @@ Datum
 gbt_oid_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(oidKEY));
+	void	   *out = palloc_object(oidKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_time.c b/contrib/btree_gist/btree_time.c
index 9483846c473..8c456728820 100644
--- a/contrib/btree_gist/btree_time.c
+++ b/contrib/btree_gist/btree_time.c
@@ -162,11 +162,11 @@ gbt_timetz_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)
 	{
-		timeKEY    *r = (timeKEY *) palloc(sizeof(timeKEY));
+		timeKEY    *r = palloc_object(timeKEY);
 		TimeTzADT  *tz = DatumGetTimeTzADTP(entry->key);
 		TimeADT		tmp;
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 
 		/* We are using the time + zone only to compress */
 		tmp = tz->time + (tz->zone * INT64CONST(1000000));
@@ -256,7 +256,7 @@ Datum
 gbt_time_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(timeKEY));
+	void	   *out = palloc_object(timeKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c
index b7bbae2f4d6..b7c43c20b91 100644
--- a/contrib/btree_gist/btree_ts.c
+++ b/contrib/btree_gist/btree_ts.c
@@ -146,7 +146,7 @@ ts_dist(PG_FUNCTION_ARGS)
 
 	if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
 	{
-		Interval   *p = palloc(sizeof(Interval));
+		Interval   *p = palloc_object(Interval);
 
 		p->day = INT_MAX;
 		p->month = INT_MAX;
@@ -170,7 +170,7 @@ tstz_dist(PG_FUNCTION_ARGS)
 
 	if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
 	{
-		Interval   *p = palloc(sizeof(Interval));
+		Interval   *p = palloc_object(Interval);
 
 		p->day = INT_MAX;
 		p->month = INT_MAX;
@@ -212,13 +212,13 @@ gbt_tstz_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)
 	{
-		tsKEY	   *r = (tsKEY *) palloc(sizeof(tsKEY));
+		tsKEY	   *r = palloc_object(tsKEY);
 		TimestampTz ts = DatumGetTimestampTz(entry->key);
 		Timestamp	gmt;
 
 		gmt = tstz_to_ts_gmt(ts);
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		r->lower = r->upper = gmt;
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page,
@@ -325,7 +325,7 @@ Datum
 gbt_ts_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(tsKEY));
+	void	   *out = palloc_object(tsKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_utils_num.c b/contrib/btree_gist/btree_utils_num.c
index 446fa930b92..23d03c3669b 100644
--- a/contrib/btree_gist/btree_utils_num.c
+++ b/contrib/btree_gist/btree_utils_num.c
@@ -89,7 +89,7 @@ gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
 
 		memcpy(&r[0], leaf, tinfo->size);
 		memcpy(&r[tinfo->size], leaf, tinfo->size);
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
 					  entry->offset, false);
 	}
@@ -156,7 +156,7 @@ gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
 			datum = entry->key;
 	}
 
-	retval = palloc(sizeof(GISTENTRY));
+	retval = palloc_object(GISTENTRY);
 	gistentryinit(*retval, datum, entry->rel, entry->page, entry->offset,
 				  false);
 	return retval;
diff --git a/contrib/btree_gist/btree_utils_var.c b/contrib/btree_gist/btree_utils_var.c
index fb466e5aa32..2f69389ed69 100644
--- a/contrib/btree_gist/btree_utils_var.c
+++ b/contrib/btree_gist/btree_utils_var.c
@@ -40,7 +40,7 @@ gbt_var_decompress(PG_FUNCTION_ARGS)
 
 	if (key != (GBT_VARKEY *) DatumGetPointer(entry->key))
 	{
-		GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
@@ -289,7 +289,7 @@ gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo *tinfo)
 
 		r = gbt_var_key_from_datum(leaf);
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page,
 					  entry->offset, true);
@@ -309,7 +309,7 @@ gbt_var_fetch(PG_FUNCTION_ARGS)
 	GBT_VARKEY_R r = gbt_var_key_readable(key);
 	GISTENTRY  *retval;
 
-	retval = palloc(sizeof(GISTENTRY));
+	retval = palloc_object(GISTENTRY);
 	gistentryinit(*retval, PointerGetDatum(r.lower),
 				  entry->rel, entry->page,
 				  entry->offset, true);
@@ -476,7 +476,7 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
 	v->spl_nleft = 0;
 	v->spl_nright = 0;
 
-	sv = palloc(sizeof(bytea *) * (maxoff + 1));
+	sv = palloc_array(bytea *, (maxoff + 1));
 
 	/* Sort entries */
 
diff --git a/contrib/btree_gist/btree_uuid.c b/contrib/btree_gist/btree_uuid.c
index 07f304f39f1..d423aea15c1 100644
--- a/contrib/btree_gist/btree_uuid.c
+++ b/contrib/btree_gist/btree_uuid.c
@@ -108,7 +108,7 @@ gbt_uuid_compress(PG_FUNCTION_ARGS)
 		char	   *r = (char *) palloc(2 * UUID_LEN);
 		pg_uuid_t  *key = DatumGetUUIDP(entry->key);
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 
 		memcpy(r, key, UUID_LEN);
 		memcpy(r + UUID_LEN, key, UUID_LEN);
@@ -157,7 +157,7 @@ Datum
 gbt_uuid_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(uuidKEY));
+	void	   *out = palloc_object(uuidKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(uuidKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c
index 8d3654ab7aa..9bba4160785 100644
--- a/contrib/cube/cube.c
+++ b/contrib/cube/cube.c
@@ -471,7 +471,7 @@ g_cube_decompress(PG_FUNCTION_ARGS)
 
 	if (key != DatumGetNDBOXP(entry->key))
 	{
-		GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
diff --git a/contrib/dict_int/dict_int.c b/contrib/dict_int/dict_int.c
index bdad52d2028..5d9523a1a63 100644
--- a/contrib/dict_int/dict_int.c
+++ b/contrib/dict_int/dict_int.c
@@ -38,7 +38,7 @@ dintdict_init(PG_FUNCTION_ARGS)
 	DictInt    *d;
 	ListCell   *l;
 
-	d = (DictInt *) palloc0(sizeof(DictInt));
+	d = palloc0_object(DictInt);
 	d->maxlen = 6;
 	d->rejectlong = false;
 	d->absval = false;
@@ -83,7 +83,7 @@ dintdict_lexize(PG_FUNCTION_ARGS)
 	char	   *in = (char *) PG_GETARG_POINTER(1);
 	int			len = PG_GETARG_INT32(2);
 	char	   *txt;
-	TSLexeme   *res = palloc0(sizeof(TSLexeme) * 2);
+	TSLexeme   *res = palloc0_array(TSLexeme, 2);
 
 	res[1].lexeme = NULL;
 
diff --git a/contrib/dict_xsyn/dict_xsyn.c b/contrib/dict_xsyn/dict_xsyn.c
index 1ec5285d6d1..bbb2fd850fd 100644
--- a/contrib/dict_xsyn/dict_xsyn.c
+++ b/contrib/dict_xsyn/dict_xsyn.c
@@ -109,9 +109,9 @@ read_dictionary(DictSyn *d, const char *filename)
 			{
 				d->len = (d->len > 0) ? 2 * d->len : 16;
 				if (d->syn)
-					d->syn = (Syn *) repalloc(d->syn, sizeof(Syn) * d->len);
+					d->syn = repalloc_array(d->syn, Syn, d->len);
 				else
-					d->syn = (Syn *) palloc(sizeof(Syn) * d->len);
+					d->syn = palloc_array(Syn, d->len);
 			}
 
 			/* Save first word only if we will match it */
@@ -150,7 +150,7 @@ dxsyn_init(PG_FUNCTION_ARGS)
 	ListCell   *l;
 	char	   *filename = NULL;
 
-	d = (DictSyn *) palloc0(sizeof(DictSyn));
+	d = palloc0_object(DictSyn);
 	d->len = 0;
 	d->syn = NULL;
 	d->matchorig = true;
@@ -235,7 +235,7 @@ dxsyn_lexize(PG_FUNCTION_ARGS)
 		char	   *end;
 		int			nsyns = 0;
 
-		res = palloc(sizeof(TSLexeme));
+		res = palloc_object(TSLexeme);
 
 		pos = value;
 		while ((syn = find_word(pos, &end)) != NULL)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 70564a68b13..e9cda3c47d1 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -531,7 +531,7 @@ fileGetForeignRelSize(PlannerInfo *root,
 	 * we might as well get everything and not need to re-fetch it later in
 	 * planning.
 	 */
-	fdw_private = (FileFdwPlanState *) palloc(sizeof(FileFdwPlanState));
+	fdw_private = palloc_object(FileFdwPlanState);
 	fileGetOptions(foreigntableid,
 				   &fdw_private->filename,
 				   &fdw_private->is_program,
@@ -712,7 +712,7 @@ fileBeginForeignScan(ForeignScanState *node, int eflags)
 	 * Save state in node->fdw_state.  We must save enough information to call
 	 * BeginCopyFrom() again.
 	 */
-	festate = (FileFdwExecutionState *) palloc(sizeof(FileFdwExecutionState));
+	festate = palloc_object(FileFdwExecutionState);
 	festate->filename = filename;
 	festate->is_program = is_program;
 	festate->options = options;
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.c b/contrib/fuzzystrmatch/fuzzystrmatch.c
index e7cc314b763..c8f76dfc833 100644
--- a/contrib/fuzzystrmatch/fuzzystrmatch.c
+++ b/contrib/fuzzystrmatch/fuzzystrmatch.c
@@ -370,11 +370,11 @@ _metaphone(char *word,			/* IN */
 	/*-- Allocate memory for our phoned_phrase --*/
 	if (max_phonemes == 0)
 	{							/* Assume largest possible */
-		*phoned_word = palloc(sizeof(char) * strlen(word) + 1);
+		*phoned_word = palloc_array(char, strlen(word) + 1);
 	}
 	else
 	{
-		*phoned_word = palloc(sizeof(char) * max_phonemes + 1);
+		*phoned_word = palloc_array(char, max_phonemes + 1);
 	}
 
 	/*-- The first phoneme has to be processed specially. --*/
diff --git a/contrib/hstore/hstore_gin.c b/contrib/hstore/hstore_gin.c
index 2e5fa115924..4e43aeeb05d 100644
--- a/contrib/hstore/hstore_gin.c
+++ b/contrib/hstore/hstore_gin.c
@@ -53,7 +53,7 @@ gin_extract_hstore(PG_FUNCTION_ARGS)
 
 	*nentries = 2 * count;
 	if (count)
-		entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
+		entries = palloc_array(Datum, 2 * count);
 
 	for (i = 0; i < count; ++i)
 	{
@@ -103,7 +103,7 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
 		text	   *item;
 
 		*nentries = 1;
-		entries = (Datum *) palloc(sizeof(Datum));
+		entries = palloc_object(Datum);
 		item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query), KEYFLAG);
 		entries[0] = PointerGetDatum(item);
 	}
@@ -120,7 +120,7 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
 
 		deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
 
-		entries = (Datum *) palloc(sizeof(Datum) * key_count);
+		entries = palloc_array(Datum, key_count);
 
 		for (i = 0, j = 0; i < key_count; ++i)
 		{
diff --git a/contrib/hstore/hstore_gist.c b/contrib/hstore/hstore_gist.c
index 69515dc3d3f..36825ef867b 100644
--- a/contrib/hstore/hstore_gist.c
+++ b/contrib/hstore/hstore_gist.c
@@ -175,7 +175,7 @@ ghstore_compress(PG_FUNCTION_ARGS)
 			}
 		}
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset,
@@ -195,7 +195,7 @@ ghstore_compress(PG_FUNCTION_ARGS)
 
 		res = ghstore_alloc(true, siglen, NULL);
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset,
@@ -429,7 +429,7 @@ ghstore_picksplit(PG_FUNCTION_ARGS)
 
 	maxoff = OffsetNumberNext(maxoff);
 	/* sort before ... */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index 9c53877c4a5..6b01f27c5a4 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -221,7 +221,7 @@ parse_hstore(HSParser *state)
 	bool		escaped = false;
 
 	state->plen = 16;
-	state->pairs = (Pairs *) palloc(sizeof(Pairs) * state->plen);
+	state->pairs = palloc_array(Pairs, state->plen);
 	state->pcur = 0;
 	state->ptr = state->begin;
 	state->word = NULL;
diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
index bcba75f9258..cab59700c0d 100644
--- a/contrib/hstore/hstore_op.c
+++ b/contrib/hstore/hstore_op.c
@@ -101,7 +101,7 @@ hstoreArrayToPairs(ArrayType *a, int *npairs)
 				 errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
 						key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
 
-	key_pairs = palloc(sizeof(Pairs) * key_count);
+	key_pairs = palloc_array(Pairs, key_count);
 
 	for (i = 0, j = 0; i < key_count; i++)
 	{
@@ -588,8 +588,8 @@ hstore_slice_to_array(PG_FUNCTION_ARGS)
 		PG_RETURN_POINTER(aout);
 	}
 
-	out_datums = palloc(sizeof(Datum) * key_count);
-	out_nulls = palloc(sizeof(bool) * key_count);
+	out_datums = palloc_array(Datum, key_count);
+	out_nulls = palloc_array(bool, key_count);
 
 	for (i = 0; i < key_count; ++i)
 	{
@@ -649,7 +649,7 @@ hstore_slice_to_hstore(PG_FUNCTION_ARGS)
 	}
 
 	/* hstoreArrayToPairs() checked overflow */
-	out_pairs = palloc(sizeof(Pairs) * nkeys);
+	out_pairs = palloc_array(Pairs, nkeys);
 	bufsiz = 0;
 
 	/*
@@ -705,7 +705,7 @@ hstore_akeys(PG_FUNCTION_ARGS)
 		PG_RETURN_POINTER(a);
 	}
 
-	d = (Datum *) palloc(sizeof(Datum) * count);
+	d = palloc_array(Datum, count);
 
 	for (i = 0; i < count; ++i)
 	{
@@ -741,8 +741,8 @@ hstore_avals(PG_FUNCTION_ARGS)
 		PG_RETURN_POINTER(a);
 	}
 
-	d = (Datum *) palloc(sizeof(Datum) * count);
-	nulls = (bool *) palloc(sizeof(bool) * count);
+	d = palloc_array(Datum, count);
+	nulls = palloc_array(bool, count);
 
 	for (i = 0; i < count; ++i)
 	{
@@ -786,8 +786,8 @@ hstore_to_array_internal(HStore *hs, int ndims)
 		return construct_empty_array(TEXTOID);
 
 	out_size[0] = count * 2 / ndims;
-	out_datums = palloc(sizeof(Datum) * count * 2);
-	out_nulls = palloc(sizeof(bool) * count * 2);
+	out_datums = palloc_array(Datum, count * 2);
+	out_nulls = palloc_array(bool, count * 2);
 
 	for (i = 0; i < count; ++i)
 	{
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index 2b2c3f4029e..f45df86d60c 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -135,7 +135,7 @@ gettoken(WORKSTATE *state, int32 *val)
 static void
 pushquery(WORKSTATE *state, int32 type, int32 val)
 {
-	NODE	   *tmp = (NODE *) palloc(sizeof(NODE));
+	NODE	   *tmp = palloc_object(NODE);
 
 	tmp->type = type;
 	tmp->val = val;
@@ -346,7 +346,7 @@ gin_bool_consistent(QUERYTYPE *query, bool *check)
 	 * extraction code in ginint4_queryextract.
 	 */
 	gcv.first = items;
-	gcv.mapped_check = (bool *) palloc(sizeof(bool) * query->size);
+	gcv.mapped_check = palloc_array(bool, query->size);
 	for (i = 0; i < query->size; i++)
 	{
 		if (items[i].type == VAL)
@@ -613,7 +613,7 @@ infix(INFIX *in, bool first)
 
 		nrm.curpol = in->curpol;
 		nrm.buflen = 16;
-		nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+		nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 
 		/* get right operand */
 		infix(&nrm, false);
@@ -651,7 +651,7 @@ bqarr_out(PG_FUNCTION_ARGS)
 
 	nrm.curpol = GETQUERY(query) + query->size - 1;
 	nrm.buflen = 32;
-	nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+	nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 	*(nrm.cur) = '\0';
 	infix(&nrm, true);
 
diff --git a/contrib/intarray/_int_gin.c b/contrib/intarray/_int_gin.c
index b7958d8eca5..c60616c3f77 100644
--- a/contrib/intarray/_int_gin.c
+++ b/contrib/intarray/_int_gin.c
@@ -42,7 +42,7 @@ ginint4_queryextract(PG_FUNCTION_ARGS)
 		/*
 		 * Extract all the VAL items as things we want GIN to check for.
 		 */
-		res = (Datum *) palloc(sizeof(Datum) * query->size);
+		res = palloc_array(Datum, query->size);
 		*nentries = 0;
 
 		for (i = 0; i < query->size; i++)
@@ -65,7 +65,7 @@ ginint4_queryextract(PG_FUNCTION_ARGS)
 			int32	   *arr;
 			int32		i;
 
-			res = (Datum *) palloc(sizeof(Datum) * (*nentries));
+			res = palloc_array(Datum, *nentries);
 
 			arr = ARRPTR(query);
 			for (i = 0; i < *nentries; i++)
diff --git a/contrib/intarray/_int_gist.c b/contrib/intarray/_int_gist.c
index a09b7fa812c..90cf11c01a5 100644
--- a/contrib/intarray/_int_gist.c
+++ b/contrib/intarray/_int_gist.c
@@ -186,7 +186,7 @@ g_int_compress(PG_FUNCTION_ARGS)
 					 errmsg("input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead",
 							2 * num_ranges - 1, ARRNELEMS(r))));
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page, entry->offset, false);
 
@@ -276,7 +276,7 @@ g_int_compress(PG_FUNCTION_ARGS)
 					 errmsg("data is too sparse, recreate index using gist__intbig_ops opclass instead")));
 
 		r = resize_intArrayType(r, len);
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page, entry->offset, false);
 		PG_RETURN_POINTER(retval);
@@ -306,7 +306,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
 	{
 		if (in != (ArrayType *) DatumGetPointer(entry->key))
 		{
-			retval = palloc(sizeof(GISTENTRY));
+			retval = palloc_object(GISTENTRY);
 			gistentryinit(*retval, PointerGetDatum(in),
 						  entry->rel, entry->page, entry->offset, false);
 			PG_RETURN_POINTER(retval);
@@ -321,7 +321,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
 	{							/* not compressed value */
 		if (in != (ArrayType *) DatumGetPointer(entry->key))
 		{
-			retval = palloc(sizeof(GISTENTRY));
+			retval = palloc_object(GISTENTRY);
 			gistentryinit(*retval, PointerGetDatum(in),
 						  entry->rel, entry->page, entry->offset, false);
 
@@ -350,7 +350,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
 
 	if (in != (ArrayType *) DatumGetPointer(entry->key))
 		pfree(in);
-	retval = palloc(sizeof(GISTENTRY));
+	retval = palloc_object(GISTENTRY);
 	gistentryinit(*retval, PointerGetDatum(r),
 				  entry->rel, entry->page, entry->offset, false);
 
@@ -535,7 +535,7 @@ g_int_picksplit(PG_FUNCTION_ARGS)
 	/*
 	 * sort entries
 	 */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
 	{
 		costvector[i - 1].pos = i;
diff --git a/contrib/intarray/_intbig_gist.c b/contrib/intarray/_intbig_gist.c
index 9699fbf3b4f..0afa8a73b68 100644
--- a/contrib/intarray/_intbig_gist.c
+++ b/contrib/intarray/_intbig_gist.c
@@ -174,7 +174,7 @@ g_intbig_compress(PG_FUNCTION_ARGS)
 			ptr++;
 		}
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -195,7 +195,7 @@ g_intbig_compress(PG_FUNCTION_ARGS)
 		}
 
 		res = _intbig_alloc(true, siglen, sign);
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -385,7 +385,7 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 
 	maxoff = OffsetNumberNext(maxoff);
 	/* sort before ... */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/contrib/jsonb_plperl/jsonb_plperl.c b/contrib/jsonb_plperl/jsonb_plperl.c
index c02e2d41af1..a708d9fd82e 100644
--- a/contrib/jsonb_plperl/jsonb_plperl.c
+++ b/contrib/jsonb_plperl/jsonb_plperl.c
@@ -266,7 +266,7 @@ SV_to_JsonbValue(SV *in, JsonbParseState **jsonb_state, bool is_elem)
 	/* Push result into 'jsonb_state' unless it is a raw scalar. */
 	return *jsonb_state
 		? pushJsonbValue(jsonb_state, is_elem ? WJB_ELEM : WJB_VALUE, &out)
-		: memcpy(palloc(sizeof(JsonbValue)), &out, sizeof(JsonbValue));
+		: memcpy(palloc_object(JsonbValue), &out, sizeof(JsonbValue));
 }
 
 
diff --git a/contrib/jsonb_plpython/jsonb_plpython.c b/contrib/jsonb_plpython/jsonb_plpython.c
index 9383615abbf..2892e88c58b 100644
--- a/contrib/jsonb_plpython/jsonb_plpython.c
+++ b/contrib/jsonb_plpython/jsonb_plpython.c
@@ -419,7 +419,7 @@ PLyObject_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state, bool is_ele
 			return PLyMapping_ToJsonbValue(obj, jsonb_state);
 	}
 
-	out = palloc(sizeof(JsonbValue));
+	out = palloc_object(JsonbValue);
 
 	if (obj == Py_None)
 		out->type = jbvNull;
diff --git a/contrib/ltree/_ltree_gist.c b/contrib/ltree/_ltree_gist.c
index 30d516e60bc..ceb92a6304d 100644
--- a/contrib/ltree/_ltree_gist.c
+++ b/contrib/ltree/_ltree_gist.c
@@ -79,7 +79,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
 			item = NEXTVAL(item);
 		}
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -97,7 +97,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
 		}
 
 		key = ltree_gist_alloc(true, sign, siglen, NULL, NULL);
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -310,7 +310,7 @@ _ltree_picksplit(PG_FUNCTION_ARGS)
 
 	maxoff = OffsetNumberNext(maxoff);
 	/* sort before ... */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/contrib/ltree/_ltree_op.c b/contrib/ltree/_ltree_op.c
index b4a8097328d..4d54ad34bb6 100644
--- a/contrib/ltree/_ltree_op.c
+++ b/contrib/ltree/_ltree_op.c
@@ -307,7 +307,7 @@ _lca(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 				 errmsg("array must not contain nulls")));
 
-	a = (ltree **) palloc(sizeof(ltree *) * num);
+	a = palloc_array(ltree *, num);
 	while (num > 0)
 	{
 		num--;
diff --git a/contrib/ltree/ltree_gist.c b/contrib/ltree/ltree_gist.c
index 932f69bff2d..bb7f4634722 100644
--- a/contrib/ltree/ltree_gist.c
+++ b/contrib/ltree/ltree_gist.c
@@ -101,7 +101,7 @@ ltree_compress(PG_FUNCTION_ARGS)
 		ltree	   *val = DatumGetLtreeP(entry->key);
 		ltree_gist *key = ltree_gist_alloc(false, NULL, 0, val, 0);
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -117,7 +117,7 @@ ltree_decompress(PG_FUNCTION_ARGS)
 
 	if (PointerGetDatum(key) != entry->key)
 	{
-		GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
@@ -318,7 +318,7 @@ ltree_picksplit(PG_FUNCTION_ARGS)
 	v->spl_right = (OffsetNumber *) palloc(nbytes);
 	v->spl_nleft = 0;
 	v->spl_nright = 0;
-	array = (RIX *) palloc(sizeof(RIX) * (maxoff + 1));
+	array = palloc_array(RIX, maxoff + 1);
 
 	/* copy the data into RIXes, and sort the RIXes */
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
diff --git a/contrib/ltree/ltree_io.c b/contrib/ltree/ltree_io.c
index b54a15d6c68..59c4462df80 100644
--- a/contrib/ltree/ltree_io.c
+++ b/contrib/ltree/ltree_io.c
@@ -65,7 +65,7 @@ parse_ltree(const char *buf, struct Node *escontext)
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("number of ltree labels (%d) exceeds the maximum allowed (%d)",
 						num + 1, LTREE_MAX_LEVELS)));
-	list = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (num + 1));
+	list = lptr = palloc_array(nodeitem, num + 1);
 	ptr = buf;
 	while (*ptr)
 	{
@@ -318,14 +318,14 @@ parse_lquery(const char *buf, struct Node *escontext)
 			case LQPRS_WAITLEVEL:
 				if (ISLABEL(ptr))
 				{
-					GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
+					GETVAR(curqlevel) = lptr = palloc0_array(nodeitem, numOR + 1);
 					lptr->start = ptr;
 					state = LQPRS_WAITDELIM;
 					curqlevel->numvar = 1;
 				}
 				else if (t_iseq(ptr, '!'))
 				{
-					GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
+					GETVAR(curqlevel) = lptr = palloc0_array(nodeitem, numOR + 1);
 					lptr->start = ptr + 1;
 					lptr->wlen = -1;	/* compensate for counting ! below */
 					state = LQPRS_WAITDELIM;
diff --git a/contrib/ltree/ltree_op.c b/contrib/ltree/ltree_op.c
index e3a84db37ff..c1fc77fc804 100644
--- a/contrib/ltree/ltree_op.c
+++ b/contrib/ltree/ltree_op.c
@@ -566,7 +566,7 @@ lca(PG_FUNCTION_ARGS)
 	ltree	  **a,
 			   *res;
 
-	a = (ltree **) palloc(sizeof(ltree *) * fcinfo->nargs);
+	a = palloc_array(ltree *, fcinfo->nargs);
 	for (i = 0; i < fcinfo->nargs; i++)
 		a[i] = PG_GETARG_LTREE_P(i);
 	res = lca_inner(a, (int) fcinfo->nargs);
diff --git a/contrib/ltree/ltxtquery_io.c b/contrib/ltree/ltxtquery_io.c
index ec331607793..3a2aa223c3e 100644
--- a/contrib/ltree/ltxtquery_io.c
+++ b/contrib/ltree/ltxtquery_io.c
@@ -154,7 +154,7 @@ gettoken_query(QPRS_STATE *state, int32 *val, int32 *lenval, char **strval, uint
 static bool
 pushquery(QPRS_STATE *state, int32 type, int32 val, int32 distance, int32 lenval, uint16 flag)
 {
-	NODE	   *tmp = (NODE *) palloc(sizeof(NODE));
+	NODE	   *tmp = palloc_object(NODE);
 
 	tmp->type = type;
 	tmp->val = val;
@@ -543,7 +543,7 @@ infix(INFIX *in, bool first)
 		nrm.curpol = in->curpol;
 		nrm.op = in->op;
 		nrm.buflen = 16;
-		nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+		nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 
 		/* get right operand */
 		infix(&nrm, false);
@@ -582,7 +582,7 @@ ltxtq_out(PG_FUNCTION_ARGS)
 
 	nrm.curpol = GETQUERY(query);
 	nrm.buflen = 32;
-	nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+	nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 	*(nrm.cur) = '\0';
 	nrm.op = GETOPERAND(query);
 	infix(&nrm, true);
@@ -615,7 +615,7 @@ ltxtq_send(PG_FUNCTION_ARGS)
 
 	nrm.curpol = GETQUERY(query);
 	nrm.buflen = 32;
-	nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+	nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 	*(nrm.cur) = '\0';
 	nrm.op = GETOPERAND(query);
 	infix(&nrm, true);
diff --git a/contrib/pageinspect/brinfuncs.c b/contrib/pageinspect/brinfuncs.c
index 990c965aa92..c5cebcd280b 100644
--- a/contrib/pageinspect/brinfuncs.c
+++ b/contrib/pageinspect/brinfuncs.c
@@ -186,7 +186,7 @@ brin_page_items(PG_FUNCTION_ARGS)
 	 * Initialize output functions for all indexed datatypes; simplifies
 	 * calling them later.
 	 */
-	columns = palloc(sizeof(brin_column_state *) * RelationGetDescr(indexRel)->natts);
+	columns = palloc_array(brin_column_state *, RelationGetDescr(indexRel)->natts); 
 	for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 	{
 		Oid			output;
diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c
index 2e67c9adf5a..7ff6dc08934 100644
--- a/contrib/pageinspect/btreefuncs.c
+++ b/contrib/pageinspect/btreefuncs.c
@@ -379,7 +379,7 @@ bt_multi_page_stats(PG_FUNCTION_ARGS)
 		/* Save arguments for reuse */
 		mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
 
-		uargs = palloc(sizeof(ua_page_stats));
+		uargs = palloc_object(ua_page_stats);
 
 		uargs->relid = RelationGetRelid(rel);
 		uargs->blkno = blkno;
@@ -660,7 +660,7 @@ bt_page_items_internal(PG_FUNCTION_ARGS, enum pageinspect_version ext_version)
 		 */
 		mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
 
-		uargs = palloc(sizeof(ua_page_items));
+		uargs = palloc_object(ua_page_items);
 
 		uargs->page = palloc(BLCKSZ);
 		memcpy(uargs->page, BufferGetPage(buffer), BLCKSZ);
@@ -752,7 +752,7 @@ bt_page_items_bytea(PG_FUNCTION_ARGS)
 		fctx = SRF_FIRSTCALL_INIT();
 		mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
 
-		uargs = palloc(sizeof(ua_page_items));
+		uargs = palloc_object(ua_page_items);
 
 		uargs->page = get_page_from_raw(raw_page);
 
diff --git a/contrib/pageinspect/ginfuncs.c b/contrib/pageinspect/ginfuncs.c
index 09a90957081..f6168d8e895 100644
--- a/contrib/pageinspect/ginfuncs.c
+++ b/contrib/pageinspect/ginfuncs.c
@@ -222,7 +222,7 @@ gin_leafpage_items(PG_FUNCTION_ARGS)
 							   opaq->flags,
 							   (GIN_DATA | GIN_LEAF | GIN_COMPRESSED))));
 
-		inter_call_data = palloc(sizeof(gin_leafpage_items_state));
+		inter_call_data = palloc_object(gin_leafpage_items_state);
 
 		/* Build a tuple descriptor for our result type */
 		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
diff --git a/contrib/pageinspect/hashfuncs.c b/contrib/pageinspect/hashfuncs.c
index ca7f1f6e741..0e898889fa5 100644
--- a/contrib/pageinspect/hashfuncs.c
+++ b/contrib/pageinspect/hashfuncs.c
@@ -325,7 +325,7 @@ hash_page_items(PG_FUNCTION_ARGS)
 
 		page = verify_hash_page(raw_page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
 
-		uargs = palloc(sizeof(struct user_args));
+		uargs = palloc_object(struct user_args);
 
 		uargs->page = page;
 
diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c
index c13f07655c4..b38c4d159f6 100644
--- a/contrib/pageinspect/heapfuncs.c
+++ b/contrib/pageinspect/heapfuncs.c
@@ -154,7 +154,7 @@ heap_page_items(PG_FUNCTION_ARGS)
 		fctx = SRF_FIRSTCALL_INIT();
 		mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
 
-		inter_call_data = palloc(sizeof(heap_page_items_state));
+		inter_call_data = palloc_object(heap_page_items_state);
 
 		/* Build a tuple descriptor for our result type */
 		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
@@ -553,7 +553,7 @@ heap_tuple_infomask_flags(PG_FUNCTION_ARGS)
 	}
 
 	/* build set of raw flags */
-	flags = (Datum *) palloc0(sizeof(Datum) * bitcnt);
+	flags = palloc0_array(Datum, bitcnt); 
 
 	/* decode t_infomask */
 	if ((t_infomask & HEAP_HASNULL) != 0)
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index ae1712fc93c..f0d48d1ac83 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -128,7 +128,7 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* Create a user function context for cross-call persistence */
-		fctx = (BufferCachePagesContext *) palloc(sizeof(BufferCachePagesContext));
+		fctx = palloc_object(BufferCachePagesContext);
 
 		/*
 		 * To smoothly support upgrades from version 1.0 of this extension
@@ -376,8 +376,8 @@ pg_buffercache_os_pages_internal(FunctionCallInfo fcinfo, bool include_numa)
 			os_page_count = (endptr - startptr) / os_page_size;
 
 			/* Used to determine the NUMA node for all OS pages at once */
-			os_page_ptrs = palloc0(sizeof(void *) * os_page_count);
-			os_page_status = palloc(sizeof(uint64) * os_page_count);
+			os_page_ptrs = palloc0_array(void *, os_page_count);
+			os_page_status = palloc_array(int, os_page_count);
 
 			/*
 			 * Fill pointers for all the memory pages.  This loop stores and
@@ -419,7 +419,7 @@ pg_buffercache_os_pages_internal(FunctionCallInfo fcinfo, bool include_numa)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* Create a user function context for cross-call persistence */
-		fctx = (BufferCacheOsPagesContext *) palloc(sizeof(BufferCacheOsPagesContext));
+		fctx = palloc_object(BufferCacheOsPagesContext);
 
 		if (get_call_result_type(fcinfo, NULL, &expected_tupledesc) != TYPEFUNC_COMPOSITE)
 			elog(ERROR, "return type must be a row type");
diff --git a/contrib/pg_overexplain/pg_overexplain.c b/contrib/pg_overexplain/pg_overexplain.c
index bd70b6d9d5e..fcdc17012da 100644
--- a/contrib/pg_overexplain/pg_overexplain.c
+++ b/contrib/pg_overexplain/pg_overexplain.c
@@ -95,7 +95,7 @@ overexplain_ensure_options(ExplainState *es)
 
 	if (options == NULL)
 	{
-		options = palloc0(sizeof(overexplain_options));
+		options = palloc0_object(overexplain_options);
 		SetExplainExtensionState(es, es_extension_id, options);
 	}
 
diff --git a/contrib/pg_trgm/trgm_gin.c b/contrib/pg_trgm/trgm_gin.c
index 29a52eac7af..34a91cf9789 100644
--- a/contrib/pg_trgm/trgm_gin.c
+++ b/contrib/pg_trgm/trgm_gin.c
@@ -51,7 +51,7 @@ gin_extract_value_trgm(PG_FUNCTION_ARGS)
 		int32		i;
 
 		*nentries = trglen;
-		entries = (Datum *) palloc(sizeof(Datum) * trglen);
+		entries = palloc_array(Datum, trglen);
 
 		ptr = GETARR(trg);
 		for (i = 0; i < trglen; i++)
@@ -123,7 +123,7 @@ gin_extract_query_trgm(PG_FUNCTION_ARGS)
 				 * Pointers, but we just put the same value in each element.
 				 */
 				trglen = ARRNELEM(trg);
-				*extra_data = (Pointer *) palloc(sizeof(Pointer) * trglen);
+				*extra_data = palloc_array(Pointer, trglen);
 				for (i = 0; i < trglen; i++)
 					(*extra_data)[i] = (Pointer) graph;
 			}
@@ -146,7 +146,7 @@ gin_extract_query_trgm(PG_FUNCTION_ARGS)
 
 	if (trglen > 0)
 	{
-		entries = (Datum *) palloc(sizeof(Datum) * trglen);
+		entries = palloc_array(Datum, trglen);
 		ptr = GETARR(trg);
 		for (i = 0; i < trglen; i++)
 		{
@@ -339,7 +339,7 @@ gin_trgm_triconsistent(PG_FUNCTION_ARGS)
 				 * function, promoting all GIN_MAYBE keys to GIN_TRUE will
 				 * give a conservative result.
 				 */
-				boolcheck = (bool *) palloc(sizeof(bool) * nkeys);
+				boolcheck = palloc_array(bool, nkeys);
 				for (i = 0; i < nkeys; i++)
 					boolcheck[i] = (check[i] != GIN_FALSE);
 				if (!trigramsMatchGraph((TrgmPackedGraph *) extra_data[0],
diff --git a/contrib/pg_trgm/trgm_gist.c b/contrib/pg_trgm/trgm_gist.c
index 5ba895217b0..5c7deb103a6 100644
--- a/contrib/pg_trgm/trgm_gist.c
+++ b/contrib/pg_trgm/trgm_gist.c
@@ -124,7 +124,7 @@ gtrgm_compress(PG_FUNCTION_ARGS)
 		text	   *val = DatumGetTextPP(entry->key);
 
 		res = generate_trgm(VARDATA_ANY(val), VARSIZE_ANY_EXHDR(val));
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -143,7 +143,7 @@ gtrgm_compress(PG_FUNCTION_ARGS)
 		}
 
 		res = gtrgm_alloc(true, siglen, sign);
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -163,7 +163,7 @@ gtrgm_decompress(PG_FUNCTION_ARGS)
 	if (key != (text *) DatumGetPointer(entry->key))
 	{
 		/* need to pass back the decompressed item */
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page, entry->offset, entry->leafkey);
 		PG_RETURN_POINTER(retval);
@@ -820,7 +820,7 @@ gtrgm_picksplit(PG_FUNCTION_ARGS)
 	SPLITCOST  *costvector;
 
 	/* cache the sign data for each existing item */
-	cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 1));
+	cache = palloc_array(CACHESIGN, maxoff + 1);
 	cache_sign = palloc(siglen * (maxoff + 1));
 
 	for (k = FirstOffsetNumber; k <= maxoff; k = OffsetNumberNext(k))
@@ -864,7 +864,7 @@ gtrgm_picksplit(PG_FUNCTION_ARGS)
 	union_r = GETSIGN(datum_r);
 
 	/* sort before ... */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c
index 29b39ec8a4c..bd4a924612d 100644
--- a/contrib/pg_trgm/trgm_op.c
+++ b/contrib/pg_trgm/trgm_op.c
@@ -452,7 +452,7 @@ make_positional_trgm(trgm *trg1, int len1, trgm *trg2, int len2)
 	int			i,
 				len = len1 + len2;
 
-	result = (pos_trgm *) palloc(sizeof(pos_trgm) * len);
+	result = palloc_array(pos_trgm, len);
 
 	for (i = 0; i < len1; i++)
 	{
@@ -535,7 +535,7 @@ iterate_word_similarity(int *trg2indexes,
 	lower = (flags & WORD_SIMILARITY_STRICT) ? 0 : -1;
 
 	/* Memorise last position of each trigram */
-	lastpos = (int *) palloc(sizeof(int) * len);
+	lastpos = palloc_array(int, len);
 	memset(lastpos, -1, sizeof(int) * len);
 
 	for (i = 0; i < len2; i++)
@@ -690,10 +690,10 @@ calc_word_similarity(char *str1, int slen1, char *str2, int slen2,
 	protect_out_of_mem(slen1 + slen2);
 
 	/* Make positional trigrams */
-	trg1 = (trgm *) palloc(sizeof(trgm) * (slen1 / 2 + 1) * 3);
-	trg2 = (trgm *) palloc(sizeof(trgm) * (slen2 / 2 + 1) * 3);
+	trg1 = palloc_array(trgm, (slen1 / 2 + 1) * 3);
+	trg2 = palloc_array(trgm, (slen2 / 2 + 1) * 3);
 	if (flags & WORD_SIMILARITY_STRICT)
-		bounds = (TrgmBound *) palloc0(sizeof(TrgmBound) * (slen2 / 2 + 1) * 3);
+		bounds = palloc0_array(TrgmBound, (slen2 / 2 + 1) * 3);
 	else
 		bounds = NULL;
 
@@ -711,8 +711,8 @@ calc_word_similarity(char *str1, int slen1, char *str2, int slen2,
 	 * Merge positional trigrams array: enumerate each trigram and find its
 	 * presence in required word.
 	 */
-	trg2indexes = (int *) palloc(sizeof(int) * len2);
-	found = (bool *) palloc0(sizeof(bool) * len);
+	trg2indexes = palloc_array(int, len2);
+	found = palloc0_array(bool, len);
 
 	ulen1 = 0;
 	j = 0;
@@ -938,7 +938,7 @@ generate_wildcard_trgm(const char *str, int slen)
 	tptr = GETARR(trg);
 
 	/* Allocate a buffer for blank-padded, but not yet case-folded, words */
-	buf = palloc(sizeof(char) * (slen + 4));
+	buf = palloc_array(char, slen + 4);
 
 	/*
 	 * Extract trigrams from each substring extracted by get_wildcard_part.
@@ -1008,7 +1008,7 @@ show_trgm(PG_FUNCTION_ARGS)
 	int			i;
 
 	trg = generate_trgm(VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
-	d = (Datum *) palloc(sizeof(Datum) * (1 + ARRNELEM(trg)));
+	d = palloc_array(Datum, ARRNELEM(trg) + 1);
 
 	for (i = 0, ptr = GETARR(trg); i < ARRNELEM(trg); i++, ptr++)
 	{
@@ -1136,7 +1136,7 @@ trgm_presence_map(TRGM *query, TRGM *key)
 				lenk = ARRNELEM(key),
 				i;
 
-	result = (bool *) palloc0(lenq * sizeof(bool));
+	result = palloc0_array(bool, lenq);
 
 	/* for each query trigram, do a binary search in the key array */
 	for (i = 0; i < lenq; i++)
diff --git a/contrib/pg_trgm/trgm_regexp.c b/contrib/pg_trgm/trgm_regexp.c
index 149f9eb259c..1a76794c422 100644
--- a/contrib/pg_trgm/trgm_regexp.c
+++ b/contrib/pg_trgm/trgm_regexp.c
@@ -791,12 +791,11 @@ getColorInfo(regex_t *regex, TrgmNFA *trgmNFA)
 
 		colorInfo->expandable = true;
 		colorInfo->containsNonWord = false;
-		colorInfo->wordChars = (trgm_mb_char *)
-			palloc(sizeof(trgm_mb_char) * charsCount);
+		colorInfo->wordChars = palloc_array(trgm_mb_char, charsCount);
 		colorInfo->wordCharsCount = 0;
 
 		/* Extract all the chars in this color */
-		chars = (pg_wchar *) palloc(sizeof(pg_wchar) * charsCount);
+		chars = palloc_array(pg_wchar, charsCount);
 		pg_reg_getcharacters(regex, i, chars, charsCount);
 
 		/*
@@ -1063,7 +1062,7 @@ addKey(TrgmNFA *trgmNFA, TrgmState *state, TrgmStateKey *key)
 	 * original NFA.
 	 */
 	arcsCount = pg_reg_getnumoutarcs(trgmNFA->regex, key->nstate);
-	arcs = (regex_arc_t *) palloc(sizeof(regex_arc_t) * arcsCount);
+	arcs = palloc_array(regex_arc_t, arcsCount);
 	pg_reg_getoutarcs(trgmNFA->regex, key->nstate, arcs, arcsCount);
 
 	for (i = 0; i < arcsCount; i++)
@@ -1177,7 +1176,7 @@ addKey(TrgmNFA *trgmNFA, TrgmState *state, TrgmStateKey *key)
 static void
 addKeyToQueue(TrgmNFA *trgmNFA, TrgmStateKey *key)
 {
-	TrgmStateKey *keyCopy = (TrgmStateKey *) palloc(sizeof(TrgmStateKey));
+	TrgmStateKey *keyCopy = palloc_object(TrgmStateKey);
 
 	memcpy(keyCopy, key, sizeof(TrgmStateKey));
 	trgmNFA->keysQueue = lappend(trgmNFA->keysQueue, keyCopy);
@@ -1215,7 +1214,7 @@ addArcs(TrgmNFA *trgmNFA, TrgmState *state)
 		TrgmStateKey *key = (TrgmStateKey *) lfirst(cell);
 
 		arcsCount = pg_reg_getnumoutarcs(trgmNFA->regex, key->nstate);
-		arcs = (regex_arc_t *) palloc(sizeof(regex_arc_t) * arcsCount);
+		arcs = palloc_array(regex_arc_t, arcsCount);
 		pg_reg_getoutarcs(trgmNFA->regex, key->nstate, arcs, arcsCount);
 
 		for (i = 0; i < arcsCount; i++)
@@ -1311,7 +1310,7 @@ addArc(TrgmNFA *trgmNFA, TrgmState *state, TrgmStateKey *key,
 	}
 
 	/* Checks were successful, add new arc */
-	arc = (TrgmArc *) palloc(sizeof(TrgmArc));
+	arc = palloc_object(TrgmArc);
 	arc->target = getState(trgmNFA, destKey);
 	arc->ctrgm.colors[0] = key->prefix.colors[0];
 	arc->ctrgm.colors[1] = key->prefix.colors[1];
@@ -1467,7 +1466,7 @@ selectColorTrigrams(TrgmNFA *trgmNFA)
 	int			cnumber;
 
 	/* Collect color trigrams from all arcs */
-	colorTrgms = (ColorTrgmInfo *) palloc0(sizeof(ColorTrgmInfo) * arcsCount);
+	colorTrgms = palloc0_array(ColorTrgmInfo, arcsCount);
 	trgmNFA->colorTrgms = colorTrgms;
 
 	i = 0;
@@ -1479,7 +1478,7 @@ selectColorTrigrams(TrgmNFA *trgmNFA)
 		foreach(cell, state->arcs)
 		{
 			TrgmArc    *arc = (TrgmArc *) lfirst(cell);
-			TrgmArcInfo *arcInfo = (TrgmArcInfo *) palloc(sizeof(TrgmArcInfo));
+			TrgmArcInfo *arcInfo = palloc_object(TrgmArcInfo);
 			ColorTrgmInfo *trgmInfo = &colorTrgms[i];
 
 			arcInfo->source = state;
@@ -1964,8 +1963,7 @@ packGraph(TrgmNFA *trgmNFA, MemoryContext rcontext)
 	}
 
 	/* Collect array of all arcs */
-	arcs = (TrgmPackArcInfo *)
-		palloc(sizeof(TrgmPackArcInfo) * trgmNFA->arcsCount);
+	arcs = palloc_array(TrgmPackArcInfo, trgmNFA->arcsCount);
 	arcIndex = 0;
 	hash_seq_init(&scan_status, trgmNFA->states);
 	while ((state = (TrgmState *) hash_seq_search(&scan_status)) != NULL)
@@ -2147,7 +2145,7 @@ printSourceNFA(regex_t *regex, TrgmColorInfo *colors, int ncolors)
 		appendStringInfoString(&buf, ";\n");
 
 		arcsCount = pg_reg_getnumoutarcs(regex, state);
-		arcs = (regex_arc_t *) palloc(sizeof(regex_arc_t) * arcsCount);
+		arcs = palloc_array(regex_arc_t, arcsCount);
 		pg_reg_getoutarcs(regex, state, arcs, arcsCount);
 
 		for (i = 0; i < arcsCount; i++)
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index d79ef35006b..7046c1b5f8e 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -741,7 +741,7 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
 	 * number of entries allocated.  We'll repurpose these fields before
 	 * returning.
 	 */
-	items = palloc0(sizeof(corrupt_items));
+	items = palloc0_object(corrupt_items);
 	items->next = 0;
 	items->count = 64;
 	items->tids = palloc(items->count * sizeof(ItemPointerData));
diff --git a/contrib/pg_walinspect/pg_walinspect.c b/contrib/pg_walinspect/pg_walinspect.c
index 3c5e4a856a7..6945bac1306 100644
--- a/contrib/pg_walinspect/pg_walinspect.c
+++ b/contrib/pg_walinspect/pg_walinspect.c
@@ -109,8 +109,7 @@ InitXLogReaderState(XLogRecPtr lsn)
 				 errmsg("could not read WAL at LSN %X/%08X",
 						LSN_FORMAT_ARGS(lsn))));
 
-	private_data = (ReadLocalXLogPageNoWaitPrivate *)
-		palloc0(sizeof(ReadLocalXLogPageNoWaitPrivate));
+	private_data = palloc0_object(ReadLocalXLogPageNoWaitPrivate);
 
 	xlogreader = XLogReaderAllocate(wal_segment_size, NULL,
 									XL_ROUTINE(.page_read = &read_local_xlog_page_no_wait,
@@ -310,7 +309,7 @@ GetWALBlockInfo(FunctionCallInfo fcinfo, XLogReaderState *record,
 			/* Construct and save block_fpi_info */
 			bitcnt = pg_popcount((const char *) &blk->bimg_info,
 								 sizeof(uint8));
-			flags = (Datum *) palloc0(sizeof(Datum) * bitcnt);
+			flags = palloc0_array(Datum, bitcnt);
 			if ((blk->bimg_info & BKPIMAGE_HAS_HOLE) != 0)
 				flags[cnt++] = CStringGetTextDatum("HAS_HOLE");
 			if (blk->apply_image)
diff --git a/contrib/pgcrypto/mbuf.c b/contrib/pgcrypto/mbuf.c
index 99f8957b004..054b5599d07 100644
--- a/contrib/pgcrypto/mbuf.c
+++ b/contrib/pgcrypto/mbuf.c
@@ -115,7 +115,7 @@ mbuf_create(int len)
 	if (!len)
 		len = 8192;
 
-	mbuf = palloc(sizeof *mbuf);
+	mbuf = palloc_object(MBuf);
 	mbuf->data = palloc(len);
 	mbuf->buf_end = mbuf->data + len;
 	mbuf->data_end = mbuf->data;
@@ -132,7 +132,7 @@ mbuf_create_from_data(uint8 *data, int len)
 {
 	MBuf	   *mbuf;
 
-	mbuf = palloc(sizeof *mbuf);
+	mbuf = palloc_object(MBuf);
 	mbuf->data = (uint8 *) data;
 	mbuf->buf_end = mbuf->data + len;
 	mbuf->data_end = mbuf->data + len;
@@ -206,7 +206,7 @@ pullf_create(PullFilter **pf_p, const PullFilterOps *op, void *init_arg, PullFil
 		res = 0;
 	}
 
-	pf = palloc0(sizeof(*pf));
+	pf = palloc0_object(PullFilter);
 	pf->buflen = res;
 	pf->op = op;
 	pf->priv = priv;
@@ -372,7 +372,7 @@ pushf_create(PushFilter **mp_p, const PushFilterOps *op, void *init_arg, PushFil
 		res = 0;
 	}
 
-	mp = palloc0(sizeof(*mp));
+	mp = palloc0_object(PushFilter);
 	mp->block_size = res;
 	mp->op = op;
 	mp->priv = priv;
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index f179e80c842..d3c12e7fda3 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -197,7 +197,7 @@ px_find_digest(const char *name, PX_MD **res)
 	ResourceOwnerRememberOSSLDigest(digest->owner, digest);
 
 	/* The PX_MD object is allocated in the current memory context. */
-	h = palloc(sizeof(*h));
+	h = palloc_object(PX_MD);
 	h->result_size = digest_result_size;
 	h->block_size = digest_block_size;
 	h->reset = digest_reset;
@@ -813,7 +813,7 @@ px_find_cipher(const char *name, PX_Cipher **res)
 		od->evp_ciph = i->ciph->cipher_func();
 
 	/* The PX_Cipher is allocated in current memory context */
-	c = palloc(sizeof(*c));
+	c = palloc_object(PX_Cipher);
 	c->block_size = gen_ossl_block_size;
 	c->key_size = gen_ossl_key_size;
 	c->iv_size = gen_ossl_iv_size;
diff --git a/contrib/pgcrypto/pgp-cfb.c b/contrib/pgcrypto/pgp-cfb.c
index de41e825b0c..d8f1afc3aba 100644
--- a/contrib/pgcrypto/pgp-cfb.c
+++ b/contrib/pgcrypto/pgp-cfb.c
@@ -67,7 +67,7 @@ pgp_cfb_create(PGP_CFB **ctx_p, int algo, const uint8 *key, int key_len,
 		return res;
 	}
 
-	ctx = palloc0(sizeof(*ctx));
+	ctx = palloc0_object(PGP_CFB);
 	ctx->ciph = ciph;
 	ctx->block_size = px_cipher_block_size(ciph);
 	ctx->resync = resync;
diff --git a/contrib/pgcrypto/pgp-compress.c b/contrib/pgcrypto/pgp-compress.c
index 961cf21e748..caa80ecdb45 100644
--- a/contrib/pgcrypto/pgp-compress.c
+++ b/contrib/pgcrypto/pgp-compress.c
@@ -80,7 +80,7 @@ compress_init(PushFilter *next, void *init_arg, void **priv_p)
 	/*
 	 * init
 	 */
-	st = palloc0(sizeof(*st));
+	st = palloc0_object(struct ZipStat);
 	st->buf_len = ZIP_OUT_BUF;
 	st->stream.zalloc = z_alloc;
 	st->stream.zfree = z_free;
@@ -211,7 +211,7 @@ decompress_init(void **priv_p, void *arg, PullFilter *src)
 		&& ctx->compress_algo != PGP_COMPR_ZIP)
 		return PXE_PGP_UNSUPPORTED_COMPR;
 
-	dec = palloc0(sizeof(*dec));
+	dec = palloc0_object(struct DecomprData);
 	dec->buf_len = ZIP_OUT_BUF;
 	*priv_p = dec;
 
diff --git a/contrib/pgcrypto/pgp-decrypt.c b/contrib/pgcrypto/pgp-decrypt.c
index e1ea5b3e58d..52ca7840c6d 100644
--- a/contrib/pgcrypto/pgp-decrypt.c
+++ b/contrib/pgcrypto/pgp-decrypt.c
@@ -224,7 +224,7 @@ pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
 					  int pkttype, PGP_Context *ctx)
 {
 	int			res;
-	struct PktData *pkt = palloc(sizeof(*pkt));
+	struct PktData *pkt = palloc_object(struct PktData);
 
 	pkt->type = pkttype;
 	pkt->len = len;
@@ -448,7 +448,7 @@ mdcbuf_init(void **priv_p, void *arg, PullFilter *src)
 	PGP_Context *ctx = arg;
 	struct MDCBufData *st;
 
-	st = palloc0(sizeof(*st));
+	st = palloc0_object(struct MDCBufData);
 	st->buflen = sizeof(st->buf);
 	st->ctx = ctx;
 	*priv_p = st;
diff --git a/contrib/pgcrypto/pgp-encrypt.c b/contrib/pgcrypto/pgp-encrypt.c
index f7467c9b1cb..2c059804706 100644
--- a/contrib/pgcrypto/pgp-encrypt.c
+++ b/contrib/pgcrypto/pgp-encrypt.c
@@ -178,7 +178,7 @@ encrypt_init(PushFilter *next, void *init_arg, void **priv_p)
 	if (res < 0)
 		return res;
 
-	st = palloc0(sizeof(*st));
+	st = palloc0_object(struct EncStat);
 	st->ciph = ciph;
 
 	*priv_p = st;
@@ -240,7 +240,7 @@ pkt_stream_init(PushFilter *next, void *init_arg, void **priv_p)
 {
 	struct PktStreamStat *st;
 
-	st = palloc(sizeof(*st));
+	st = palloc_object(struct PktStreamStat);
 	st->final_done = 0;
 	st->pkt_block = 1 << STREAM_BLOCK_SHIFT;
 	*priv_p = st;
diff --git a/contrib/pgcrypto/pgp-pgsql.c b/contrib/pgcrypto/pgp-pgsql.c
index 7c9f4c7b39b..8cfb1f60f08 100644
--- a/contrib/pgcrypto/pgp-pgsql.c
+++ b/contrib/pgcrypto/pgp-pgsql.c
@@ -782,8 +782,8 @@ parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
 				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 				 errmsg("mismatched array dimensions")));
 
-	keys = (char **) palloc(sizeof(char *) * key_count);
-	values = (char **) palloc(sizeof(char *) * val_count);
+	keys = (char **) palloc_array(char *, key_count);
+	values = (char **) palloc_array(char *, val_count);
 
 	for (i = 0; i < key_count; i++)
 	{
@@ -937,7 +937,7 @@ pgp_armor_headers(PG_FUNCTION_ARGS)
 		attinmeta = TupleDescGetAttInMetadata(tupdesc);
 		funcctx->attinmeta = attinmeta;
 
-		state = (pgp_armor_headers_state *) palloc(sizeof(pgp_armor_headers_state));
+		state = palloc_object(pgp_armor_headers_state);
 
 		res = pgp_extract_armor_headers((uint8 *) VARDATA_ANY(data),
 										VARSIZE_ANY_EXHDR(data),
diff --git a/contrib/pgcrypto/pgp-pubkey.c b/contrib/pgcrypto/pgp-pubkey.c
index 9a6561caf9d..6f118865917 100644
--- a/contrib/pgcrypto/pgp-pubkey.c
+++ b/contrib/pgcrypto/pgp-pubkey.c
@@ -39,7 +39,7 @@ pgp_key_alloc(PGP_PubKey **pk_p)
 {
 	PGP_PubKey *pk;
 
-	pk = palloc0(sizeof(*pk));
+	pk = palloc0_object(PGP_PubKey);
 	*pk_p = pk;
 	return 0;
 }
diff --git a/contrib/pgcrypto/px-hmac.c b/contrib/pgcrypto/px-hmac.c
index 99174d26551..68e5cff6d6a 100644
--- a/contrib/pgcrypto/px-hmac.c
+++ b/contrib/pgcrypto/px-hmac.c
@@ -157,7 +157,7 @@ px_find_hmac(const char *name, PX_HMAC **res)
 		return PXE_HASH_UNUSABLE_FOR_HMAC;
 	}
 
-	h = palloc(sizeof(*h));
+	h = palloc_object(PX_HMAC);
 	h->p.ipad = palloc(bs);
 	h->p.opad = palloc(bs);
 	h->md = md;
diff --git a/contrib/pgcrypto/px.c b/contrib/pgcrypto/px.c
index d35ccca7774..4d668d4e496 100644
--- a/contrib/pgcrypto/px.c
+++ b/contrib/pgcrypto/px.c
@@ -291,7 +291,7 @@ px_find_combo(const char *name, PX_Combo **res)
 
 	PX_Combo   *cx;
 
-	cx = palloc0(sizeof(*cx));
+	cx = palloc0_object(PX_Combo);
 	buf = pstrdup(name);
 
 	err = parse_cipher_name(buf, &s_cipher, &s_pad);
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 06b52c65300..b293a7904fb 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -633,7 +633,7 @@ postgresGetForeignRelSize(PlannerInfo *root,
 	 * We use PgFdwRelationInfo to pass various information to subsequent
 	 * functions.
 	 */
-	fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
+	fpinfo = palloc0_object(PgFdwRelationInfo);
 	baserel->fdw_private = fpinfo;
 
 	/* Base foreign tables need to be pushed down always. */
@@ -1517,7 +1517,7 @@ postgresBeginForeignScan(ForeignScanState *node, int eflags)
 	/*
 	 * We'll save private state in node->fdw_state.
 	 */
-	fsstate = (PgFdwScanState *) palloc0(sizeof(PgFdwScanState));
+	fsstate = palloc0_object(PgFdwScanState);
 	node->fdw_state = fsstate;
 
 	/*
@@ -2663,7 +2663,7 @@ postgresBeginDirectModify(ForeignScanState *node, int eflags)
 	/*
 	 * We'll save private state in node->fdw_state.
 	 */
-	dmstate = (PgFdwDirectModifyState *) palloc0(sizeof(PgFdwDirectModifyState));
+	dmstate = palloc0_object(PgFdwDirectModifyState);
 	node->fdw_state = dmstate;
 
 	/*
@@ -3977,7 +3977,7 @@ create_foreign_modify(EState *estate,
 	ListCell   *lc;
 
 	/* Begin constructing PgFdwModifyState. */
-	fmstate = (PgFdwModifyState *) palloc0(sizeof(PgFdwModifyState));
+	fmstate = palloc0_object(PgFdwModifyState);
 	fmstate->rel = rel;
 
 	/* Identify which user to do the remote access as. */
@@ -4014,7 +4014,7 @@ create_foreign_modify(EState *estate,
 
 	/* Prepare for output conversion of parameters used in prepared stmt. */
 	n_params = list_length(fmstate->target_attrs) + 1;
-	fmstate->p_flinfo = (FmgrInfo *) palloc0(sizeof(FmgrInfo) * n_params);
+	fmstate->p_flinfo = palloc0_array(FmgrInfo, n_params);
 	fmstate->p_nums = 0;
 
 	if (operation == CMD_UPDATE || operation == CMD_DELETE)
@@ -4256,7 +4256,7 @@ convert_prep_stmt_params(PgFdwModifyState *fmstate,
 
 	oldcontext = MemoryContextSwitchTo(fmstate->temp_cxt);
 
-	p_values = (const char **) palloc(sizeof(char *) * fmstate->p_nums * numSlots);
+	p_values = palloc_array(const char *, fmstate->p_nums * numSlots); 
 
 	/* ctid is provided only for UPDATE/DELETE, which don't allow batching */
 	Assert(!(tupleid != NULL && numSlots > 1));
@@ -4814,7 +4814,7 @@ prepare_query_params(PlanState *node,
 	Assert(numParams > 0);
 
 	/* Prepare for output conversion of parameters used in remote query. */
-	*param_flinfo = (FmgrInfo *) palloc0(sizeof(FmgrInfo) * numParams);
+	*param_flinfo = palloc0_array(FmgrInfo, numParams);
 
 	i = 0;
 	foreach(lc, fdw_exprs)
@@ -6297,7 +6297,7 @@ postgresGetForeignJoinPaths(PlannerInfo *root,
 	 * if found safe. Once we know that this join can be pushed down, we fill
 	 * the entry.
 	 */
-	fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
+	fpinfo = palloc0_object(PgFdwRelationInfo);
 	fpinfo->pushdown_safe = false;
 	joinrel->fdw_private = fpinfo;
 	/* attrs_used is only for base relations. */
@@ -6666,7 +6666,7 @@ postgresGetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage,
 		output_rel->fdw_private)
 		return;
 
-	fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
+	fpinfo = palloc0_object(PgFdwRelationInfo);
 	fpinfo->pushdown_safe = false;
 	fpinfo->stage = stage;
 	output_rel->fdw_private = fpinfo;
@@ -6891,7 +6891,7 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel,
 	fpinfo->pushdown_safe = true;
 
 	/* Construct PgFdwPathExtraData */
-	fpextra = (PgFdwPathExtraData *) palloc0(sizeof(PgFdwPathExtraData));
+	fpextra = palloc0_object(PgFdwPathExtraData);
 	fpextra->target = root->upper_targets[UPPERREL_ORDERED];
 	fpextra->has_final_sort = true;
 
@@ -7125,7 +7125,7 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel,
 	fpinfo->pushdown_safe = true;
 
 	/* Construct PgFdwPathExtraData */
-	fpextra = (PgFdwPathExtraData *) palloc0(sizeof(PgFdwPathExtraData));
+	fpextra = palloc0_object(PgFdwPathExtraData);
 	fpextra->target = root->upper_targets[UPPERREL_FINAL];
 	fpextra->has_final_sort = has_final_sort;
 	fpextra->has_limit = extra->limit_needed;
diff --git a/contrib/seg/seg.c b/contrib/seg/seg.c
index b5de2a5e1be..2d3a048c73e 100644
--- a/contrib/seg/seg.c
+++ b/contrib/seg/seg.c
@@ -107,7 +107,7 @@ Datum
 seg_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
-	SEG		   *result = palloc(sizeof(SEG));
+	SEG		   *result = palloc_object(SEG);
 	yyscan_t	scanner;
 
 	seg_scanner_init(str, &scanner);
@@ -370,7 +370,7 @@ gseg_picksplit(PG_FUNCTION_ARGS)
 	/*
 	 * Emit segments to the left output page, and compute its bounding box.
 	 */
-	seg_l = (SEG *) palloc(sizeof(SEG));
+	seg_l = palloc_object(SEG);
 	memcpy(seg_l, sort_items[0].data, sizeof(SEG));
 	*left++ = sort_items[0].index;
 	v->spl_nleft++;
@@ -388,7 +388,7 @@ gseg_picksplit(PG_FUNCTION_ARGS)
 	/*
 	 * Likewise for the right page.
 	 */
-	seg_r = (SEG *) palloc(sizeof(SEG));
+	seg_r = palloc_object(SEG);
 	memcpy(seg_r, sort_items[firstright].data, sizeof(SEG));
 	*right++ = sort_items[firstright].index;
 	v->spl_nright++;
@@ -632,7 +632,7 @@ seg_union(PG_FUNCTION_ARGS)
 	SEG		   *b = PG_GETARG_SEG_P(1);
 	SEG		   *n;
 
-	n = (SEG *) palloc(sizeof(*n));
+	n = palloc_object(SEG);
 
 	/* take max of upper endpoints */
 	if (a->upper > b->upper)
@@ -672,7 +672,7 @@ seg_inter(PG_FUNCTION_ARGS)
 	SEG		   *b = PG_GETARG_SEG_P(1);
 	SEG		   *n;
 
-	n = (SEG *) palloc(sizeof(*n));
+	n = palloc_object(SEG);
 
 	/* take min of upper endpoints */
 	if (a->upper < b->upper)
diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c
index a37d89a3f1c..931cd08bdad 100644
--- a/contrib/sepgsql/label.c
+++ b/contrib/sepgsql/label.c
@@ -145,7 +145,7 @@ sepgsql_set_client_label(const char *new_label)
 	 */
 	oldcxt = MemoryContextSwitchTo(CurTransactionContext);
 
-	plabel = palloc0(sizeof(pending_label));
+	plabel = palloc0_object(pending_label);
 	plabel->subid = GetCurrentSubTransactionId();
 	if (new_label)
 		plabel->label = pstrdup(new_label);
@@ -326,7 +326,7 @@ sepgsql_fmgr_hook(FmgrHookEventType event,
 				MemoryContext oldcxt;
 
 				oldcxt = MemoryContextSwitchTo(flinfo->fn_mcxt);
-				stack = palloc(sizeof(*stack));
+				stack = palloc_object(sepgsql_proc_stack);
 				stack->old_label = NULL;
 				stack->new_label = sepgsql_avc_trusted_proc(flinfo->fn_oid);
 				stack->next_private = 0;
diff --git a/contrib/sepgsql/uavc.c b/contrib/sepgsql/uavc.c
index d9ccbc38bc5..5e57971bb4d 100644
--- a/contrib/sepgsql/uavc.c
+++ b/contrib/sepgsql/uavc.c
@@ -257,7 +257,7 @@ sepgsql_avc_compute(const char *scontext, const char *tcontext, uint16 tclass)
 	 */
 	oldctx = MemoryContextSwitchTo(avc_mem_cxt);
 
-	cache = palloc0(sizeof(avc_cache));
+	cache = palloc0_object(avc_cache);
 
 	cache->hash = hash;
 	cache->scontext = pstrdup(scontext);
diff --git a/contrib/spi/refint.c b/contrib/spi/refint.c
index 89898cad7b0..fbbd558ca1e 100644
--- a/contrib/spi/refint.c
+++ b/contrib/spi/refint.c
@@ -651,7 +651,7 @@ find_plan(char *ident, EPlan **eplan, int *nplans)
 	}
 	else
 	{
-		newp = *eplan = (EPlan *) palloc(sizeof(EPlan));
+		newp = *eplan = palloc_object(EPlan);
 		(*nplans) = i = 0;
 	}
 
diff --git a/contrib/sslinfo/sslinfo.c b/contrib/sslinfo/sslinfo.c
index da702011193..2b9eb90b093 100644
--- a/contrib/sslinfo/sslinfo.c
+++ b/contrib/sslinfo/sslinfo.c
@@ -374,7 +374,7 @@ ssl_extension_info(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* Create a user function context for cross-call persistence */
-		fctx = (SSLExtensionInfoContext *) palloc(sizeof(SSLExtensionInfoContext));
+		fctx = palloc_object(SSLExtensionInfoContext);
 
 		/* Construct tuple descriptor */
 		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index 74afdc0977f..c40fd36dc96 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -207,7 +207,7 @@ normal_rand(PG_FUNCTION_ARGS)
 		funcctx->max_calls = num_tuples;
 
 		/* allocate memory for user context */
-		fctx = (normal_rand_fctx *) palloc(sizeof(normal_rand_fctx));
+		fctx = palloc_object(normal_rand_fctx);
 
 		/*
 		 * Use fctx to keep track of upper and lower bounds from call to call.
@@ -766,7 +766,7 @@ load_categories_hash(char *cats_sql, MemoryContext per_query_ctx)
 
 			SPIcontext = MemoryContextSwitchTo(per_query_ctx);
 
-			catdesc = (crosstab_cat_desc *) palloc(sizeof(crosstab_cat_desc));
+			catdesc = palloc_object(crosstab_cat_desc);
 			catdesc->catname = catname;
 			catdesc->attidx = i;
 
diff --git a/contrib/test_decoding/test_decoding.c b/contrib/test_decoding/test_decoding.c
index 36e77c69e1c..47094f86f5f 100644
--- a/contrib/test_decoding/test_decoding.c
+++ b/contrib/test_decoding/test_decoding.c
@@ -163,7 +163,7 @@ pg_decode_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 	TestDecodingData *data;
 	bool		enable_streaming = false;
 
-	data = palloc0(sizeof(TestDecodingData));
+	data = palloc0_object(TestDecodingData);
 	data->context = AllocSetContextCreate(ctx->context,
 										  "text conversion context",
 										  ALLOCSET_DEFAULT_SIZES);
diff --git a/contrib/tsm_system_rows/tsm_system_rows.c b/contrib/tsm_system_rows/tsm_system_rows.c
index f401efa2131..ef145fa6747 100644
--- a/contrib/tsm_system_rows/tsm_system_rows.c
+++ b/contrib/tsm_system_rows/tsm_system_rows.c
@@ -163,7 +163,7 @@ system_rows_samplescangetsamplesize(PlannerInfo *root,
 static void
 system_rows_initsamplescan(SampleScanState *node, int eflags)
 {
-	node->tsm_state = palloc0(sizeof(SystemRowsSamplerData));
+	node->tsm_state = palloc0_object(SystemRowsSamplerData);
 	/* Note the above leaves tsm_state->step equal to zero */
 }
 
diff --git a/contrib/tsm_system_time/tsm_system_time.c b/contrib/tsm_system_time/tsm_system_time.c
index c9c71d8c3af..1041258ea1a 100644
--- a/contrib/tsm_system_time/tsm_system_time.c
+++ b/contrib/tsm_system_time/tsm_system_time.c
@@ -179,7 +179,7 @@ system_time_samplescangetsamplesize(PlannerInfo *root,
 static void
 system_time_initsamplescan(SampleScanState *node, int eflags)
 {
-	node->tsm_state = palloc0(sizeof(SystemTimeSamplerData));
+	node->tsm_state = palloc0_object(SystemTimeSamplerData);
 	/* Note the above leaves tsm_state->step equal to zero */
 }
 
diff --git a/contrib/unaccent/unaccent.c b/contrib/unaccent/unaccent.c
index 336ba31047a..68251660887 100644
--- a/contrib/unaccent/unaccent.c
+++ b/contrib/unaccent/unaccent.c
@@ -60,7 +60,7 @@ placeChar(TrieChar *node, const unsigned char *str, int lenstr,
 	TrieChar   *curnode;
 
 	if (!node)
-		node = (TrieChar *) palloc0(sizeof(TrieChar) * 256);
+		node = palloc0_array(TrieChar, 256);
 
 	Assert(lenstr > 0);			/* else str[0] doesn't exist */
 
@@ -239,7 +239,7 @@ initTrie(const char *filename)
 				if (trgquoted && state > 0)
 				{
 					/* Ignore first and end quotes */
-					trgstore = (char *) palloc(sizeof(char) * (trglen - 2));
+					trgstore = palloc_array(char, trglen - 2);
 					trgstorelen = 0;
 					for (int i = 1; i < trglen - 1; i++)
 					{
@@ -252,7 +252,7 @@ initTrie(const char *filename)
 				}
 				else
 				{
-					trgstore = (char *) palloc(sizeof(char) * trglen);
+					trgstore = palloc_array(char, trglen);
 					trgstorelen = trglen;
 					memcpy(trgstore, trg, trgstorelen);
 				}
@@ -421,7 +421,7 @@ unaccent_lexize(PG_FUNCTION_ARGS)
 	/* return a result only if we made at least one substitution */
 	if (buf.data != NULL)
 	{
-		res = (TSLexeme *) palloc0(sizeof(TSLexeme) * 2);
+		res = palloc0_array(TSLexeme, 2);
 		res->lexeme = buf.data;
 		res->flags = TSL_FILTER;
 	}
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 4ac291c8251..662d7d02f27 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -485,8 +485,7 @@ pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
 	xmlXPathCompExprPtr comppath;
-	xpath_workspace *workspace = (xpath_workspace *)
-		palloc0(sizeof(xpath_workspace));
+	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c
index 36578b82e4d..2be87bec0cd 100644
--- a/contrib/xml2/xslt_proc.c
+++ b/contrib/xml2/xslt_proc.c
@@ -69,7 +69,7 @@ xslt_process(PG_FUNCTION_ARGS)
 	else
 	{
 		/* No parameters */
-		params = (const char **) palloc(sizeof(char *));
+		params = palloc_object(const char *);
 		params[0] = NULL;
 	}
 
diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml
index ee86e170055..5cbea8c3d55 100644
--- a/doc/src/sgml/gist.sgml
+++ b/doc/src/sgml/gist.sgml
@@ -506,11 +506,11 @@ my_compress(PG_FUNCTION_ARGS)
     if (entry-&gt;leafkey)
     {
         /* replace entry-&gt;key with a compressed version */
-        compressed_data_type *compressed_data = palloc(sizeof(compressed_data_type));
+        compressed_data_type *compressed_data = palloc_object(compressed_data_type);
 
         /* fill *compressed_data from entry-&gt;key ... */
 
-        retval = palloc(sizeof(GISTENTRY));
+        retval = palloc_object(GISTENTRY);
         gistentryinit(*retval, PointerGetDatum(compressed_data),
                       entry-&gt;rel, entry-&gt;page, entry-&gt;offset, FALSE);
     }
@@ -921,8 +921,8 @@ my_fetch(PG_FUNCTION_ARGS)
     fetched_data_type *fetched_data;
     GISTENTRY  *retval;
 
-    retval = palloc(sizeof(GISTENTRY));
-    fetched_data = palloc(sizeof(fetched_data_type));
+    retval = palloc_object(GISTENTRY);
+    fetched_data = palloc_object(fetched_data_type);
 
     /*
      * Convert 'fetched_data' into the a Datum of the original datatype.
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 537ee6fa254..2dc98df29c4 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -2491,7 +2491,7 @@ makepoint(PG_FUNCTION_ARGS)
     /* Here, the pass-by-reference nature of Point is not hidden. */
     Point     *pointx = PG_GETARG_POINT_P(0);
     Point     *pointy = PG_GETARG_POINT_P(1);
-    Point     *new_point = (Point *) palloc(sizeof(Point));
+    Point     *new_point = palloc_object(Point);
 
     new_point->x = pointx->x;
     new_point->y = pointy->y;
diff --git a/doc/src/sgml/xtypes.sgml b/doc/src/sgml/xtypes.sgml
index e67e5bdf4c4..df56d1c3ace 100644
--- a/doc/src/sgml/xtypes.sgml
+++ b/doc/src/sgml/xtypes.sgml
@@ -89,7 +89,7 @@ complex_in(PG_FUNCTION_ARGS)
                  errmsg("invalid input syntax for type %s: \"%s\"",
                         "complex", str)));
 
-    result = (Complex *) palloc(sizeof(Complex));
+    result = palloc_object(Complex);
     result->x = x;
     result->y = y;
     PG_RETURN_POINTER(result);
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index cb3331921cb..26cb75058d1 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -318,7 +318,7 @@ initialize_brin_insertstate(Relation idxRel, IndexInfo *indexInfo)
 	MemoryContext oldcxt;
 
 	oldcxt = MemoryContextSwitchTo(indexInfo->ii_Context);
-	bistate = palloc0(sizeof(BrinInsertState));
+	bistate = palloc0_object(BrinInsertState);
 	bistate->bis_desc = brin_build_desc(idxRel);
 	bistate->bis_rmAccess = brinRevmapInitialize(idxRel,
 												 &bistate->bis_pages_per_range);
@@ -1185,7 +1185,7 @@ brinbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	{
 		SortCoordinate coordinate;
 
-		coordinate = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
+		coordinate = palloc0_object(SortCoordinateData);
 		coordinate->isWorker = false;
 		coordinate->nParticipants =
 			state->bs_leader->nparticipanttuplesorts;
@@ -2384,7 +2384,7 @@ _brin_begin_parallel(BrinBuildState *buildstate, Relation heap, Relation index,
 	Size		estsort;
 	BrinShared *brinshared;
 	Sharedsort *sharedsort;
-	BrinLeader *brinleader = (BrinLeader *) palloc0(sizeof(BrinLeader));
+	BrinLeader *brinleader = palloc0_object(BrinLeader);
 	WalUsage   *walusage;
 	BufferUsage *bufferusage;
 	bool		leaderparticipates = true;
@@ -2828,7 +2828,7 @@ _brin_parallel_scan_and_build(BrinBuildState *state,
 	IndexInfo  *indexInfo;
 
 	/* Initialize local tuplesort coordination state */
-	coordinate = palloc0(sizeof(SortCoordinateData));
+	coordinate = palloc0_object(SortCoordinateData);
 	coordinate->isWorker = true;
 	coordinate->nParticipants = -1;
 	coordinate->sharedsort = sharedsort;
diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c
index f8a11444d66..0298a9da8ba 100644
--- a/src/backend/access/brin/brin_minmax_multi.c
+++ b/src/backend/access/brin/brin_minmax_multi.c
@@ -1340,7 +1340,7 @@ build_distances(FmgrInfo *distanceFn, Oid colloid,
 		return NULL;
 
 	ndistances = (neranges - 1);
-	distances = (DistanceValue *) palloc0(sizeof(DistanceValue) * ndistances);
+	distances = palloc0_array(DistanceValue, ndistances);
 
 	/*
 	 * Walk through the ranges once and compute the distance between the
@@ -1504,7 +1504,7 @@ reduce_expanded_ranges(ExpandedRange *eranges, int neranges,
 
 	/* allocate space for the boundary values */
 	nvalues = 0;
-	values = (Datum *) palloc(sizeof(Datum) * max_values);
+	values = palloc_array(Datum, max_values);
 
 	/* add the global min/max values, from the first/last range */
 	values[nvalues++] = eranges[0].minval;
diff --git a/src/backend/access/brin/brin_revmap.c b/src/backend/access/brin/brin_revmap.c
index 4e380ecc710..644f9889a8a 100644
--- a/src/backend/access/brin/brin_revmap.c
+++ b/src/backend/access/brin/brin_revmap.c
@@ -79,7 +79,7 @@ brinRevmapInitialize(Relation idxrel, BlockNumber *pagesPerRange)
 	page = BufferGetPage(meta);
 	metadata = (BrinMetaPageData *) PageGetContents(page);
 
-	revmap = palloc(sizeof(BrinRevmap));
+	revmap = palloc_object(BrinRevmap);
 	revmap->rm_irel = idxrel;
 	revmap->rm_pagesPerRange = metadata->pagesPerRange;
 	revmap->rm_lastRevmapPage = metadata->lastRevmapPage;
diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c
index 861f397e6db..4796d94da8d 100644
--- a/src/backend/access/brin/brin_tuple.c
+++ b/src/backend/access/brin/brin_tuple.c
@@ -119,13 +119,13 @@ brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno, BrinMemTuple *tuple,
 
 	Assert(brdesc->bd_totalstored > 0);
 
-	values = (Datum *) palloc(sizeof(Datum) * brdesc->bd_totalstored);
-	nulls = (bool *) palloc0(sizeof(bool) * brdesc->bd_totalstored);
+	values = palloc_array(Datum, brdesc->bd_totalstored);
+	nulls = palloc0_array(bool, brdesc->bd_totalstored);
 	phony_nullbitmap = (bits8 *)
-		palloc(sizeof(bits8) * BITMAPLEN(brdesc->bd_totalstored));
+		palloc_array(bits8, BITMAPLEN(brdesc->bd_totalstored));
 
 #ifdef TOAST_INDEX_HACK
-	untoasted_values = (Datum *) palloc(sizeof(Datum) * brdesc->bd_totalstored);
+	untoasted_values = palloc_array(Datum, brdesc->bd_totalstored);
 #endif
 
 	/*
@@ -488,9 +488,9 @@ brin_new_memtuple(BrinDesc *brdesc)
 						sizeof(BrinValues) * brdesc->bd_tupdesc->natts);
 	dtup = palloc0(basesize + sizeof(Datum) * brdesc->bd_totalstored);
 
-	dtup->bt_values = palloc(sizeof(Datum) * brdesc->bd_totalstored);
-	dtup->bt_allnulls = palloc(sizeof(bool) * brdesc->bd_tupdesc->natts);
-	dtup->bt_hasnulls = palloc(sizeof(bool) * brdesc->bd_tupdesc->natts);
+	dtup->bt_values = palloc_array(Datum, brdesc->bd_totalstored); 
+	dtup->bt_allnulls = palloc_array(bool, brdesc->bd_tupdesc->natts);
+	dtup->bt_hasnulls = palloc_array(bool, brdesc->bd_tupdesc->natts);
 
 	dtup->bt_empty_range = true;
 
diff --git a/src/backend/access/common/attmap.c b/src/backend/access/common/attmap.c
index 4901ebecef7..4cfa9ee78f9 100644
--- a/src/backend/access/common/attmap.c
+++ b/src/backend/access/common/attmap.c
@@ -41,9 +41,9 @@ make_attrmap(int maplen)
 {
 	AttrMap    *res;
 
-	res = (AttrMap *) palloc0(sizeof(AttrMap));
+	res = palloc0_object(AttrMap);
 	res->maplen = maplen;
-	res->attnums = (AttrNumber *) palloc0(sizeof(AttrNumber) * maplen);
+	res->attnums = palloc0_array(AttrNumber, maplen);
 	return res;
 }
 
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 74a52d87067..6944f70c435 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -1230,8 +1230,8 @@ heap_modify_tuple(HeapTuple tuple,
 	 * O(N^2) if there are many non-replaced columns, so it seems better to
 	 * err on the side of linear cost.
 	 */
-	values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
-	isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
+	values = palloc_array(Datum, numberOfAttributes);
+	isnull = palloc_array(bool, numberOfAttributes);
 
 	heap_deform_tuple(tuple, tupleDesc, values, isnull);
 
@@ -1292,8 +1292,8 @@ heap_modify_tuple_by_cols(HeapTuple tuple,
 	 * allocate and fill values and isnull arrays from the tuple, then replace
 	 * selected columns from the input arrays.
 	 */
-	values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
-	isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
+	values = palloc_array(Datum, numberOfAttributes);
+	isnull = palloc_array(bool, numberOfAttributes);
 
 	heap_deform_tuple(tuple, tupleDesc, values, isnull);
 
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index 9f05e1d15bd..45e77a27f42 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -71,7 +71,7 @@ typedef struct
 DestReceiver *
 printtup_create_DR(CommandDest dest)
 {
-	DR_printtup *self = (DR_printtup *) palloc0(sizeof(DR_printtup));
+	DR_printtup *self = palloc0_object(DR_printtup);
 
 	self->pub.receiveSlot = printtup;	/* might get changed later */
 	self->pub.rStartup = printtup_startup;
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 9e288dfecbf..31926d8a368 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -776,7 +776,7 @@ register_reloptions_validator(local_relopts *relopts, relopts_validator validato
 static void
 add_local_reloption(local_relopts *relopts, relopt_gen *newoption, int offset)
 {
-	local_relopt *opt = palloc(sizeof(*opt));
+	local_relopt *opt = palloc_object(local_relopt);
 
 	Assert(offset < relopts->relopt_struct_size);
 
@@ -1570,7 +1570,7 @@ static relopt_value *
 parseLocalRelOptions(local_relopts *relopts, Datum options, bool validate)
 {
 	int			nopts = list_length(relopts->options);
-	relopt_value *values = palloc(sizeof(*values) * nopts);
+	relopt_value *values = palloc_array(relopt_value, nopts);
 	ListCell   *lc;
 	int			i = 0;
 
@@ -1991,7 +1991,7 @@ void *
 build_local_reloptions(local_relopts *relopts, Datum options, bool validate)
 {
 	int			noptions = list_length(relopts->options);
-	relopt_parse_elt *elems = palloc(sizeof(*elems) * noptions);
+	relopt_parse_elt *elems = palloc_array(relopt_parse_elt, noptions);
 	relopt_value *vals;
 	void	   *opts;
 	int			i = 0;
diff --git a/src/backend/access/common/tidstore.c b/src/backend/access/common/tidstore.c
index fb807d9fe59..6fae41e7b6d 100644
--- a/src/backend/access/common/tidstore.c
+++ b/src/backend/access/common/tidstore.c
@@ -166,7 +166,7 @@ TidStoreCreateLocal(size_t max_bytes, bool insert_only)
 	size_t		minContextSize = ALLOCSET_DEFAULT_MINSIZE;
 	size_t		maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
 
-	ts = palloc0(sizeof(TidStore));
+	ts = palloc0_object(TidStore);
 
 	/* choose the maxBlockSize to be no larger than 1/16 of max_bytes */
 	while (16 * maxBlockSize > max_bytes)
@@ -212,7 +212,7 @@ TidStoreCreateShared(size_t max_bytes, int tranche_id)
 	size_t		dsa_init_size = DSA_DEFAULT_INIT_SEGMENT_SIZE;
 	size_t		dsa_max_size = DSA_MAX_SEGMENT_SIZE;
 
-	ts = palloc0(sizeof(TidStore));
+	ts = palloc0_object(TidStore);
 
 	/*
 	 * Choose the initial and maximum DSA segment sizes to be no longer than
@@ -250,7 +250,7 @@ TidStoreAttach(dsa_handle area_handle, dsa_pointer handle)
 	Assert(DsaPointerIsValid(handle));
 
 	/* create per-backend state */
-	ts = palloc0(sizeof(TidStore));
+	ts = palloc0_object(TidStore);
 
 	area = dsa_attach(area_handle);
 
@@ -472,7 +472,7 @@ TidStoreBeginIterate(TidStore *ts)
 {
 	TidStoreIter *iter;
 
-	iter = palloc0(sizeof(TidStoreIter));
+	iter = palloc0_object(TidStoreIter);
 	iter->ts = ts;
 
 	if (TidStoreIsShared(ts))
diff --git a/src/backend/access/common/toast_internals.c b/src/backend/access/common/toast_internals.c
index 63b848473f8..d06af82de15 100644
--- a/src/backend/access/common/toast_internals.c
+++ b/src/backend/access/common/toast_internals.c
@@ -568,7 +568,7 @@ toast_open_indexes(Relation toastrel,
 	*num_indexes = list_length(indexlist);
 
 	/* Open all the index relations */
-	*toastidxs = (Relation *) palloc(*num_indexes * sizeof(Relation));
+	*toastidxs = palloc_array(Relation, *num_indexes);
 	foreach(lc, indexlist)
 		(*toastidxs)[i++] = index_open(lfirst_oid(lc), lock);
 
diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c
index 1df0c2d2f98..99c197e361f 100644
--- a/src/backend/access/common/tupconvert.c
+++ b/src/backend/access/common/tupconvert.c
@@ -75,17 +75,17 @@ convert_tuples_by_position(TupleDesc indesc,
 	}
 
 	/* Prepare the map structure */
-	map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap));
+	map = palloc_object(TupleConversionMap);
 	map->indesc = indesc;
 	map->outdesc = outdesc;
 	map->attrMap = attrMap;
 	/* preallocate workspace for Datum arrays */
 	n = outdesc->natts + 1;		/* +1 for NULL */
-	map->outvalues = (Datum *) palloc(n * sizeof(Datum));
-	map->outisnull = (bool *) palloc(n * sizeof(bool));
+	map->outvalues = palloc_array(Datum, n);
+	map->outisnull = palloc_array(bool, n);
 	n = indesc->natts + 1;		/* +1 for NULL */
-	map->invalues = (Datum *) palloc(n * sizeof(Datum));
-	map->inisnull = (bool *) palloc(n * sizeof(bool));
+	map->invalues = palloc_array(Datum, n);
+	map->inisnull = palloc_array(bool, n);
 	map->invalues[0] = (Datum) 0;	/* set up the NULL entry */
 	map->inisnull[0] = true;
 
@@ -132,16 +132,16 @@ convert_tuples_by_name_attrmap(TupleDesc indesc,
 	Assert(attrMap != NULL);
 
 	/* Prepare the map structure */
-	map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap));
+	map = palloc_object(TupleConversionMap);
 	map->indesc = indesc;
 	map->outdesc = outdesc;
 	map->attrMap = attrMap;
 	/* preallocate workspace for Datum arrays */
-	map->outvalues = (Datum *) palloc(n * sizeof(Datum));
-	map->outisnull = (bool *) palloc(n * sizeof(bool));
+	map->outvalues = palloc_array(Datum, n);
+	map->outisnull = palloc_array(bool, n);
 	n = indesc->natts + 1;		/* +1 for NULL */
-	map->invalues = (Datum *) palloc(n * sizeof(Datum));
-	map->inisnull = (bool *) palloc(n * sizeof(bool));
+	map->invalues = palloc_array(Datum, n);
+	map->inisnull = palloc_array(bool, n);
 	map->invalues[0] = (Datum) 0;	/* set up the NULL entry */
 	map->inisnull[0] = true;
 
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index d715c345dd8..bcd1ddcc68b 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -361,7 +361,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
 	/* Copy the TupleConstr data structure, if any */
 	if (constr)
 	{
-		TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
+		TupleConstr *cpy = palloc0_object(TupleConstr);
 
 		cpy->has_not_null = constr->has_not_null;
 		cpy->has_generated_stored = constr->has_generated_stored;
diff --git a/src/backend/access/gin/ginbtree.c b/src/backend/access/gin/ginbtree.c
index 644d484ea53..47f881ae596 100644
--- a/src/backend/access/gin/ginbtree.c
+++ b/src/backend/access/gin/ginbtree.c
@@ -85,7 +85,7 @@ ginFindLeafPage(GinBtree btree, bool searchMode,
 {
 	GinBtreeStack *stack;
 
-	stack = (GinBtreeStack *) palloc(sizeof(GinBtreeStack));
+	stack = palloc_object(GinBtreeStack);
 	stack->blkno = btree->rootBlkno;
 	stack->buffer = ReadBuffer(btree->index, btree->rootBlkno);
 	stack->parent = NULL;
@@ -152,7 +152,7 @@ ginFindLeafPage(GinBtree btree, bool searchMode,
 		}
 		else
 		{
-			GinBtreeStack *ptr = (GinBtreeStack *) palloc(sizeof(GinBtreeStack));
+			GinBtreeStack *ptr = palloc_object(GinBtreeStack);
 
 			ptr->parent = stack;
 			stack = ptr;
@@ -246,7 +246,7 @@ ginFindParents(GinBtree btree, GinBtreeStack *stack)
 	blkno = root->blkno;
 	buffer = root->buffer;
 
-	ptr = (GinBtreeStack *) palloc(sizeof(GinBtreeStack));
+	ptr = palloc_object(GinBtreeStack);
 
 	for (;;)
 	{
diff --git a/src/backend/access/gin/ginbulk.c b/src/backend/access/gin/ginbulk.c
index 302cb2092a9..f73ee7b1fa4 100644
--- a/src/backend/access/gin/ginbulk.c
+++ b/src/backend/access/gin/ginbulk.c
@@ -93,7 +93,7 @@ ginAllocEntryAccumulator(void *arg)
 	 */
 	if (accum->entryallocator == NULL || accum->eas_used >= DEF_NENTRY)
 	{
-		accum->entryallocator = palloc(sizeof(GinEntryAccumulator) * DEF_NENTRY);
+		accum->entryallocator = palloc_array(GinEntryAccumulator, DEF_NENTRY);
 		accum->allocatedMemory += GetMemoryChunkSpace(accum->entryallocator);
 		accum->eas_used = 0;
 	}
@@ -177,8 +177,7 @@ ginInsertBAEntry(BuildAccumulator *accum,
 		ea->maxcount = DEF_NPTR;
 		ea->count = 1;
 		ea->shouldSort = false;
-		ea->list =
-			(ItemPointerData *) palloc(sizeof(ItemPointerData) * DEF_NPTR);
+		ea->list = palloc_array(ItemPointerData, DEF_NPTR);
 		ea->list[0] = *heapptr;
 		accum->allocatedMemory += GetMemoryChunkSpace(ea->list);
 	}
diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c
index 6c2c6194720..91191ff18b9 100644
--- a/src/backend/access/gin/gindatapage.c
+++ b/src/backend/access/gin/gindatapage.c
@@ -1332,7 +1332,7 @@ dataSplitPageInternal(GinBtree btree, Buffer origbuf,
 static void *
 dataPrepareDownlink(GinBtree btree, Buffer lbuf)
 {
-	PostingItem *pitem = palloc(sizeof(PostingItem));
+	PostingItem *pitem = palloc_object(PostingItem);
 	Page		lpage = BufferGetPage(lbuf);
 
 	PostingItemSetBlockNumber(pitem, BufferGetBlockNumber(lbuf));
@@ -1374,7 +1374,7 @@ disassembleLeaf(Page page)
 	Pointer		segbegin;
 	Pointer		segend;
 
-	leaf = palloc0(sizeof(disassembledLeaf));
+	leaf = palloc0_object(disassembledLeaf);
 	dlist_init(&leaf->segments);
 
 	if (GinPageIsCompressed(page))
@@ -1387,7 +1387,7 @@ disassembleLeaf(Page page)
 		segend = segbegin + GinDataLeafPageGetPostingListSize(page);
 		while ((Pointer) seg < segend)
 		{
-			leafSegmentInfo *seginfo = palloc(sizeof(leafSegmentInfo));
+			leafSegmentInfo *seginfo = palloc_object(leafSegmentInfo);
 
 			seginfo->action = GIN_SEGMENT_UNMODIFIED;
 			seginfo->seg = seg;
@@ -1414,7 +1414,7 @@ disassembleLeaf(Page page)
 
 		if (nuncompressed > 0)
 		{
-			seginfo = palloc(sizeof(leafSegmentInfo));
+			seginfo = palloc_object(leafSegmentInfo);
 
 			seginfo->action = GIN_SEGMENT_REPLACE;
 			seginfo->seg = NULL;
@@ -1455,7 +1455,7 @@ addItemsToLeaf(disassembledLeaf *leaf, ItemPointer newItems, int nNewItems)
 	 */
 	if (dlist_is_empty(&leaf->segments))
 	{
-		newseg = palloc(sizeof(leafSegmentInfo));
+		newseg = palloc_object(leafSegmentInfo);
 		newseg->seg = NULL;
 		newseg->items = newItems;
 		newseg->nitems = nNewItems;
@@ -1512,7 +1512,7 @@ addItemsToLeaf(disassembledLeaf *leaf, ItemPointer newItems, int nNewItems)
 			cur->seg != NULL &&
 			SizeOfGinPostingList(cur->seg) >= GinPostingListSegmentTargetSize)
 		{
-			newseg = palloc(sizeof(leafSegmentInfo));
+			newseg = palloc_object(leafSegmentInfo);
 			newseg->seg = NULL;
 			newseg->items = nextnew;
 			newseg->nitems = nthis;
@@ -1629,7 +1629,7 @@ leafRepackItems(disassembledLeaf *leaf, ItemPointer remaining)
 					if (seginfo->action != GIN_SEGMENT_INSERT)
 						seginfo->action = GIN_SEGMENT_REPLACE;
 
-					nextseg = palloc(sizeof(leafSegmentInfo));
+					nextseg = palloc_object(leafSegmentInfo);
 					nextseg->action = GIN_SEGMENT_INSERT;
 					nextseg->seg = NULL;
 					nextseg->items = &seginfo->items[npacked];
diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c
index c0592367700..63413afa00b 100644
--- a/src/backend/access/gin/ginentrypage.c
+++ b/src/backend/access/gin/ginentrypage.c
@@ -183,7 +183,7 @@ ginReadTuple(GinState *ginstate, OffsetNumber attnum, IndexTuple itup,
 	}
 	else
 	{
-		ipd = (ItemPointer) palloc(sizeof(ItemPointerData) * nipd);
+		ipd = palloc_array(ItemPointerData, nipd);
 		memcpy(ipd, ptr, sizeof(ItemPointerData) * nipd);
 	}
 	*nitems = nipd;
@@ -708,7 +708,7 @@ entryPrepareDownlink(GinBtree btree, Buffer lbuf)
 
 	itup = getRightMostTuple(lpage);
 
-	insertData = palloc(sizeof(GinBtreeEntryInsertData));
+	insertData = palloc_object(GinBtreeEntryInsertData);
 	insertData->entry = GinFormInteriorTuple(itup, lpage, lblkno);
 	insertData->isDelete = false;
 
diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0d4108d05a3..b3e2e9d5f6e 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -552,7 +552,7 @@ startScanKey(GinState *ginstate, GinScanOpaque so, GinScanKey key)
 	{
 		MemoryContextSwitchTo(so->tempCtx);
 
-		entryIndexes = (int *) palloc(sizeof(int) * key->nentries);
+		entryIndexes = palloc_array(int, key->nentries);
 		for (i = 0; i < key->nentries; i++)
 			entryIndexes[i] = i;
 		qsort_arg(entryIndexes, key->nentries, sizeof(int),
@@ -1873,7 +1873,7 @@ scanPendingInsert(IndexScanDesc scan, TIDBitmap *tbm, int64 *ntids)
 	LockBuffer(pos.pendingBuffer, GIN_SHARE);
 	pos.firstOffset = FirstOffsetNumber;
 	UnlockReleaseBuffer(metabuffer);
-	pos.hasMatchKey = palloc(sizeof(bool) * so->nkeys);
+	pos.hasMatchKey = palloc_array(bool, so->nkeys);
 
 	/*
 	 * loop for each heap row. scanGetCandidate returns full row or row's
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index c2b879b2bf6..ab0c5186b3d 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -707,7 +707,7 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	{
 		SortCoordinate coordinate;
 
-		coordinate = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
+		coordinate = palloc0_object(SortCoordinateData);
 		coordinate->isWorker = false;
 		coordinate->nParticipants =
 			state->bs_leader->nparticipanttuplesorts;
@@ -791,7 +791,7 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	/*
 	 * Return statistics
 	 */
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 
 	result->heap_tuples = reltuples;
 	result->index_tuples = buildstate.indtuples;
@@ -867,7 +867,7 @@ gininsert(Relation index, Datum *values, bool *isnull,
 	if (ginstate == NULL)
 	{
 		oldCtx = MemoryContextSwitchTo(indexInfo->ii_Context);
-		ginstate = (GinState *) palloc(sizeof(GinState));
+		ginstate = palloc_object(GinState);
 		initGinState(ginstate, index);
 		indexInfo->ii_AmCache = ginstate;
 		MemoryContextSwitchTo(oldCtx);
@@ -934,7 +934,7 @@ _gin_begin_parallel(GinBuildState *buildstate, Relation heap, Relation index,
 	Size		estsort;
 	GinBuildShared *ginshared;
 	Sharedsort *sharedsort;
-	GinLeader  *ginleader = (GinLeader *) palloc0(sizeof(GinLeader));
+	GinLeader  *ginleader = palloc0_object(GinLeader);
 	WalUsage   *walusage;
 	BufferUsage *bufferusage;
 	bool		leaderparticipates = true;
@@ -1259,7 +1259,7 @@ AssertCheckGinBuffer(GinBuffer *buffer)
 static GinBuffer *
 GinBufferInit(Relation index)
 {
-	GinBuffer  *buffer = palloc0(sizeof(GinBuffer));
+	GinBuffer  *buffer = palloc0_object(GinBuffer);
 	int			i,
 				nKeys;
 	TupleDesc	desc = RelationGetDescr(index);
@@ -1273,7 +1273,7 @@ GinBufferInit(Relation index)
 
 	nKeys = IndexRelationGetNumberOfKeyAttributes(index);
 
-	buffer->ssup = palloc0(sizeof(SortSupportData) * nKeys);
+	buffer->ssup = palloc0_array(SortSupportData, nKeys);
 
 	/*
 	 * Lookup ordering operator for the index key data type, and initialize
@@ -2030,7 +2030,7 @@ _gin_parallel_scan_and_build(GinBuildState *state,
 	IndexInfo  *indexInfo;
 
 	/* Initialize local tuplesort coordination state */
-	coordinate = palloc0(sizeof(SortCoordinateData));
+	coordinate = palloc0_object(SortCoordinateData);
 	coordinate->isWorker = true;
 	coordinate->nParticipants = -1;
 	coordinate->sharedsort = sharedsort;
@@ -2279,7 +2279,7 @@ _gin_build_tuple(OffsetNumber attrnum, unsigned char category,
 	while (ncompressed < nitems)
 	{
 		int			cnt;
-		GinSegmentInfo *seginfo = palloc(sizeof(GinSegmentInfo));
+		GinSegmentInfo *seginfo = palloc_object(GinSegmentInfo);
 
 		seginfo->seg = ginCompressPostingList(&items[ncompressed],
 											  (nitems - ncompressed),
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 26081693383..2ca635909f9 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -33,7 +33,7 @@ ginbeginscan(Relation rel, int nkeys, int norderbys)
 	scan = RelationGetIndexScan(rel, nkeys, norderbys);
 
 	/* allocate private workspace */
-	so = (GinScanOpaque) palloc(sizeof(GinScanOpaqueData));
+	so = (GinScanOpaque) palloc_object(GinScanOpaqueData);
 	so->keys = NULL;
 	so->nkeys = 0;
 	so->tempCtx = AllocSetContextCreate(CurrentMemoryContext,
@@ -98,7 +98,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	}
 
 	/* Nope, create a new entry */
-	scanEntry = (GinScanEntry) palloc(sizeof(GinScanEntryData));
+	scanEntry = palloc_object(GinScanEntryData);
 	scanEntry->queryKey = queryKey;
 	scanEntry->queryCategory = queryCategory;
 	scanEntry->isPartialMatch = isPartialMatch;
@@ -123,8 +123,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	if (so->totalentries >= so->allocentries)
 	{
 		so->allocentries *= 2;
-		so->entries = (GinScanEntry *)
-			repalloc(so->entries, so->allocentries * sizeof(GinScanEntry));
+		so->entries = repalloc_array(so->entries, GinScanEntry, so->allocentries);
 	}
 	so->entries[so->totalentries++] = scanEntry;
 
@@ -170,10 +169,8 @@ ginFillScanKey(GinScanOpaque so, OffsetNumber attnum,
 	key->nuserentries = nQueryValues;
 
 	/* Allocate one extra array slot for possible "hidden" entry */
-	key->scanEntry = (GinScanEntry *) palloc(sizeof(GinScanEntry) *
-											 (nQueryValues + 1));
-	key->entryRes = (GinTernaryValue *) palloc0(sizeof(GinTernaryValue) *
-												(nQueryValues + 1));
+	key->scanEntry = palloc_array(GinScanEntry, nQueryValues + 1);
+	key->entryRes = palloc0_array(GinTernaryValue, nQueryValues + 1);
 
 	key->query = query;
 	key->queryValues = queryValues;
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index 78f7b7a2495..605f80aad39 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -500,9 +500,9 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 	if (isNull)
 	{
 		*nentries = 1;
-		entries = (Datum *) palloc(sizeof(Datum));
+		entries = palloc_object(Datum);
 		entries[0] = (Datum) 0;
-		*categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
+		*categories = palloc_object(GinNullCategory);
 		(*categories)[0] = GIN_CAT_NULL_ITEM;
 		return entries;
 	}
@@ -522,9 +522,9 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 	if (entries == NULL || *nentries <= 0)
 	{
 		*nentries = 1;
-		entries = (Datum *) palloc(sizeof(Datum));
+		entries = palloc_object(Datum);
 		entries[0] = (Datum) 0;
-		*categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
+		*categories = palloc_object(GinNullCategory);
 		(*categories)[0] = GIN_CAT_EMPTY_ITEM;
 		return entries;
 	}
@@ -548,7 +548,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 		keyEntryData *keydata;
 		cmpEntriesArg arg;
 
-		keydata = (keyEntryData *) palloc(*nentries * sizeof(keyEntryData));
+		keydata = palloc_array(keyEntryData, *nentries);
 		for (i = 0; i < *nentries; i++)
 		{
 			keydata[i].datum = entries[i];
diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c
index 2237efa50bb..d7baf7c847c 100644
--- a/src/backend/access/gin/ginvacuum.c
+++ b/src/backend/access/gin/ginvacuum.c
@@ -65,7 +65,7 @@ ginVacuumItemPointers(GinVacuumState *gvs, ItemPointerData *items,
 				 * First TID to be deleted: allocate memory to hold the
 				 * remaining items.
 				 */
-				tmpitems = palloc(sizeof(ItemPointerData) * nitem);
+				tmpitems = palloc_array(ItemPointerData, nitem);
 				memcpy(tmpitems, items, sizeof(ItemPointerData) * i);
 			}
 		}
@@ -260,7 +260,7 @@ ginScanToDelete(GinVacuumState *gvs, BlockNumber blkno, bool isRoot,
 	{
 		if (!parent->child)
 		{
-			me = (DataPageDeleteStack *) palloc0(sizeof(DataPageDeleteStack));
+			me = palloc0_object(DataPageDeleteStack);
 			me->parent = parent;
 			parent->child = me;
 			me->leftBuffer = InvalidBuffer;
@@ -584,7 +584,7 @@ ginbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 	if (stats == NULL)
 	{
 		/* Yes, so initialize stats to zeroes */
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 
 		/*
 		 * and cleanup any pending inserts
@@ -714,7 +714,7 @@ ginvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 	 */
 	if (stats == NULL)
 	{
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 		initGinState(&ginstate, index);
 		ginInsertCleanup(&ginstate, !AmAutoVacuumWorkerProcess(),
 						 false, true, stats);
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 3fb1a1285c5..c26d8538f05 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -43,7 +43,7 @@ static void gistprunepage(Relation rel, Page page, Buffer buffer,
 
 
 #define ROTATEDIST(d) do { \
-	SplitPageLayout *tmp = (SplitPageLayout *) palloc0(sizeof(SplitPageLayout)); \
+	SplitPageLayout *tmp = palloc0_object(SplitPageLayout); \
 	tmp->block.blkno = InvalidBlockNumber;	\
 	tmp->buffer = InvalidBuffer;	\
 	tmp->next = (d); \
@@ -392,7 +392,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 			/* Prepare a vector of all the downlinks */
 			for (ptr = dist; ptr; ptr = ptr->next)
 				ndownlinks++;
-			downlinks = palloc(sizeof(IndexTuple) * ndownlinks);
+			downlinks = palloc_array(IndexTuple, ndownlinks);
 			for (i = 0, ptr = dist; ptr; ptr = ptr->next)
 				downlinks[i++] = ptr->itup;
 
@@ -410,7 +410,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 			/* Prepare split-info to be returned to caller */
 			for (ptr = dist; ptr; ptr = ptr->next)
 			{
-				GISTPageSplitInfo *si = palloc(sizeof(GISTPageSplitInfo));
+				GISTPageSplitInfo *si = palloc_object(GISTPageSplitInfo);
 
 				si->buf = ptr->buffer;
 				si->downlink = ptr->itup;
@@ -823,7 +823,7 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace,
 			xlocked = false;
 
 			/* descend to the chosen child */
-			item = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));
+			item = palloc0_object(GISTInsertStack);
 			item->blkno = childblkno;
 			item->parent = stack;
 			item->downlinkoffnum = downlinkoffnum;
@@ -923,7 +923,7 @@ gistFindPath(Relation r, BlockNumber child, OffsetNumber *downlinkoffnum)
 			   *ptr;
 	BlockNumber blkno;
 
-	top = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));
+	top = palloc0_object(GISTInsertStack);
 	top->blkno = GIST_ROOT_BLKNO;
 	top->downlinkoffnum = InvalidOffsetNumber;
 
@@ -975,7 +975,7 @@ gistFindPath(Relation r, BlockNumber child, OffsetNumber *downlinkoffnum)
 			 * leaf pages, and we assume that there can't be any non-leaf
 			 * pages behind leaf pages.
 			 */
-			ptr = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));
+			ptr = palloc0_object(GISTInsertStack);
 			ptr->blkno = GistPageGetOpaque(page)->rightlink;
 			ptr->downlinkoffnum = InvalidOffsetNumber;
 			ptr->parent = top->parent;
@@ -1000,7 +1000,7 @@ gistFindPath(Relation r, BlockNumber child, OffsetNumber *downlinkoffnum)
 			else
 			{
 				/* Append this child to the list of pages to visit later */
-				ptr = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));
+				ptr = palloc0_object(GISTInsertStack);
 				ptr->blkno = blkno;
 				ptr->downlinkoffnum = i;
 				ptr->parent = top;
@@ -1218,7 +1218,7 @@ gistfixsplit(GISTInsertState *state, GISTSTATE *giststate)
 	 */
 	for (;;)
 	{
-		GISTPageSplitInfo *si = palloc(sizeof(GISTPageSplitInfo));
+		GISTPageSplitInfo *si = palloc_object(GISTPageSplitInfo);
 		IndexTuple	downlink;
 
 		page = BufferGetPage(buf);
@@ -1482,8 +1482,8 @@ gistSplit(Relation r,
 	gistSplitByKey(r, page, itup, len, giststate, &v, 0);
 
 	/* form left and right vector */
-	lvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (len + 1));
-	rvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (len + 1));
+	lvectup = palloc_array(IndexTuple, len + 1);
+	rvectup = palloc_array(IndexTuple, len + 1);
 
 	for (i = 0; i < v.splitVector.spl_nleft; i++)
 		lvectup[i] = itup[v.splitVector.spl_left[i] - 1];
@@ -1552,7 +1552,7 @@ initGISTstate(Relation index)
 	oldCxt = MemoryContextSwitchTo(scanCxt);
 
 	/* Create and fill in the GISTSTATE */
-	giststate = (GISTSTATE *) palloc(sizeof(GISTSTATE));
+	giststate = palloc_object(GISTSTATE);
 
 	giststate->scanCxt = scanCxt;
 	giststate->tempCxt = scanCxt;	/* caller must change this if needed */
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index be0fd5b753d..b9fa196149d 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -346,7 +346,7 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	/*
 	 * Return statistics
 	 */
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 
 	result->heap_tuples = reltuples;
 	result->index_tuples = (double) buildstate.indtuples;
@@ -409,7 +409,7 @@ gist_indexsortbuild(GISTBuildState *state)
 	state->bulkstate = smgr_bulk_start_rel(state->indexrel, MAIN_FORKNUM);
 
 	/* Allocate a temporary buffer for the first leaf page batch. */
-	levelstate = palloc0(sizeof(GistSortedBuildLevelState));
+	levelstate = palloc0_object(GistSortedBuildLevelState);
 	levelstate->pages[0] = palloc(BLCKSZ);
 	levelstate->parent = NULL;
 	gistinitpage(levelstate->pages[0], F_LEAF);
@@ -526,7 +526,7 @@ gist_indexsortbuild_levelstate_flush(GISTBuildState *state,
 	else
 	{
 		/* Create split layout from single page */
-		dist = (SplitPageLayout *) palloc0(sizeof(SplitPageLayout));
+		dist = palloc0_object(SplitPageLayout);
 		union_tuple = gistunion(state->indexrel, itvec, vect_len,
 								state->giststate);
 		dist->itup = union_tuple;
@@ -597,7 +597,7 @@ gist_indexsortbuild_levelstate_flush(GISTBuildState *state,
 		parent = levelstate->parent;
 		if (parent == NULL)
 		{
-			parent = palloc0(sizeof(GistSortedBuildLevelState));
+			parent = palloc0_object(GistSortedBuildLevelState);
 			parent->pages[0] = palloc(BLCKSZ);
 			parent->parent = NULL;
 			gistinitpage(parent->pages[0], 0);
@@ -1154,7 +1154,7 @@ gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer, int level,
 
 		/* Create an array of all the downlink tuples */
 		ndownlinks = list_length(splitinfo);
-		downlinks = (IndexTuple *) palloc(sizeof(IndexTuple) * ndownlinks);
+		downlinks = palloc_array(IndexTuple, ndownlinks);
 		i = 0;
 		foreach(lc, splitinfo)
 		{
diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c
index 0707254d18e..d49b920760a 100644
--- a/src/backend/access/gist/gistbuildbuffers.c
+++ b/src/backend/access/gist/gistbuildbuffers.c
@@ -46,7 +46,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
 	GISTBuildBuffers *gfbb;
 	HASHCTL		hashCtl;
 
-	gfbb = palloc(sizeof(GISTBuildBuffers));
+	gfbb = palloc_object(GISTBuildBuffers);
 	gfbb->pagesPerBuffer = pagesPerBuffer;
 	gfbb->levelStep = levelStep;
 
@@ -60,7 +60,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
 	/* Initialize free page management. */
 	gfbb->nFreeBlocks = 0;
 	gfbb->freeBlocksLen = 32;
-	gfbb->freeBlocks = (long *) palloc(gfbb->freeBlocksLen * sizeof(long));
+	gfbb->freeBlocks = palloc_array(long, gfbb->freeBlocksLen);
 
 	/*
 	 * Current memory context will be used for all in-memory data structures
@@ -87,8 +87,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
 	 * buffers are inserted here when they are created.
 	 */
 	gfbb->buffersOnLevelsLen = 1;
-	gfbb->buffersOnLevels = (List **) palloc(sizeof(List *) *
-											 gfbb->buffersOnLevelsLen);
+	gfbb->buffersOnLevels = (List **) palloc_array(List *, gfbb->buffersOnLevelsLen);
 	gfbb->buffersOnLevels[0] = NIL;
 
 	/*
@@ -96,8 +95,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
 	 * into main memory.
 	 */
 	gfbb->loadedBuffersLen = 32;
-	gfbb->loadedBuffers = (GISTNodeBuffer **) palloc(gfbb->loadedBuffersLen *
-													 sizeof(GISTNodeBuffer *));
+	gfbb->loadedBuffers = (GISTNodeBuffer **) palloc_array(GISTNodeBuffer *, gfbb->loadedBuffersLen);
 	gfbb->loadedBuffersCount = 0;
 
 	gfbb->rootlevel = maxLevel;
@@ -582,9 +580,7 @@ gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb, GISTSTATE *giststate,
 	 * Allocate memory for information about relocation buffers.
 	 */
 	splitPagesCount = list_length(splitinfo);
-	relocationBuffersInfos =
-		(RelocationBufferInfo *) palloc(sizeof(RelocationBufferInfo) *
-										splitPagesCount);
+	relocationBuffersInfos = palloc_array(RelocationBufferInfo, splitPagesCount);
 
 	/*
 	 * Fill relocation buffers information for node buffers of pages produced
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index f2ec6cbe2e5..9ac06504be1 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -171,7 +171,7 @@ gist_box_union(PG_FUNCTION_ARGS)
 			   *pageunion;
 
 	numranges = entryvec->n;
-	pageunion = (BOX *) palloc(sizeof(BOX));
+	pageunion = palloc_object(BOX);
 	cur = DatumGetBoxP(entryvec->vector[0].key);
 	memcpy(pageunion, cur, sizeof(BOX));
 
@@ -237,7 +237,7 @@ fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
 			v->spl_left[v->spl_nleft] = i;
 			if (unionL == NULL)
 			{
-				unionL = (BOX *) palloc(sizeof(BOX));
+				unionL = palloc_object(BOX);
 				*unionL = *cur;
 			}
 			else
@@ -250,7 +250,7 @@ fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
 			v->spl_right[v->spl_nright] = i;
 			if (unionR == NULL)
 			{
-				unionR = (BOX *) palloc(sizeof(BOX));
+				unionR = palloc_object(BOX);
 				*unionR = *cur;
 			}
 			else
@@ -698,8 +698,8 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
 	v->spl_nright = 0;
 
 	/* Allocate bounding boxes of left and right groups */
-	leftBox = palloc0(sizeof(BOX));
-	rightBox = palloc0(sizeof(BOX));
+	leftBox = palloc0_object(BOX);
+	rightBox = palloc0_object(BOX);
 
 	/*
 	 * Allocate an array for "common entries" - entries which can be placed to
@@ -1042,10 +1042,10 @@ gist_poly_compress(PG_FUNCTION_ARGS)
 		POLYGON    *in = DatumGetPolygonP(entry->key);
 		BOX		   *r;
 
-		r = (BOX *) palloc(sizeof(BOX));
+		r = palloc_object(BOX);
 		memcpy(r, &(in->boundbox), sizeof(BOX));
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -1107,13 +1107,13 @@ gist_circle_compress(PG_FUNCTION_ARGS)
 		CIRCLE	   *in = DatumGetCircleP(entry->key);
 		BOX		   *r;
 
-		r = (BOX *) palloc(sizeof(BOX));
+		r = palloc_object(BOX);
 		r->high.x = float8_pl(in->center.x, in->radius);
 		r->low.x = float8_mi(in->center.x, in->radius);
 		r->high.y = float8_pl(in->center.y, in->radius);
 		r->low.y = float8_mi(in->center.y, in->radius);
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -1171,9 +1171,9 @@ gist_point_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)			/* Point, actually */
 	{
-		BOX		   *box = palloc(sizeof(BOX));
+		BOX		   *box = palloc_object(BOX);
 		Point	   *point = DatumGetPointP(entry->key);
-		GISTENTRY  *retval = palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		box->high = box->low = *point;
 
@@ -1200,9 +1200,9 @@ gist_point_fetch(PG_FUNCTION_ARGS)
 	Point	   *r;
 	GISTENTRY  *retval;
 
-	retval = palloc(sizeof(GISTENTRY));
+	retval = palloc_object(GISTENTRY);
 
-	r = (Point *) palloc(sizeof(Point));
+	r = palloc_object(Point);
 	r->x = in->high.x;
 	r->y = in->high.y;
 	gistentryinit(*retval, PointerGetDatum(r),
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 700fa959d03..01b8ff0b6fa 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -90,7 +90,7 @@ gistbeginscan(Relation r, int nkeys, int norderbys)
 	oldCxt = MemoryContextSwitchTo(giststate->scanCxt);
 
 	/* initialize opaque data */
-	so = (GISTScanOpaque) palloc0(sizeof(GISTScanOpaqueData));
+	so = palloc0_object(GISTScanOpaqueData);
 	so->giststate = giststate;
 	giststate->tempCxt = createTempGistContext();
 	so->queue = NULL;
@@ -101,8 +101,8 @@ gistbeginscan(Relation r, int nkeys, int norderbys)
 	so->qual_ok = true;			/* in case there are zero keys */
 	if (scan->numberOfOrderBys > 0)
 	{
-		scan->xs_orderbyvals = palloc0(sizeof(Datum) * scan->numberOfOrderBys);
-		scan->xs_orderbynulls = palloc(sizeof(bool) * scan->numberOfOrderBys);
+		scan->xs_orderbyvals = palloc0_array(Datum, scan->numberOfOrderBys);
+		scan->xs_orderbynulls = palloc_array(bool, scan->numberOfOrderBys);
 		memset(scan->xs_orderbynulls, true, sizeof(bool) * scan->numberOfOrderBys);
 	}
 
diff --git a/src/backend/access/gist/gistsplit.c b/src/backend/access/gist/gistsplit.c
index 49838ceb07b..5b3c67dbf3a 100644
--- a/src/backend/access/gist/gistsplit.c
+++ b/src/backend/access/gist/gistsplit.c
@@ -51,7 +51,7 @@ gistunionsubkeyvec(GISTSTATE *giststate, IndexTuple *itvec,
 	int			i,
 				cleanedLen = 0;
 
-	cleanedItVec = (IndexTuple *) palloc(sizeof(IndexTuple) * gsvp->len);
+	cleanedItVec = palloc_array(IndexTuple, gsvp->len);
 
 	for (i = 0; i < gsvp->len; i++)
 	{
@@ -501,7 +501,7 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
 		 * Locate don't-care tuples, if any.  If there are none, the split is
 		 * optimal, so just fall out and return false.
 		 */
-		v->spl_dontcare = (bool *) palloc0(sizeof(bool) * (entryvec->n + 1));
+		v->spl_dontcare = palloc0_array(bool, entryvec->n + 1);
 
 		NumDontCare = findDontCares(r, giststate, entryvec->vector, v, attno);
 
@@ -738,9 +738,9 @@ gistSplitByKey(Relation r, Page page, IndexTuple *itup, int len,
 				 * call will overwrite that with its own result.
 				 */
 				backupSplit = v->splitVector;
-				backupSplit.spl_left = (OffsetNumber *) palloc(sizeof(OffsetNumber) * len);
+				backupSplit.spl_left = palloc_array(OffsetNumber, len);
 				memcpy(backupSplit.spl_left, v->splitVector.spl_left, sizeof(OffsetNumber) * v->splitVector.spl_nleft);
-				backupSplit.spl_right = (OffsetNumber *) palloc(sizeof(OffsetNumber) * len);
+				backupSplit.spl_right = palloc_array(OffsetNumber, len);	
 				memcpy(backupSplit.spl_right, v->splitVector.spl_right, sizeof(OffsetNumber) * v->splitVector.spl_nright);
 
 				/* Recursively decide how to split the don't-care tuples */
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 75272827837..a346a85adcb 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -100,7 +100,7 @@ gistextractpage(Page page, int *len /* out */ )
 
 	maxoff = PageGetMaxOffsetNumber(page);
 	*len = maxoff;
-	itvec = palloc(sizeof(IndexTuple) * maxoff);
+	itvec = palloc_array(IndexTuple, maxoff);
 	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
 		itvec[i - FirstOffsetNumber] = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));
 
@@ -113,7 +113,7 @@ gistextractpage(Page page, int *len /* out */ )
 IndexTuple *
 gistjoinvector(IndexTuple *itvec, int *len, IndexTuple *additvec, int addlen)
 {
-	itvec = (IndexTuple *) repalloc(itvec, sizeof(IndexTuple) * ((*len) + addlen));
+	itvec = repalloc_array(itvec, IndexTuple, (*len) + addlen);
 	memmove(&itvec[*len], additvec, sizeof(IndexTuple) * addlen);
 	*len += addlen;
 	return itvec;
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index b925eda2b9b..7591ad4da1a 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -61,7 +61,7 @@ gistbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 {
 	/* allocate stats if first time through, else re-use existing struct */
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 
 	gistvacuumscan(info, stats, callback, callback_state);
 
@@ -85,7 +85,7 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 	 */
 	if (stats == NULL)
 	{
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 		gistvacuumscan(info, stats, NULL, NULL);
 	}
 
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 53061c819fb..e388252afdc 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -193,7 +193,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	/*
 	 * Return statistics
 	 */
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 
 	result->heap_tuples = reltuples;
 	result->index_tuples = buildstate.indtuples;
@@ -318,8 +318,7 @@ hashgettuple(IndexScanDesc scan, ScanDirection dir)
 			 * entries.
 			 */
 			if (so->killedItems == NULL)
-				so->killedItems = (int *)
-					palloc(MaxIndexTuplesPerPage * sizeof(int));
+				so->killedItems = palloc_array(int, MaxIndexTuplesPerPage);
 
 			if (so->numKilled < MaxIndexTuplesPerPage)
 				so->killedItems[so->numKilled++] = so->currPos.itemIndex;
@@ -381,7 +380,7 @@ hashbeginscan(Relation rel, int nkeys, int norderbys)
 
 	scan = RelationGetIndexScan(rel, nkeys, norderbys);
 
-	so = (HashScanOpaque) palloc(sizeof(HashScanOpaqueData));
+	so = (HashScanOpaque) palloc_object(HashScanOpaqueData);
 	HashScanPosInvalidate(so->currPos);
 	so->hashso_bucket_buf = InvalidBuffer;
 	so->hashso_split_bucket_buf = InvalidBuffer;
@@ -633,7 +632,7 @@ loop_top:
 
 	/* return statistics */
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 	stats->estimated_count = false;
 	stats->num_index_tuples = num_index_tuples;
 	stats->tuples_removed += tuples_removed;
diff --git a/src/backend/access/hash/hashsort.c b/src/backend/access/hash/hashsort.c
index 92ae3cf53f5..0fd41f4f4ca 100644
--- a/src/backend/access/hash/hashsort.c
+++ b/src/backend/access/hash/hashsort.c
@@ -59,7 +59,7 @@ struct HSpool
 HSpool *
 _h_spoolinit(Relation heap, Relation index, uint32 num_buckets)
 {
-	HSpool	   *hspool = (HSpool *) palloc0(sizeof(HSpool));
+	HSpool	   *hspool = palloc0_object(HSpool);
 
 	hspool->index = index;
 
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4b0c49f4bb0..7368e56033d 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1118,7 +1118,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	 */
 	if (flags & SO_TYPE_BITMAPSCAN)
 	{
-		BitmapHeapScanDesc bscan = palloc(sizeof(BitmapHeapScanDescData));
+		BitmapHeapScanDesc bscan = palloc_object(BitmapHeapScanDescData);
 
 		/*
 		 * Bitmap Heap scans do not have any fields that a normal Heap Scan
@@ -1127,7 +1127,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 		scan = (HeapScanDesc) bscan;
 	}
 	else
-		scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData));
+		scan = (HeapScanDesc) palloc_object(HeapScanDescData);
 
 	scan->rs_base.rs_rd = relation;
 	scan->rs_base.rs_snapshot = snapshot;
@@ -1186,7 +1186,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	 * when doing a parallel scan.
 	 */
 	if (parallel_scan != NULL)
-		scan->rs_parallelworkerdata = palloc(sizeof(ParallelBlockTableScanWorkerData));
+		scan->rs_parallelworkerdata = palloc_object(ParallelBlockTableScanWorkerData);
 	else
 		scan->rs_parallelworkerdata = NULL;
 
@@ -1195,7 +1195,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	 * initscan() and we don't want to allocate memory again
 	 */
 	if (nkeys > 0)
-		scan->rs_base.rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
+		scan->rs_base.rs_key = palloc_array(ScanKeyData, nkeys);
 	else
 		scan->rs_base.rs_key = NULL;
 
@@ -2022,7 +2022,7 @@ GetBulkInsertState(void)
 {
 	BulkInsertState bistate;
 
-	bistate = (BulkInsertState) palloc(sizeof(BulkInsertStateData));
+	bistate = (BulkInsertState) palloc_object(BulkInsertStateData);
 	bistate->strategy = GetAccessStrategy(BAS_BULKWRITE);
 	bistate->current_buf = InvalidBuffer;
 	bistate->next_free = InvalidBlockNumber;
@@ -6880,7 +6880,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
 	 * even member XIDs >= OldestXmin often won't be kept by second pass.
 	 */
 	nnewmembers = 0;
-	newmembers = palloc(sizeof(MultiXactMember) * nmembers);
+	newmembers = palloc_array(MultiXactMember, nmembers);
 	has_lockers = false;
 	update_xid = InvalidTransactionId;
 	update_committed = false;
@@ -8696,7 +8696,7 @@ bottomup_sort_and_shrink(TM_IndexDeleteOp *delstate)
 	Assert(delstate->ndeltids > 0);
 
 	/* Calculate per-heap-block count of TIDs */
-	blockgroups = palloc(sizeof(IndexDeleteCounts) * delstate->ndeltids);
+	blockgroups = palloc_array(IndexDeleteCounts, delstate->ndeltids);
 	for (int i = 0; i < delstate->ndeltids; i++)
 	{
 		TM_IndexDelete *ideltid = &delstate->deltids[i];
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index bcbac844bb6..dd4fe6bf62f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -81,7 +81,7 @@ heapam_slot_callbacks(Relation relation)
 static IndexFetchTableData *
 heapam_index_fetch_begin(Relation rel)
 {
-	IndexFetchHeapData *hscan = palloc0(sizeof(IndexFetchHeapData));
+	IndexFetchHeapData *hscan = palloc0_object(IndexFetchHeapData);
 
 	hscan->xs_base.rel = rel;
 	hscan->xs_cbuf = InvalidBuffer;
@@ -717,8 +717,8 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 
 	/* Preallocate values/isnull arrays */
 	natts = newTupDesc->natts;
-	values = (Datum *) palloc(natts * sizeof(Datum));
-	isnull = (bool *) palloc(natts * sizeof(bool));
+	values = palloc_array(Datum, natts);
+	isnull = palloc_array(bool, natts);
 
 	/* Initialize the rewrite operation */
 	rwstate = begin_heap_rewrite(OldHeap, NewHeap, OldestXmin, *xid_cutoff,
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 66ab48f0fe0..7ce3c5e2685 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -249,7 +249,7 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm
 	old_cxt = MemoryContextSwitchTo(rw_cxt);
 
 	/* Create and fill in the state struct */
-	state = palloc0(sizeof(RewriteStateData));
+	state = palloc0_object(RewriteStateData);
 
 	state->rs_old_rel = old_heap;
 	state->rs_new_rel = new_heap;
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 65bb0568a86..91e0b8c8a71 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -677,7 +677,7 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	 * of each rel.  It's convenient for code in lazy_scan_heap to always use
 	 * these temp copies.
 	 */
-	vacrel = (LVRelState *) palloc0(sizeof(LVRelState));
+	vacrel = palloc0_object(LVRelState);
 	vacrel->dbname = get_database_name(MyDatabaseId);
 	vacrel->relnamespace = get_namespace_name(RelationGetNamespace(rel));
 	vacrel->relname = pstrdup(RelationGetRelationName(rel));
@@ -697,7 +697,7 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	if (instrument && vacrel->nindexes > 0)
 	{
 		/* Copy index names used by instrumentation (not error reporting) */
-		indnames = palloc(sizeof(char *) * vacrel->nindexes);
+		indnames = palloc_array(char *, vacrel->nindexes);
 		for (int i = 0; i < vacrel->nindexes; i++)
 			indnames[i] = pstrdup(RelationGetRelationName(vacrel->indrels[i]));
 	}
@@ -3567,7 +3567,7 @@ dead_items_alloc(LVRelState *vacrel, int nworkers)
 	 * locally.
 	 */
 
-	dead_items_info = (VacDeadItemsInfo *) palloc(sizeof(VacDeadItemsInfo));
+	dead_items_info = palloc_object(VacDeadItemsInfo);
 	dead_items_info->max_bytes = vac_work_mem * (Size) 1024;
 	dead_items_info->num_items = 0;
 	vacrel->dead_items_info = dead_items_info;
diff --git a/src/backend/access/index/amvalidate.c b/src/backend/access/index/amvalidate.c
index 4cf237019ad..8d7e7171bd7 100644
--- a/src/backend/access/index/amvalidate.c
+++ b/src/backend/access/index/amvalidate.c
@@ -118,7 +118,7 @@ identify_opfamily_groups(CatCList *oprlist, CatCList *proclist)
 		}
 
 		/* Time for a new group */
-		thisgroup = (OpFamilyOpFuncGroup *) palloc(sizeof(OpFamilyOpFuncGroup));
+		thisgroup = palloc_object(OpFamilyOpFuncGroup);
 		if (oprform &&
 			(!procform ||
 			 (oprform->amoplefttype < procform->amproclefttype ||
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index 0cb27af1310..1e9eadb723e 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -81,7 +81,7 @@ RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
 {
 	IndexScanDesc scan;
 
-	scan = (IndexScanDesc) palloc(sizeof(IndexScanDescData));
+	scan = (IndexScanDesc) palloc_object(IndexScanDescData);
 
 	scan->heapRelation = NULL;	/* may be set later */
 	scan->xs_heapfetch = NULL;
@@ -94,11 +94,11 @@ RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
 	 * We allocate key workspace here, but it won't get filled until amrescan.
 	 */
 	if (nkeys > 0)
-		scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
+		scan->keyData = palloc_array(ScanKeyData, nkeys); 
 	else
 		scan->keyData = NULL;
 	if (norderbys > 0)
-		scan->orderByData = (ScanKey) palloc(sizeof(ScanKeyData) * norderbys);
+		scan->orderByData = palloc_array(ScanKeyData, norderbys);
 	else
 		scan->orderByData = NULL;
 
@@ -310,8 +310,8 @@ index_compute_xid_horizon_for_tuples(Relation irel,
 	delstate.bottomup = false;
 	delstate.bottomupfreespace = 0;
 	delstate.ndeltids = 0;
-	delstate.deltids = palloc(nitems * sizeof(TM_IndexDelete));
-	delstate.status = palloc(nitems * sizeof(TM_IndexStatus));
+	delstate.deltids = palloc_array(TM_IndexDelete, nitems);
+	delstate.status = palloc_array(TM_IndexStatus, nitems);
 
 	/* identify what the index tuples about to be deleted point to */
 	for (int i = 0; i < nitems; i++)
@@ -401,7 +401,7 @@ systable_beginscan(Relation heapRelation,
 	else
 		irel = NULL;
 
-	sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData));
+	sysscan = (SysScanDesc) palloc_object(SysScanDescData);
 
 	sysscan->heap_rel = heapRelation;
 	sysscan->irel = irel;
@@ -667,7 +667,7 @@ systable_beginscan_ordered(Relation heapRelation,
 		elog(WARNING, "using index \"%s\" despite IgnoreSystemIndexes",
 			 RelationGetRelationName(indexRelation));
 
-	sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData));
+	sysscan = (SysScanDesc) palloc_object(SysScanDescData);
 
 	sysscan->heap_rel = heapRelation;
 	sysscan->irel = indexRelation;
diff --git a/src/backend/access/nbtree/nbtdedup.c b/src/backend/access/nbtree/nbtdedup.c
index a746de45dd3..ec07ea3d123 100644
--- a/src/backend/access/nbtree/nbtdedup.c
+++ b/src/backend/access/nbtree/nbtdedup.c
@@ -82,7 +82,7 @@ _bt_dedup_pass(Relation rel, Buffer buf, IndexTuple newitem, Size newitemsz,
 	 * That ought to leave us with a good split point when pages full of
 	 * duplicates can be split several times.
 	 */
-	state = (BTDedupState) palloc(sizeof(BTDedupStateData));
+	state = (BTDedupState) palloc_object(BTDedupStateData);
 	state->deduplicate = true;
 	state->nmaxitems = 0;
 	state->maxpostingsize = Min(BTMaxItemSize / 2, INDEX_SIZE_MASK);
@@ -321,7 +321,7 @@ _bt_bottomupdel_pass(Relation rel, Buffer buf, Relation heapRel,
 	newitemsz += sizeof(ItemIdData);
 
 	/* Initialize deduplication state */
-	state = (BTDedupState) palloc(sizeof(BTDedupStateData));
+	state = (BTDedupState) palloc_object(BTDedupStateData);
 	state->deduplicate = true;
 	state->nmaxitems = 0;
 	state->maxpostingsize = BLCKSZ; /* We're not really deduplicating */
@@ -355,8 +355,8 @@ _bt_bottomupdel_pass(Relation rel, Buffer buf, Relation heapRel,
 	delstate.bottomup = true;
 	delstate.bottomupfreespace = Max(BLCKSZ / 16, newitemsz);
 	delstate.ndeltids = 0;
-	delstate.deltids = palloc(MaxTIDsPerBTreePage * sizeof(TM_IndexDelete));
-	delstate.status = palloc(MaxTIDsPerBTreePage * sizeof(TM_IndexStatus));
+	delstate.deltids = palloc_array(TM_IndexDelete, MaxTIDsPerBTreePage);
+	delstate.status = palloc_array(TM_IndexStatus, MaxTIDsPerBTreePage);
 
 	minoff = P_FIRSTDATAKEY(opaque);
 	maxoff = PageGetMaxOffsetNumber(page);
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 7c113c007e5..0af7e3feb40 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -2954,7 +2954,7 @@ _bt_deadblocks(Page page, OffsetNumber *deletable, int ndeletable,
 	 */
 	spacentids = ndeletable + 1;
 	ntids = 0;
-	tidblocks = (BlockNumber *) palloc(sizeof(BlockNumber) * spacentids);
+	tidblocks = palloc_array(BlockNumber, spacentids);
 
 	/*
 	 * First add the table block for the incoming newitem.  This is the one
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 30b43a4dd18..cfa8745cb6a 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -2975,7 +2975,7 @@ _bt_pendingfsm_init(Relation rel, BTVacState *vstate, bool cleanuponly)
 	vstate->maxbufsize = (int) maxbufsize;
 
 	/* Allocate buffer, indicate that there are currently 0 pending pages */
-	vstate->pendingpages = palloc(sizeof(BTPendingFSM) * vstate->bufsize);
+	vstate->pendingpages = palloc_array(BTPendingFSM, vstate->bufsize);
 	vstate->npendingpages = 0;
 }
 
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index fdff960c130..c87e4cfa42f 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -260,8 +260,7 @@ btgettuple(IndexScanDesc scan, ScanDirection dir)
 				 * just forget any excess entries.
 				 */
 				if (so->killedItems == NULL)
-					so->killedItems = (int *)
-						palloc(MaxTIDsPerBTreePage * sizeof(int));
+					so->killedItems = palloc_array(int, MaxTIDsPerBTreePage);
 				if (so->numKilled < MaxTIDsPerBTreePage)
 					so->killedItems[so->numKilled++] = so->currPos.itemIndex;
 			}
@@ -345,7 +344,7 @@ btbeginscan(Relation rel, int nkeys, int norderbys)
 	scan = RelationGetIndexScan(rel, nkeys, norderbys);
 
 	/* allocate private workspace */
-	so = (BTScanOpaque) palloc(sizeof(BTScanOpaqueData));
+	so = (BTScanOpaque) palloc_object(BTScanOpaqueData);
 	BTScanPosInvalidate(so->currPos);
 	BTScanPosInvalidate(so->markPos);
 	if (scan->numberOfKeys > 0)
@@ -1070,7 +1069,7 @@ btbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 
 	/* allocate stats if first time through, else re-use existing struct */
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 
 	/* Establish the vacuum cycle ID to use for this scan */
 	/* The ENSURE stuff ensures we clean up shared memory on failure */
@@ -1131,7 +1130,7 @@ btvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 		 * We handle the problem by making num_index_tuples an estimate in
 		 * cleanup-only case.
 		 */
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 		btvacuumscan(info, stats, NULL, NULL, 0);
 		stats->estimated_count = true;
 	}
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index 0605356ec9f..2b34e7eecfc 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -169,7 +169,7 @@ _bt_search(Relation rel, Relation heaprel, BTScanInsert key, Buffer *bufP,
 		 * page one level down, it usually ends up inserting a new pivot
 		 * tuple/downlink immediately after the location recorded here.
 		 */
-		new_stack = (BTStack) palloc(sizeof(BTStackData));
+		new_stack = (BTStack) palloc_object(BTStackData);
 		new_stack->bts_blkno = BufferGetBlockNumber(*bufP);
 		new_stack->bts_offset = offnum;
 		new_stack->bts_parent = stack_in;
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 454adaee7dc..bf70bf209a5 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -335,7 +335,7 @@ btbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	if (buildstate.btleader)
 		_bt_end_parallel(buildstate.btleader);
 
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 
 	result->heap_tuples = reltuples;
 	result->index_tuples = buildstate.indtuples;
@@ -366,7 +366,7 @@ static double
 _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
 					IndexInfo *indexInfo)
 {
-	BTSpool    *btspool = (BTSpool *) palloc0(sizeof(BTSpool));
+	BTSpool    *btspool = palloc0_object(BTSpool);
 	SortCoordinate coordinate = NULL;
 	double		reltuples = 0;
 
@@ -399,7 +399,7 @@ _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
 	 */
 	if (buildstate->btleader)
 	{
-		coordinate = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
+		coordinate = (SortCoordinate) palloc0_object(SortCoordinateData);
 		coordinate->isWorker = false;
 		coordinate->nParticipants =
 			buildstate->btleader->nparticipanttuplesorts;
@@ -440,7 +440,7 @@ _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
 	 */
 	if (indexInfo->ii_Unique)
 	{
-		BTSpool    *btspool2 = (BTSpool *) palloc0(sizeof(BTSpool));
+		BTSpool    *btspool2 = palloc0_object(BTSpool);
 		SortCoordinate coordinate2 = NULL;
 
 		/* Initialize secondary spool */
@@ -457,7 +457,7 @@ _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
 			 * tuplesort_begin_index_btree() about the basic high level
 			 * coordination of a parallel sort.
 			 */
-			coordinate2 = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
+			coordinate2 = (SortCoordinate) palloc0_object(SortCoordinateData);
 			coordinate2->isWorker = false;
 			coordinate2->nParticipants =
 				buildstate->btleader->nparticipanttuplesorts;
@@ -648,7 +648,7 @@ _bt_blwritepage(BTWriteState *wstate, BulkWriteBuffer buf, BlockNumber blkno)
 static BTPageState *
 _bt_pagestate(BTWriteState *wstate, uint32 level)
 {
-	BTPageState *state = (BTPageState *) palloc0(sizeof(BTPageState));
+	BTPageState *state = palloc0_object(BTPageState);
 
 	/* create initial page for level */
 	state->btps_buf = _bt_blnewpage(wstate, level);
@@ -1002,7 +1002,7 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, IndexTuple itup,
 	if (last_off == P_HIKEY)
 	{
 		Assert(state->btps_lowkey == NULL);
-		state->btps_lowkey = palloc0(sizeof(IndexTupleData));
+		state->btps_lowkey = palloc0_object(IndexTupleData);
 		state->btps_lowkey->t_info = sizeof(IndexTupleData);
 		BTreeTupleSetNAtts(state->btps_lowkey, 0, false);
 	}
@@ -1164,7 +1164,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
 		itup2 = tuplesort_getindextuple(btspool2->sortstate, true);
 
 		/* Prepare SortSupport data for each column */
-		sortKeys = (SortSupport) palloc0(keysz * sizeof(SortSupportData));
+		sortKeys = (SortSupport) palloc0_array(SortSupportData, keysz);
 
 		for (i = 0; i < keysz; i++)
 		{
@@ -1266,7 +1266,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
 		/* merge is unnecessary, deduplicate into posting lists */
 		BTDedupState dstate;
 
-		dstate = (BTDedupState) palloc(sizeof(BTDedupStateData));
+		dstate = (BTDedupState) palloc_object(BTDedupStateData);
 		dstate->deduplicate = true; /* unused */
 		dstate->nmaxitems = 0;	/* unused */
 		dstate->maxpostingsize = 0; /* set later */
@@ -1404,7 +1404,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
 	Sharedsort *sharedsort;
 	Sharedsort *sharedsort2;
 	BTSpool    *btspool = buildstate->spool;
-	BTLeader   *btleader = (BTLeader *) palloc0(sizeof(BTLeader));
+	BTLeader   *btleader = palloc0_object(BTLeader);
 	WalUsage   *walusage;
 	BufferUsage *bufferusage;
 	bool		leaderparticipates = true;
@@ -1693,7 +1693,7 @@ _bt_leader_participate_as_worker(BTBuildState *buildstate)
 	int			sortmem;
 
 	/* Allocate memory and initialize private spool */
-	leaderworker = (BTSpool *) palloc0(sizeof(BTSpool));
+	leaderworker = palloc0_object(BTSpool);
 	leaderworker->heap = buildstate->spool->heap;
 	leaderworker->index = buildstate->spool->index;
 	leaderworker->isunique = buildstate->spool->isunique;
@@ -1705,7 +1705,7 @@ _bt_leader_participate_as_worker(BTBuildState *buildstate)
 	else
 	{
 		/* Allocate memory for worker's own private secondary spool */
-		leaderworker2 = (BTSpool *) palloc0(sizeof(BTSpool));
+		leaderworker2 = palloc0_object(BTSpool);
 
 		/* Initialize worker's own secondary spool */
 		leaderworker2->heap = leaderworker->heap;
@@ -1796,7 +1796,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
 	indexRel = index_open(btshared->indexrelid, indexLockmode);
 
 	/* Initialize worker's own spool */
-	btspool = (BTSpool *) palloc0(sizeof(BTSpool));
+	btspool = palloc0_object(BTSpool);
 	btspool->heap = heapRel;
 	btspool->index = indexRel;
 	btspool->isunique = btshared->isunique;
@@ -1813,7 +1813,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
 	else
 	{
 		/* Allocate memory for worker's own private secondary spool */
-		btspool2 = (BTSpool *) palloc0(sizeof(BTSpool));
+		btspool2 = palloc0_object(BTSpool);
 
 		/* Initialize worker's own secondary spool */
 		btspool2->heap = btspool->heap;
@@ -1874,7 +1874,7 @@ _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2,
 	IndexInfo  *indexInfo;
 
 	/* Initialize local tuplesort coordination state */
-	coordinate = palloc0(sizeof(SortCoordinateData));
+	coordinate = palloc0_object(SortCoordinateData);
 	coordinate->isWorker = true;
 	coordinate->nParticipants = -1;
 	coordinate->sharedsort = sharedsort;
@@ -1901,7 +1901,7 @@ _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2,
 		 * worker).  Worker processes are generally permitted to allocate
 		 * work_mem independently.
 		 */
-		coordinate2 = palloc0(sizeof(SortCoordinateData));
+		coordinate2 = palloc0_object(SortCoordinateData);
 		coordinate2->isWorker = true;
 		coordinate2->nParticipants = -1;
 		coordinate2->sharedsort = sharedsort2;
diff --git a/src/backend/access/nbtree/nbtsplitloc.c b/src/backend/access/nbtree/nbtsplitloc.c
index f0082f88c76..651ab013025 100644
--- a/src/backend/access/nbtree/nbtsplitloc.c
+++ b/src/backend/access/nbtree/nbtsplitloc.c
@@ -197,7 +197,7 @@ _bt_findsplitloc(Relation rel,
 	 * between tuples will be legal).
 	 */
 	state.maxsplits = maxoff;
-	state.splits = palloc(sizeof(SplitPoint) * state.maxsplits);
+	state.splits = palloc_array(SplitPoint, state.maxsplits);
 	state.nsplits = 0;
 
 	/*
diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c
index d4a26de06a3..dbe67c166fd 100644
--- a/src/backend/access/nbtree/nbtxlog.c
+++ b/src/backend/access/nbtree/nbtxlog.c
@@ -469,7 +469,7 @@ btree_xlog_dedup(XLogReaderState *record)
 		BTDedupInterval *intervals;
 		Page		newpage;
 
-		state = (BTDedupState) palloc(sizeof(BTDedupStateData));
+		state = palloc_object(BTDedupStateData);
 		state->deduplicate = true;	/* unused */
 		state->nmaxitems = 0;	/* unused */
 		/* Conservatively use larger maxpostingsize than primary */
diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c
index 4eadb518776..1e1e61d2044 100644
--- a/src/backend/access/spgist/spgdoinsert.c
+++ b/src/backend/access/spgist/spgdoinsert.c
@@ -89,7 +89,7 @@ addNode(SpGistState *state, SpGistInnerTuple tuple, Datum label, int offset)
 	else if (offset > tuple->nNodes)
 		elog(ERROR, "invalid offset for adding node to SPGiST inner tuple");
 
-	nodes = palloc(sizeof(SpGistNodeTuple) * (tuple->nNodes + 1));
+	nodes = palloc_array(SpGistNodeTuple, tuple->nNodes + 1);
 	SGITITERATE(tuple, i, node)
 	{
 		if (i < offset)
@@ -409,8 +409,8 @@ moveLeafs(Relation index, SpGistState *state,
 
 	/* Locate the tuples to be moved, and count up the space needed */
 	i = PageGetMaxOffsetNumber(current->page);
-	toDelete = (OffsetNumber *) palloc(sizeof(OffsetNumber) * i);
-	toInsert = (OffsetNumber *) palloc(sizeof(OffsetNumber) * (i + 1));
+	toDelete = palloc_array(OffsetNumber, i);
+	toInsert = palloc_array(OffsetNumber, i + 1);
 
 	size = newLeafTuple->size + sizeof(ItemIdData);
 
@@ -634,7 +634,7 @@ checkAllTheSame(spgPickSplitIn *in, spgPickSplitOut *out, bool tooBig,
 	{
 		Datum		theLabel = out->nodeLabels[theNode];
 
-		out->nodeLabels = (Datum *) palloc(sizeof(Datum) * out->nNodes);
+		out->nodeLabels = palloc_array(Datum, out->nNodes);
 		for (i = 0; i < out->nNodes; i++)
 			out->nodeLabels[i] = theLabel;
 	}
@@ -717,12 +717,12 @@ doPickSplit(Relation index, SpGistState *state,
 	 */
 	max = PageGetMaxOffsetNumber(current->page);
 	n = max + 1;
-	in.datums = (Datum *) palloc(sizeof(Datum) * n);
-	toDelete = (OffsetNumber *) palloc(sizeof(OffsetNumber) * n);
-	toInsert = (OffsetNumber *) palloc(sizeof(OffsetNumber) * n);
-	oldLeafs = (SpGistLeafTuple *) palloc(sizeof(SpGistLeafTuple) * n);
-	newLeafs = (SpGistLeafTuple *) palloc(sizeof(SpGistLeafTuple) * n);
-	leafPageSelect = (uint8 *) palloc(sizeof(uint8) * n);
+	in.datums = palloc_array(Datum, n);
+	toDelete = palloc_array(OffsetNumber, n);
+	toInsert = palloc_array(OffsetNumber, n);
+	oldLeafs = palloc_array(SpGistLeafTuple, n);
+	newLeafs = palloc_array(SpGistLeafTuple, n);
+	leafPageSelect = palloc_array(uint8, n);
 
 	STORE_STATE(state, xlrec.stateSrc);
 
@@ -858,7 +858,7 @@ doPickSplit(Relation index, SpGistState *state,
 		out.hasPrefix = false;
 		out.nNodes = 1;
 		out.nodeLabels = NULL;
-		out.mapTuplesToNodes = palloc0(sizeof(int) * in.nTuples);
+		out.mapTuplesToNodes = palloc0_array(int, in.nTuples);
 
 		/*
 		 * Form new leaf tuples and count up the total space needed.
@@ -914,8 +914,8 @@ doPickSplit(Relation index, SpGistState *state,
 	 * out.nNodes with a value larger than the number of tuples on the input
 	 * page, we can't allocate these arrays before here.
 	 */
-	nodes = (SpGistNodeTuple *) palloc(sizeof(SpGistNodeTuple) * out.nNodes);
-	leafSizes = (int *) palloc0(sizeof(int) * out.nNodes);
+	nodes = palloc_array(SpGistNodeTuple, out.nNodes);
+	leafSizes = palloc0_array(int, out.nNodes);
 
 	/*
 	 * Form nodes of inner tuple and inner tuple itself
@@ -1054,7 +1054,7 @@ doPickSplit(Relation index, SpGistState *state,
 		 * do so, even if totalLeafSizes is less than the available space,
 		 * because we can't split a group across pages.
 		 */
-		nodePageSelect = (uint8 *) palloc(sizeof(uint8) * out.nNodes);
+		nodePageSelect = palloc_array(uint8, out.nNodes);
 
 		curspace = currentFreeSpace;
 		newspace = PageGetExactFreeSpace(BufferGetPage(newLeafBuffer));
@@ -1740,8 +1740,7 @@ spgSplitNodeAction(Relation index, SpGistState *state,
 	 * Construct new prefix tuple with requested number of nodes.  We'll fill
 	 * in the childNodeN'th node's downlink below.
 	 */
-	nodes = (SpGistNodeTuple *) palloc(sizeof(SpGistNodeTuple) *
-									   out->result.splitTuple.prefixNNodes);
+	nodes = palloc_array(SpGistNodeTuple, out->result.splitTuple.prefixNNodes);
 
 	for (i = 0; i < out->result.splitTuple.prefixNNodes; i++)
 	{
@@ -1769,7 +1768,7 @@ spgSplitNodeAction(Relation index, SpGistState *state,
 	 * same node datums, but with the prefix specified by the picksplit
 	 * function.
 	 */
-	nodes = palloc(sizeof(SpGistNodeTuple) * innerTuple->nNodes);
+	nodes = palloc_array(SpGistNodeTuple, innerTuple->nNodes);
 	SGITITERATE(innerTuple, i, node)
 	{
 		nodes[i] = node;
diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c
index 6a61e093fa0..dda99755f66 100644
--- a/src/backend/access/spgist/spginsert.c
+++ b/src/backend/access/spgist/spginsert.c
@@ -140,7 +140,7 @@ spgbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 						  true);
 	}
 
-	result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
+	result = palloc0_object(IndexBuildResult);
 	result->heap_tuples = reltuples;
 	result->index_tuples = buildstate.indtuples;
 
diff --git a/src/backend/access/spgist/spgkdtreeproc.c b/src/backend/access/spgist/spgkdtreeproc.c
index d6989759e5f..f0167d6ffa6 100644
--- a/src/backend/access/spgist/spgkdtreeproc.c
+++ b/src/backend/access/spgist/spgkdtreeproc.c
@@ -114,7 +114,7 @@ spg_kd_picksplit(PG_FUNCTION_ARGS)
 	SortedPoint *sorted;
 	double		coord;
 
-	sorted = palloc(sizeof(*sorted) * in->nTuples);
+	sorted = palloc_array(SortedPoint, in->nTuples);
 	for (i = 0; i < in->nTuples; i++)
 	{
 		sorted[i].p = DatumGetPointP(in->datums[i]);
@@ -132,8 +132,8 @@ spg_kd_picksplit(PG_FUNCTION_ARGS)
 	out->nNodes = 2;
 	out->nodeLabels = NULL;		/* we don't need node labels */
 
-	out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	/*
 	 * Note: points that have coordinates exactly equal to coord may get
@@ -259,7 +259,7 @@ spg_kd_inner_consistent(PG_FUNCTION_ARGS)
 	if (!which)
 		PG_RETURN_VOID();
 
-	out->nodeNumbers = (int *) palloc(sizeof(int) * 2);
+	out->nodeNumbers = palloc_array(int, 2);
 
 	/*
 	 * When ordering scan keys are specified, we've to calculate distance for
@@ -273,8 +273,8 @@ spg_kd_inner_consistent(PG_FUNCTION_ARGS)
 		BOX			infArea;
 		BOX		   *area;
 
-		out->distances = (double **) palloc(sizeof(double *) * in->nNodes);
-		out->traversalValues = (void **) palloc(sizeof(void *) * in->nNodes);
+		out->distances = palloc_array(double *, in->nNodes);
+		out->traversalValues = palloc_array(void *, in->nNodes);
 
 		if (in->level == 0)
 		{
@@ -335,7 +335,7 @@ spg_kd_inner_consistent(PG_FUNCTION_ARGS)
 	}
 
 	/* Set up level increments, too */
-	out->levelAdds = (int *) palloc(sizeof(int) * 2);
+	out->levelAdds = palloc_array(int, 2);
 	out->levelAdds[0] = 1;
 	out->levelAdds[1] = 1;
 
diff --git a/src/backend/access/spgist/spgproc.c b/src/backend/access/spgist/spgproc.c
index 660009291da..05d560b5ad9 100644
--- a/src/backend/access/spgist/spgproc.c
+++ b/src/backend/access/spgist/spgproc.c
@@ -64,7 +64,7 @@ spg_key_orderbys_distances(Datum key, bool isLeaf,
 						   ScanKey orderbys, int norderbys)
 {
 	int			sk_num;
-	double	   *distances = (double *) palloc(norderbys * sizeof(double)),
+	double	   *distances = palloc_array(double, norderbys),
 			   *distance = distances;
 
 	for (sk_num = 0; sk_num < norderbys; ++sk_num, ++orderbys, ++distance)
@@ -81,7 +81,7 @@ spg_key_orderbys_distances(Datum key, bool isLeaf,
 BOX *
 box_copy(BOX *orig)
 {
-	BOX		   *result = palloc(sizeof(BOX));
+	BOX		   *result = palloc_object(BOX);
 
 	*result = *orig;
 	return result;
diff --git a/src/backend/access/spgist/spgquadtreeproc.c b/src/backend/access/spgist/spgquadtreeproc.c
index 3e8cfa1709a..75ffb09ca5a 100644
--- a/src/backend/access/spgist/spgquadtreeproc.c
+++ b/src/backend/access/spgist/spgquadtreeproc.c
@@ -82,7 +82,7 @@ getQuadrant(Point *centroid, Point *tst)
 static BOX *
 getQuadrantArea(BOX *bbox, Point *centroid, int quadrant)
 {
-	BOX		   *result = (BOX *) palloc(sizeof(BOX));
+	BOX		   *result = palloc_object(BOX);
 
 	switch (quadrant)
 	{
@@ -177,11 +177,11 @@ spg_quad_picksplit(PG_FUNCTION_ARGS)
 	/* Use the median values of x and y as the centroid point */
 	Point	  **sorted;
 
-	sorted = palloc(sizeof(*sorted) * in->nTuples);
+	sorted = palloc_array(Point *, in->nTuples);
 	for (i = 0; i < in->nTuples; i++)
 		sorted[i] = DatumGetPointP(in->datums[i]);
 
-	centroid = palloc(sizeof(*centroid));
+	centroid = palloc_object(Point);
 
 	qsort(sorted, in->nTuples, sizeof(*sorted), x_cmp);
 	centroid->x = sorted[in->nTuples >> 1]->x;
@@ -189,7 +189,7 @@ spg_quad_picksplit(PG_FUNCTION_ARGS)
 	centroid->y = sorted[in->nTuples >> 1]->y;
 #else
 	/* Use the average values of x and y as the centroid point */
-	centroid = palloc0(sizeof(*centroid));
+	centroid = palloc0_object(Point);
 
 	for (i = 0; i < in->nTuples; i++)
 	{
@@ -207,8 +207,8 @@ spg_quad_picksplit(PG_FUNCTION_ARGS)
 	out->nNodes = 4;
 	out->nodeLabels = NULL;		/* we don't need node labels */
 
-	out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	for (i = 0; i < in->nTuples; i++)
 	{
@@ -246,8 +246,8 @@ spg_quad_inner_consistent(PG_FUNCTION_ARGS)
 	 */
 	if (in->norderbys > 0)
 	{
-		out->distances = (double **) palloc(sizeof(double *) * in->nNodes);
-		out->traversalValues = (void **) palloc(sizeof(void *) * in->nNodes);
+		out->distances = palloc_array(double *, in->nNodes);
+		out->traversalValues = palloc_array(void *, in->nNodes);
 
 		if (in->level == 0)
 		{
@@ -270,7 +270,7 @@ spg_quad_inner_consistent(PG_FUNCTION_ARGS)
 	{
 		/* Report that all nodes should be visited */
 		out->nNodes = in->nNodes;
-		out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
+		out->nodeNumbers = palloc_array(int, in->nNodes);
 		for (i = 0; i < in->nNodes; i++)
 		{
 			out->nodeNumbers[i] = i;
@@ -368,12 +368,12 @@ spg_quad_inner_consistent(PG_FUNCTION_ARGS)
 			break;				/* no need to consider remaining conditions */
 	}
 
-	out->levelAdds = palloc(sizeof(int) * 4);
+	out->levelAdds = palloc_array(int, 4);
 	for (i = 0; i < 4; ++i)
 		out->levelAdds[i] = 1;
 
 	/* We must descend into the quadrant(s) identified by which */
-	out->nodeNumbers = (int *) palloc(sizeof(int) * 4);
+	out->nodeNumbers = palloc_array(int, 4);
 	out->nNodes = 0;
 
 	for (i = 1; i <= 4; i++)
diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c
index 25893050c58..05b3799e0e2 100644
--- a/src/backend/access/spgist/spgscan.c
+++ b/src/backend/access/spgist/spgscan.c
@@ -309,9 +309,9 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
 
 	scan = RelationGetIndexScan(rel, keysz, orderbysz);
 
-	so = (SpGistScanOpaque) palloc0(sizeof(SpGistScanOpaqueData));
+	so = palloc0_object(SpGistScanOpaqueData);
 	if (keysz > 0)
-		so->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * keysz);
+		so->keyData = palloc_array(ScanKeyData, keysz);
 	else
 		so->keyData = NULL;
 	initSpGistState(&so->state, scan->indexRelation);
@@ -336,16 +336,12 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
 	if (scan->numberOfOrderBys > 0)
 	{
 		/* This will be filled in spgrescan, but allocate the space here */
-		so->orderByTypes = (Oid *)
-			palloc(sizeof(Oid) * scan->numberOfOrderBys);
-		so->nonNullOrderByOffsets = (int *)
-			palloc(sizeof(int) * scan->numberOfOrderBys);
+		so->orderByTypes = palloc_array(Oid, scan->numberOfOrderBys);
+		so->nonNullOrderByOffsets = palloc_array(int, scan->numberOfOrderBys);
 
 		/* These arrays have constant contents, so we can fill them now */
-		so->zeroDistances = (double *)
-			palloc(sizeof(double) * scan->numberOfOrderBys);
-		so->infDistances = (double *)
-			palloc(sizeof(double) * scan->numberOfOrderBys);
+		so->zeroDistances = palloc_array(double, scan->numberOfOrderBys);
+		so->infDistances = palloc_array(double, scan->numberOfOrderBys);
 
 		for (i = 0; i < scan->numberOfOrderBys; i++)
 		{
@@ -353,10 +349,8 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
 			so->infDistances[i] = get_float8_infinity();
 		}
 
-		scan->xs_orderbyvals = (Datum *)
-			palloc0(sizeof(Datum) * scan->numberOfOrderBys);
-		scan->xs_orderbynulls = (bool *)
-			palloc(sizeof(bool) * scan->numberOfOrderBys);
+		scan->xs_orderbyvals = palloc0_array(Datum, scan->numberOfOrderBys);
+		scan->xs_orderbynulls = palloc_array(bool, scan->numberOfOrderBys);
 		memset(scan->xs_orderbynulls, true,
 			   sizeof(bool) * scan->numberOfOrderBys);
 	}
@@ -690,7 +684,7 @@ spgInnerTest(SpGistScanOpaque so, SpGistSearchItem *item,
 	{
 		/* force all children to be visited */
 		out.nNodes = nNodes;
-		out.nodeNumbers = (int *) palloc(sizeof(int) * nNodes);
+		out.nodeNumbers = palloc_array(int, nNodes);
 		for (i = 0; i < nNodes; i++)
 			out.nodeNumbers[i] = i;
 	}
@@ -703,7 +697,7 @@ spgInnerTest(SpGistScanOpaque so, SpGistSearchItem *item,
 	{
 		/* collect node pointers */
 		SpGistNodeTuple node;
-		SpGistNodeTuple *nodes = (SpGistNodeTuple *) palloc(sizeof(SpGistNodeTuple) * nNodes);
+		SpGistNodeTuple *nodes = palloc_array(SpGistNodeTuple, nNodes);
 
 		SGITITERATE(innerTuple, i, node)
 		{
@@ -972,8 +966,7 @@ storeGettuple(SpGistScanOpaque so, ItemPointer heapPtr,
 			so->distances[so->nPtrs] = NULL;
 		else
 		{
-			IndexOrderByDistance *distances =
-				palloc(sizeof(distances[0]) * so->numberOfOrderBys);
+			IndexOrderByDistance *distances = palloc_array(IndexOrderByDistance, so->numberOfOrderBys);
 			int			i;
 
 			for (i = 0; i < so->numberOfOrderBys; i++)
diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c
index 91f4ab260c2..09be7ffe47e 100644
--- a/src/backend/access/spgist/spgtextproc.c
+++ b/src/backend/access/spgist/spgtextproc.c
@@ -230,8 +230,7 @@ spg_text_choose(PG_FUNCTION_ARGS)
 					formTextDatum(prefixStr, commonLen);
 			}
 			out->result.splitTuple.prefixNNodes = 1;
-			out->result.splitTuple.prefixNodeLabels =
-				(Datum *) palloc(sizeof(Datum));
+			out->result.splitTuple.prefixNodeLabels = palloc_object(Datum);
 			out->result.splitTuple.prefixNodeLabels[0] =
 				Int16GetDatum(*(unsigned char *) (prefixStr + commonLen));
 
@@ -303,7 +302,7 @@ spg_text_choose(PG_FUNCTION_ARGS)
 		out->result.splitTuple.prefixHasPrefix = in->hasPrefix;
 		out->result.splitTuple.prefixPrefixDatum = in->prefixDatum;
 		out->result.splitTuple.prefixNNodes = 1;
-		out->result.splitTuple.prefixNodeLabels = (Datum *) palloc(sizeof(Datum));
+		out->result.splitTuple.prefixNodeLabels = palloc_object(Datum);
 		out->result.splitTuple.prefixNodeLabels[0] = Int16GetDatum(-2);
 		out->result.splitTuple.childNodeN = 0;
 		out->result.splitTuple.postfixHasPrefix = false;
@@ -371,7 +370,7 @@ spg_text_picksplit(PG_FUNCTION_ARGS)
 	}
 
 	/* Extract the node label (first non-common byte) from each value */
-	nodes = (spgNodePtr *) palloc(sizeof(spgNodePtr) * in->nTuples);
+	nodes = palloc_array(spgNodePtr, in->nTuples);
 
 	for (i = 0; i < in->nTuples; i++)
 	{
@@ -394,9 +393,9 @@ spg_text_picksplit(PG_FUNCTION_ARGS)
 
 	/* And emit results */
 	out->nNodes = 0;
-	out->nodeLabels = (Datum *) palloc(sizeof(Datum) * in->nTuples);
-	out->mapTuplesToNodes = (int *) palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = (Datum *) palloc(sizeof(Datum) * in->nTuples);
+	out->nodeLabels = palloc_array(Datum, in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	for (i = 0; i < in->nTuples; i++)
 	{
@@ -476,9 +475,9 @@ spg_text_inner_consistent(PG_FUNCTION_ARGS)
 	 * and see if it's consistent with the query.  If so, emit an entry into
 	 * the output arrays.
 	 */
-	out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
-	out->levelAdds = (int *) palloc(sizeof(int) * in->nNodes);
-	out->reconstructedValues = (Datum *) palloc(sizeof(Datum) * in->nNodes);
+	out->nodeNumbers = palloc_array(int, in->nNodes);
+	out->levelAdds = palloc_array(int, in->nNodes);
+	out->reconstructedValues = palloc_array(Datum, in->nNodes);
 	out->nNodes = 0;
 
 	for (i = 0; i < in->nNodes; i++)
diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c
index 87c31da71a5..a60ec85e8be 100644
--- a/src/backend/access/spgist/spgutils.c
+++ b/src/backend/access/spgist/spgutils.c
@@ -1177,7 +1177,7 @@ spgExtractNodeLabels(SpGistState *state, SpGistInnerTuple innerTuple)
 	}
 	else
 	{
-		nodeLabels = (Datum *) palloc(sizeof(Datum) * innerTuple->nNodes);
+		nodeLabels = palloc_array(Datum, innerTuple->nNodes);
 		SGITITERATE(innerTuple, i, node)
 		{
 			if (IndexTupleHasNulls(node))
diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c
index 71ef2e5036f..cb5671c1a4e 100644
--- a/src/backend/access/spgist/spgvacuum.c
+++ b/src/backend/access/spgist/spgvacuum.c
@@ -76,7 +76,7 @@ spgAddPendingTID(spgBulkDeleteState *bds, const ItemPointerData *tid)
 		listLink = &pitem->next;
 	}
 	/* not there, so append new entry */
-	pitem = (spgVacPendingItem *) palloc(sizeof(spgVacPendingItem));
+	pitem = palloc_object(spgVacPendingItem);
 	pitem->tid = *tid;
 	pitem->done = false;
 	pitem->next = NULL;
@@ -954,7 +954,7 @@ spgbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 
 	/* allocate stats if first time through, else re-use existing struct */
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 	bds.info = info;
 	bds.stats = stats;
 	bds.callback = callback;
@@ -994,7 +994,7 @@ spgvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 	 */
 	if (stats == NULL)
 	{
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 		bds.info = info;
 		bds.stats = stats;
 		bds.callback = dummy_callback;
diff --git a/src/backend/access/spgist/spgxlog.c b/src/backend/access/spgist/spgxlog.c
index b7110302b98..f635be0698f 100644
--- a/src/backend/access/spgist/spgxlog.c
+++ b/src/backend/access/spgist/spgxlog.c
@@ -901,7 +901,7 @@ spgRedoVacuumRedirect(XLogReaderState *record)
 			int			max = PageGetMaxOffsetNumber(page);
 			OffsetNumber *toDelete;
 
-			toDelete = palloc(sizeof(OffsetNumber) * max);
+			toDelete = palloc_array(OffsetNumber, max);
 
 			for (i = xldata->firstPlaceholder; i <= max; i++)
 				toDelete[i - xldata->firstPlaceholder] = i;
diff --git a/src/backend/access/tablesample/bernoulli.c b/src/backend/access/tablesample/bernoulli.c
index 5e1c5d2b723..cce603d1b7f 100644
--- a/src/backend/access/tablesample/bernoulli.c
+++ b/src/backend/access/tablesample/bernoulli.c
@@ -126,7 +126,7 @@ bernoulli_samplescangetsamplesize(PlannerInfo *root,
 static void
 bernoulli_initsamplescan(SampleScanState *node, int eflags)
 {
-	node->tsm_state = palloc0(sizeof(BernoulliSamplerData));
+	node->tsm_state = palloc0_object(BernoulliSamplerData);
 }
 
 /*
diff --git a/src/backend/access/tablesample/system.c b/src/backend/access/tablesample/system.c
index 8db813b89fc..c6740dbdd1b 100644
--- a/src/backend/access/tablesample/system.c
+++ b/src/backend/access/tablesample/system.c
@@ -129,7 +129,7 @@ system_samplescangetsamplesize(PlannerInfo *root,
 static void
 system_initsamplescan(SampleScanState *node, int eflags)
 {
-	node->tsm_state = palloc0(sizeof(SystemSamplerData));
+	node->tsm_state = palloc0_object(SystemSamplerData);
 }
 
 /*
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 9d5f130af7e..9d56e886e28 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -549,8 +549,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
 	 * Note we have the same race condition here as above: j could be 0 at the
 	 * end of the loop.
 	 */
-	newMembers = (MultiXactMember *)
-		palloc(sizeof(MultiXactMember) * (nmembers + 1));
+	newMembers = palloc_array(MultiXactMember, nmembers + 1); 
 
 	for (i = 0, j = 0; i < nmembers; i++)
 	{
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index 94db1ec3012..8428103eba4 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -186,7 +186,7 @@ CreateParallelContext(const char *library_name, const char *function_name,
 	oldcontext = MemoryContextSwitchTo(TopTransactionContext);
 
 	/* Initialize a new ParallelContext. */
-	pcxt = palloc0(sizeof(ParallelContext));
+	pcxt = palloc0_object(ParallelContext);
 	pcxt->subid = GetCurrentSubTransactionId();
 	pcxt->nworkers = nworkers;
 	pcxt->nworkers_to_launch = nworkers;
@@ -453,7 +453,7 @@ InitializeParallelDSM(ParallelContext *pcxt)
 					   clientconninfospace);
 
 		/* Allocate space for worker information. */
-		pcxt->worker = palloc0(sizeof(ParallelWorkerInfo) * pcxt->nworkers);
+		pcxt->worker = palloc0_array(ParallelWorkerInfo, pcxt->nworkers);
 
 		/*
 		 * Establish error queues in dynamic shared memory.
@@ -648,8 +648,7 @@ LaunchParallelWorkers(ParallelContext *pcxt)
 	 */
 	if (pcxt->nworkers_launched > 0)
 	{
-		pcxt->known_attached_workers =
-			palloc0(sizeof(bool) * pcxt->nworkers_launched);
+		pcxt->known_attached_workers = palloc0_array(bool, pcxt->nworkers_launched);
 		pcxt->nknown_attached_workers = 0;
 	}
 
diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index ec3e323ec0c..b8af25e82d1 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -87,7 +87,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 	/* Timeline 1 does not have a history file, so no need to check */
 	if (targetTLI == 1)
 	{
-		entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
+		entry = palloc_object(TimeLineHistoryEntry);
 		entry->tli = targetTLI;
 		entry->begin = entry->end = InvalidXLogRecPtr;
 		return list_make1(entry);
@@ -110,7 +110,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 					(errcode_for_file_access(),
 					 errmsg("could not open file \"%s\": %m", path)));
 		/* Not there, so assume no parents */
-		entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
+		entry = palloc_object(TimeLineHistoryEntry);
 		entry->tli = targetTLI;
 		entry->begin = entry->end = InvalidXLogRecPtr;
 		return list_make1(entry);
@@ -175,7 +175,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 
 		lasttli = tli;
 
-		entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
+		entry = palloc_object(TimeLineHistoryEntry);
 		entry->tli = tli;
 		entry->begin = prevend;
 		entry->end = ((uint64) (switchpoint_hi)) << 32 | (uint64) switchpoint_lo;
@@ -198,7 +198,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 	 * Create one more entry for the "tip" of the timeline, which has no entry
 	 * in the history file.
 	 */
-	entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
+	entry = palloc_object(TimeLineHistoryEntry);
 	entry->tli = targetTLI;
 	entry->begin = prevend;
 	entry->end = InvalidXLogRecPtr;
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 89d0bfa7760..ae43688b34c 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -684,7 +684,7 @@ GetPreparedTransactionList(GlobalTransaction *gxacts)
 	}
 
 	num = TwoPhaseState->numPrepXacts;
-	array = (GlobalTransaction) palloc(sizeof(GlobalTransactionData) * num);
+	array = palloc_array(GlobalTransactionData, num);
 	*gxacts = array;
 	for (i = 0; i < num; i++)
 		memcpy(array + i, TwoPhaseState->prepXacts[i],
@@ -750,7 +750,7 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
 		 * Collect all the 2PC status information that we will format and send
 		 * out as a result set.
 		 */
-		status = (Working_State *) palloc(sizeof(Working_State));
+		status = palloc_object(Working_State);
 		funcctx->user_fctx = status;
 
 		status->ngxacts = GetPreparedTransactionList(&status->array);
@@ -1027,7 +1027,7 @@ save_state_data(const void *data, uint32 len)
 
 	if (padlen > records.bytes_free)
 	{
-		records.tail->next = palloc0(sizeof(StateFileChunk));
+		records.tail->next = palloc0_object(StateFileChunk);
 		records.tail = records.tail->next;
 		records.tail->len = 0;
 		records.tail->next = NULL;
@@ -1062,7 +1062,7 @@ StartPrepare(GlobalTransaction gxact)
 	SharedInvalidationMessage *invalmsgs;
 
 	/* Initialize linked list */
-	records.head = palloc0(sizeof(StateFileChunk));
+	records.head = palloc0_object(StateFileChunk);
 	records.head->len = 0;
 	records.head->next = NULL;
 
@@ -1453,7 +1453,7 @@ XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len)
 	if (len != NULL)
 		*len = XLogRecGetDataLen(xlogreader);
 
-	*buf = palloc(sizeof(char) * XLogRecGetDataLen(xlogreader));
+	*buf = palloc_array(char, XLogRecGetDataLen(xlogreader));
 	memcpy(*buf, XLogRecGetData(xlogreader), sizeof(char) * XLogRecGetDataLen(xlogreader));
 
 	XLogReaderFree(xlogreader);
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 092e197eba3..025dd0be5fc 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -664,7 +664,7 @@ AssignTransactionId(TransactionState s)
 		TransactionState *parents;
 		size_t		parentOffset = 0;
 
-		parents = palloc(sizeof(TransactionState) * s->nestingLevel);
+		parents = palloc_array(TransactionState, s->nestingLevel);
 		while (p != NULL && !FullTransactionIdIsValid(p->fullTransactionId))
 		{
 			parents[parentOffset++] = p;
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 22d0a2e8c3a..e81f43f5256 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4902,7 +4902,7 @@ void
 LocalProcessControlFile(bool reset)
 {
 	Assert(reset || ControlFile == NULL);
-	ControlFile = palloc(sizeof(ControlFileData));
+	ControlFile = palloc_object(ControlFileData);
 	ReadControlFile();
 }
 
@@ -9135,7 +9135,7 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
 				continue;
 			}
 
-			ti = palloc(sizeof(tablespaceinfo));
+			ti = palloc_object(tablespaceinfo);
 			ti->oid = tsoid;
 			ti->path = pstrdup(linkpath);
 			ti->rpath = relpath;
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 3e45fce43ed..ad6e44b6064 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -90,7 +90,7 @@ pg_backup_start(PG_FUNCTION_ARGS)
 	}
 
 	oldcontext = MemoryContextSwitchTo(backupcontext);
-	backup_state = (BackupState *) palloc0(sizeof(BackupState));
+	backup_state = palloc0_object(BackupState);
 	tablespace_map = makeStringInfo();
 	MemoryContextSwitchTo(oldcontext);
 
diff --git a/src/backend/access/transam/xlogprefetcher.c b/src/backend/access/transam/xlogprefetcher.c
index ed3aacabc98..ccc29192c5a 100644
--- a/src/backend/access/transam/xlogprefetcher.c
+++ b/src/backend/access/transam/xlogprefetcher.c
@@ -364,7 +364,7 @@ XLogPrefetcherAllocate(XLogReaderState *reader)
 	XLogPrefetcher *prefetcher;
 	HASHCTL		ctl;
 
-	prefetcher = palloc0(sizeof(XLogPrefetcher));
+	prefetcher = palloc0_object(XLogPrefetcher);
 	prefetcher->reader = reader;
 
 	ctl.keysize = sizeof(RelFileLocator);
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 21b8f179ba0..2e03bc1cdf2 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -559,7 +559,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 	 * Set the WAL reading processor now, as it will be needed when reading
 	 * the checkpoint record required (backup_label or not).
 	 */
-	private = palloc0(sizeof(XLogPageReadPrivate));
+	private = palloc0_object(XLogPageReadPrivate);
 	xlogreader =
 		XLogReaderAllocate(wal_segment_size, NULL,
 						   XL_ROUTINE(.page_read = &XLogPageRead,
@@ -1416,7 +1416,7 @@ read_tablespace_map(List **tablespaces)
 						 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
 			str[n++] = '\0';
 
-			ti = palloc0(sizeof(tablespaceinfo));
+			ti = palloc0_object(tablespaceinfo);
 			errno = 0;
 			ti->oid = strtoul(str, &endp, 10);
 			if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
@@ -1467,7 +1467,7 @@ read_tablespace_map(List **tablespaces)
 EndOfWalRecoveryInfo *
 FinishWalRecovery(void)
 {
-	EndOfWalRecoveryInfo *result = palloc(sizeof(EndOfWalRecoveryInfo));
+	EndOfWalRecoveryInfo *result = palloc_object(EndOfWalRecoveryInfo);
 	XLogRecPtr	lastRec;
 	TimeLineID	lastRecTLI;
 	XLogRecPtr	endOfLog;
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index ce2a3e42146..db55c0c5bd2 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -574,7 +574,7 @@ CreateFakeRelcacheEntry(RelFileLocator rlocator)
 	Relation	rel;
 
 	/* Allocate the Relation struct and all related space in one block. */
-	fakeentry = palloc0(sizeof(FakeRelCacheEntryData));
+	fakeentry = palloc0_object(FakeRelCacheEntryData);
 	rel = (Relation) fakeentry;
 
 	rel->rd_rel = &fakeentry->pgc;
diff --git a/src/backend/backup/basebackup.c b/src/backend/backup/basebackup.c
index 2be4e069816..1f7b42da009 100644
--- a/src/backend/backup/basebackup.c
+++ b/src/backend/backup/basebackup.c
@@ -262,7 +262,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink,
 	total_checksum_failures = 0;
 
 	/* Allocate backup related variables. */
-	backup_state = (BackupState *) palloc0(sizeof(BackupState));
+	backup_state = palloc0_object(BackupState);
 	initStringInfo(&tablespace_map);
 
 	basebackup_progress_wait_checkpoint();
@@ -289,7 +289,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink,
 			PrepareForIncrementalBackup(ib, backup_state);
 
 		/* Add a node for the base directory at the end */
-		newti = palloc0(sizeof(tablespaceinfo));
+		newti = palloc0_object(tablespaceinfo);
 		newti->size = -1;
 		state.tablespaces = lappend(state.tablespaces, newti);
 
@@ -1206,7 +1206,7 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
 	 * But we don't need it at all if this is not an incremental backup.
 	 */
 	if (ib != NULL)
-		relative_block_numbers = palloc(sizeof(BlockNumber) * RELSEG_SIZE);
+		relative_block_numbers = palloc_array(BlockNumber, RELSEG_SIZE);
 
 	/*
 	 * Determine if the current path is a database directory that can contain
diff --git a/src/backend/backup/basebackup_copy.c b/src/backend/backup/basebackup_copy.c
index eb45d3bcb66..8bb8d3939fe 100644
--- a/src/backend/backup/basebackup_copy.c
+++ b/src/backend/backup/basebackup_copy.c
@@ -107,7 +107,7 @@ static const bbsink_ops bbsink_copystream_ops = {
 bbsink *
 bbsink_copystream_new(bool send_to_client)
 {
-	bbsink_copystream *sink = palloc0(sizeof(bbsink_copystream));
+	bbsink_copystream *sink = palloc0_object(bbsink_copystream);
 
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_copystream_ops;
 	sink->send_to_client = send_to_client;
diff --git a/src/backend/backup/basebackup_gzip.c b/src/backend/backup/basebackup_gzip.c
index c4cbb5f5276..aaad834291a 100644
--- a/src/backend/backup/basebackup_gzip.c
+++ b/src/backend/backup/basebackup_gzip.c
@@ -76,7 +76,7 @@ bbsink_gzip_new(bbsink *next, pg_compress_specification *compress)
 	Assert((compresslevel >= 1 && compresslevel <= 9) ||
 		   compresslevel == Z_DEFAULT_COMPRESSION);
 
-	sink = palloc0(sizeof(bbsink_gzip));
+	sink = palloc0_object(bbsink_gzip);
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_gzip_ops;
 	sink->base.bbs_next = next;
 	sink->compresslevel = compresslevel;
diff --git a/src/backend/backup/basebackup_incremental.c b/src/backend/backup/basebackup_incremental.c
index 852ab577045..7678e4f6ec3 100644
--- a/src/backend/backup/basebackup_incremental.c
+++ b/src/backend/backup/basebackup_incremental.c
@@ -157,7 +157,7 @@ CreateIncrementalBackupInfo(MemoryContext mcxt)
 
 	oldcontext = MemoryContextSwitchTo(mcxt);
 
-	ib = palloc0(sizeof(IncrementalBackupInfo));
+	ib = palloc0_object(IncrementalBackupInfo);
 	ib->mcxt = mcxt;
 	initStringInfo(&ib->buf);
 
@@ -169,7 +169,7 @@ CreateIncrementalBackupInfo(MemoryContext mcxt)
 	 */
 	ib->manifest_files = backup_file_create(mcxt, 10000, NULL);
 
-	context = palloc0(sizeof(JsonManifestParseContext));
+	context = palloc0_object(JsonManifestParseContext);
 	/* Parse the manifest. */
 	context->private_data = ib;
 	context->version_cb = manifest_process_version;
@@ -993,7 +993,7 @@ manifest_process_wal_range(JsonManifestParseContext *context,
 						   XLogRecPtr end_lsn)
 {
 	IncrementalBackupInfo *ib = context->private_data;
-	backup_wal_range *range = palloc(sizeof(backup_wal_range));
+	backup_wal_range *range = palloc_object(backup_wal_range);
 
 	range->tli = tli;
 	range->start_lsn = start_lsn;
diff --git a/src/backend/backup/basebackup_lz4.c b/src/backend/backup/basebackup_lz4.c
index c5ceccb846f..bd5704520fb 100644
--- a/src/backend/backup/basebackup_lz4.c
+++ b/src/backend/backup/basebackup_lz4.c
@@ -75,7 +75,7 @@ bbsink_lz4_new(bbsink *next, pg_compress_specification *compress)
 	compresslevel = compress->level;
 	Assert(compresslevel >= 0 && compresslevel <= 12);
 
-	sink = palloc0(sizeof(bbsink_lz4));
+	sink = palloc0_object(bbsink_lz4);
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_lz4_ops;
 	sink->base.bbs_next = next;
 	sink->compresslevel = compresslevel;
diff --git a/src/backend/backup/basebackup_progress.c b/src/backend/backup/basebackup_progress.c
index dac20593622..d783c9f5738 100644
--- a/src/backend/backup/basebackup_progress.c
+++ b/src/backend/backup/basebackup_progress.c
@@ -62,7 +62,7 @@ bbsink_progress_new(bbsink *next, bool estimate_backup_size, bool incremental)
 
 	Assert(next != NULL);
 
-	sink = palloc0(sizeof(bbsink));
+	sink = palloc0_object(bbsink);
 	*((const bbsink_ops **) &sink->bbs_ops) = &bbsink_progress_ops;
 	sink->bbs_next = next;
 
diff --git a/src/backend/backup/basebackup_server.c b/src/backend/backup/basebackup_server.c
index f5c0c61640a..7510ec06f5e 100644
--- a/src/backend/backup/basebackup_server.c
+++ b/src/backend/backup/basebackup_server.c
@@ -59,7 +59,7 @@ static const bbsink_ops bbsink_server_ops = {
 bbsink *
 bbsink_server_new(bbsink *next, char *pathname)
 {
-	bbsink_server *sink = palloc0(sizeof(bbsink_server));
+	bbsink_server *sink = palloc0_object(bbsink_server);
 
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_server_ops;
 	sink->pathname = pathname;
diff --git a/src/backend/backup/basebackup_target.c b/src/backend/backup/basebackup_target.c
index 84b1309d3bd..8b74828aed6 100644
--- a/src/backend/backup/basebackup_target.c
+++ b/src/backend/backup/basebackup_target.c
@@ -96,7 +96,7 @@ BaseBackupAddTarget(char *name,
 	 * name into a newly-allocated chunk of memory.
 	 */
 	oldcontext = MemoryContextSwitchTo(TopMemoryContext);
-	newtype = palloc(sizeof(BaseBackupTargetType));
+	newtype = palloc_object(BaseBackupTargetType);
 	newtype->name = pstrdup(name);
 	newtype->check_detail = check_detail;
 	newtype->get_sink = get_sink;
@@ -132,7 +132,7 @@ BaseBackupGetTargetHandle(char *target, char *target_detail)
 			BaseBackupTargetHandle *handle;
 
 			/* Found the target. */
-			handle = palloc(sizeof(BaseBackupTargetHandle));
+			handle = palloc_object(BaseBackupTargetHandle);
 			handle->type = ttype;
 			handle->detail_arg = ttype->check_detail(target, target_detail);
 
diff --git a/src/backend/backup/basebackup_throttle.c b/src/backend/backup/basebackup_throttle.c
index b2b743238f9..95746c3ea40 100644
--- a/src/backend/backup/basebackup_throttle.c
+++ b/src/backend/backup/basebackup_throttle.c
@@ -72,7 +72,7 @@ bbsink_throttle_new(bbsink *next, uint32 maxrate)
 	Assert(next != NULL);
 	Assert(maxrate > 0);
 
-	sink = palloc0(sizeof(bbsink_throttle));
+	sink = palloc0_object(bbsink_throttle);
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_throttle_ops;
 	sink->base.bbs_next = next;
 
diff --git a/src/backend/backup/basebackup_zstd.c b/src/backend/backup/basebackup_zstd.c
index 18b2e8fb0b3..647ee0eb978 100644
--- a/src/backend/backup/basebackup_zstd.c
+++ b/src/backend/backup/basebackup_zstd.c
@@ -70,7 +70,7 @@ bbsink_zstd_new(bbsink *next, pg_compress_specification *compress)
 
 	Assert(next != NULL);
 
-	sink = palloc0(sizeof(bbsink_zstd));
+	sink = palloc0_object(bbsink_zstd);
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_zstd_ops;
 	sink->base.bbs_next = next;
 	sink->compress = compress;
diff --git a/src/backend/backup/walsummary.c b/src/backend/backup/walsummary.c
index 2689eae3328..a843876337b 100644
--- a/src/backend/backup/walsummary.c
+++ b/src/backend/backup/walsummary.c
@@ -73,7 +73,7 @@ GetWalSummaries(TimeLineID tli, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
 			continue;
 
 		/* Add it to the list. */
-		ws = palloc(sizeof(WalSummaryFile));
+		ws = palloc_object(WalSummaryFile);
 		ws->tli = file_tli;
 		ws->start_lsn = file_start_lsn;
 		ws->end_lsn = file_end_lsn;
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index fc8638c1b61..4986b1ea7ed 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -742,7 +742,7 @@ populate_typ_list(void)
 		Form_pg_type typForm = (Form_pg_type) GETSTRUCT(tup);
 		struct typmap *newtyp;
 
-		newtyp = (struct typmap *) palloc(sizeof(struct typmap));
+		newtyp = palloc_object(struct typmap);
 		Typ = lappend(Typ, newtyp);
 
 		newtyp->am_oid = typForm->oid;
@@ -951,10 +951,10 @@ index_register(Oid heap,
 
 	oldcxt = MemoryContextSwitchTo(nogc);
 
-	newind = (IndexList *) palloc(sizeof(IndexList));
+	newind = palloc_object(IndexList);
 	newind->il_heap = heap;
 	newind->il_ind = ind;
-	newind->il_info = (IndexInfo *) palloc(sizeof(IndexInfo));
+	newind->il_info = palloc_object(IndexInfo);
 
 	memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
 	/* expressions will likely be null, but may as well copy it */
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 8e70a85a3f7..838ed26d6b9 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -801,8 +801,7 @@ findDependentObjects(const ObjectAddress *object,
 	 * regression testing.)
 	 */
 	maxDependentObjects = 128;	/* arbitrary initial allocation */
-	dependentObjects = (ObjectAddressAndFlags *)
-		palloc(maxDependentObjects * sizeof(ObjectAddressAndFlags));
+	dependentObjects = palloc_array(ObjectAddressAndFlags, maxDependentObjects);
 	numDependentObjects = 0;
 
 	ScanKeyInit(&key[0],
@@ -2616,12 +2615,11 @@ new_object_addresses(void)
 {
 	ObjectAddresses *addrs;
 
-	addrs = palloc(sizeof(ObjectAddresses));
+	addrs = palloc_object(ObjectAddresses);
 
 	addrs->numrefs = 0;
 	addrs->maxrefs = 32;
-	addrs->refs = (ObjectAddress *)
-		palloc(addrs->maxrefs * sizeof(ObjectAddress));
+	addrs->refs = palloc_array(ObjectAddress, addrs->maxrefs);
 	addrs->extras = NULL;		/* until/unless needed */
 
 	return addrs;
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index fd6537567ea..265cc3e5fbf 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -732,7 +732,7 @@ InsertPgAttributeTuples(Relation pg_attribute_rel,
 	/* Initialize the number of slots to use */
 	nslots = Min(tupdesc->natts,
 				 (MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_attribute)));
-	slot = palloc(sizeof(TupleTableSlot *) * nslots);
+	slot = palloc_array(TupleTableSlot *, nslots);
 	for (int i = 0; i < nslots; i++)
 		slot[i] = MakeSingleTupleTableSlot(td, &TTSOpsHeapTuple);
 
@@ -2459,7 +2459,7 @@ AddRelationNewConstraints(Relation rel,
 
 		defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
 
-		cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+		cooked = palloc_object(CookedConstraint);
 		cooked->contype = CONSTR_DEFAULT;
 		cooked->conoid = defOid;
 		cooked->name = NULL;
@@ -2593,7 +2593,7 @@ AddRelationNewConstraints(Relation rel,
 
 			numchecks++;
 
-			cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+			cooked = palloc_object(CookedConstraint);
 			cooked->contype = CONSTR_CHECK;
 			cooked->conoid = constrOid;
 			cooked->name = ccname;
@@ -2669,7 +2669,7 @@ AddRelationNewConstraints(Relation rel,
 								inhcount,
 								cdef->is_no_inherit);
 
-			nncooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+			nncooked = palloc_object(CookedConstraint);
 			nncooked->contype = CONSTR_NOTNULL;
 			nncooked->conoid = constrOid;
 			nncooked->name = nnname;
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 5d9db167e59..d94ca7ea53a 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1414,7 +1414,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
 	}
 
 	/* Extract opclass options for each attribute */
-	opclassOptions = palloc0(sizeof(Datum) * newInfo->ii_NumIndexAttrs);
+	opclassOptions = palloc0_array(Datum, newInfo->ii_NumIndexAttrs);
 	for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
 		opclassOptions[i] = get_attoptions(oldIndexId, i + 1);
 
@@ -2678,9 +2678,9 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
 	 */
 	Assert(ii->ii_Unique);
 
-	ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
+	ii->ii_UniqueOps = (Oid *) palloc_array(Oid, indnkeyatts);
+	ii->ii_UniqueProcs = (Oid *) palloc_array(Oid, indnkeyatts);
+	ii->ii_UniqueStrats = (uint16 *) palloc_array(uint16, indnkeyatts);
 
 	/*
 	 * We have to look up the operator's strategy number.  This provides a
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index d23474da4fb..c94089caa58 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -3929,7 +3929,7 @@ GetSearchPathMatcher(MemoryContext context)
 
 	oldcxt = MemoryContextSwitchTo(context);
 
-	result = (SearchPathMatcher *) palloc0(sizeof(SearchPathMatcher));
+	result = palloc0_object(SearchPathMatcher);
 	schemas = list_copy(activeSearchPath);
 	while (schemas && linitial_oid(schemas) != activeCreationNamespace)
 	{
@@ -3960,7 +3960,7 @@ CopySearchPathMatcher(SearchPathMatcher *path)
 {
 	SearchPathMatcher *result;
 
-	result = (SearchPathMatcher *) palloc(sizeof(SearchPathMatcher));
+	result = palloc_object(SearchPathMatcher);
 	result->schemas = list_copy(path->schemas);
 	result->addCatalog = path->addCatalog;
 	result->addTemp = path->addTemp;
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index c75b7131ed7..fa6c6df598a 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -6144,8 +6144,8 @@ strlist_to_textarray(List *list)
 								   ALLOCSET_DEFAULT_SIZES);
 	oldcxt = MemoryContextSwitchTo(memcxt);
 
-	datums = (Datum *) palloc(sizeof(Datum) * list_length(list));
-	nulls = palloc(sizeof(bool) * list_length(list));
+	datums = palloc_array(Datum, list_length(list));
+	nulls = palloc_array(bool, list_length(list));
 
 	foreach(cell, list)
 	{
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 9944e4bd2d1..fa73ca178c5 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -846,7 +846,7 @@ RelationGetNotNullConstraints(Oid relid, bool cooked, bool include_noinh)
 		{
 			CookedConstraint *cooked;
 
-			cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+			cooked = palloc_object(CookedConstraint);
 
 			cooked->contype = CONSTR_NOTNULL;
 			cooked->conoid = conForm->oid;
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index c8b11f887e2..a6f63e107bb 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -88,7 +88,7 @@ recordMultipleDependencies(const ObjectAddress *depender,
 	 */
 	max_slots = Min(nreferenced,
 					MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_depend));
-	slot = palloc(sizeof(TupleTableSlot *) * max_slots);
+	slot = palloc_array(TupleTableSlot *, max_slots);
 
 	/* Don't open indexes unless we need to make an update */
 	indstate = NULL;
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index da9c2a46cfa..07998839aff 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -120,7 +120,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 	 * allocating the next), trouble could only occur if the OID counter wraps
 	 * all the way around before we finish. Which seems unlikely.
 	 */
-	oids = (Oid *) palloc(num_elems * sizeof(Oid));
+	oids = palloc_array(Oid, num_elems);
 
 	for (elemno = 0; elemno < num_elems; elemno++)
 	{
@@ -148,7 +148,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 	/* allocate the slots to use and initialize them */
 	nslots = Min(num_elems,
 				 MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_enum));
-	slot = palloc(sizeof(TupleTableSlot *) * nslots);
+	slot = palloc_array(TupleTableSlot *, nslots);
 	for (int i = 0; i < nslots; i++)
 		slot[i] = MakeSingleTupleTableSlot(RelationGetDescr(pg_enum),
 										   &TTSOpsHeapTuple);
@@ -375,7 +375,7 @@ restart:
 	nelems = list->n_members;
 
 	/* Sort the existing members by enumsortorder */
-	existing = (HeapTuple *) palloc(nelems * sizeof(HeapTuple));
+	existing = palloc_array(HeapTuple, nelems);
 	for (i = 0; i < nelems; i++)
 		existing[i] = &(list->members[i]->tuple);
 
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index 0994220c53d..be5ef5e4c0e 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -1086,7 +1086,7 @@ GetPublication(Oid pubid)
 
 	pubform = (Form_pg_publication) GETSTRUCT(tup);
 
-	pub = (Publication *) palloc(sizeof(Publication));
+	pub = palloc_object(Publication);
 	pub->oid = pubid;
 	pub->name = pstrdup(NameStr(pubform->pubname));
 	pub->alltables = pubform->puballtables;
@@ -1196,7 +1196,7 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
 			 */
 			foreach(lc, pub_elem_tables)
 			{
-				published_rel *table_info = (published_rel *) palloc(sizeof(published_rel));
+				published_rel *table_info = palloc_object(published_rel);
 
 				table_info->relid = lfirst_oid(lc);
 				table_info->pubid = pub_elem->oid;
@@ -1299,7 +1299,7 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
 			TupleDesc	desc = RelationGetDescr(rel);
 			int			i;
 
-			attnums = (int16 *) palloc(desc->natts * sizeof(int16));
+			attnums = palloc_array(int16, desc->natts);
 
 			for (i = 0; i < desc->natts; i++)
 			{
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index 16e3e5c7457..fe4e4536676 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -791,7 +791,7 @@ checkSharedDependencies(Oid classId, Oid objectId,
 			}
 			if (!stored)
 			{
-				dep = (remoteDep *) palloc(sizeof(remoteDep));
+				dep = palloc_object(remoteDep);
 				dep->dbOid = sdepForm->dbid;
 				dep->count = 1;
 				remDeps = lappend(remDeps, dep);
@@ -913,7 +913,7 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId)
 	 * know that they will be used.
 	 */
 	max_slots = MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_shdepend);
-	slot = palloc(sizeof(TupleTableSlot *) * max_slots);
+	slot = palloc_array(TupleTableSlot *, max_slots);
 
 	indstate = CatalogOpenIndexes(sdepRel);
 
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index 180e77e9484..ad6fbd77ffd 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -89,7 +89,7 @@ GetSubscription(Oid subid, bool missing_ok)
 
 	subform = (Form_pg_subscription) GETSTRUCT(tup);
 
-	sub = (Subscription *) palloc(sizeof(Subscription));
+	sub = palloc_object(Subscription);
 	sub->oid = subid;
 	sub->dbid = subform->subdbid;
 	sub->skiplsn = subform->subskiplsn;
@@ -618,7 +618,7 @@ GetSubscriptionRelations(Oid subid, bool tables, bool sequences,
 			 relkind == RELKIND_PARTITIONED_TABLE) && !tables)
 			continue;
 
-		relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState));
+		relstate = palloc_object(SubscriptionRelState);
 		relstate->relid = subrel->srrelid;
 		relstate->state = subrel->srsubstate;
 		d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup,
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index c58e9418ac3..d06c1c68174 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -707,12 +707,12 @@ smgrDoPendingDeletes(bool isCommit)
 				if (maxrels == 0)
 				{
 					maxrels = 8;
-					srels = palloc(sizeof(SMgrRelation) * maxrels);
+					srels = palloc_array(SMgrRelation, maxrels);
 				}
 				else if (maxrels <= nrels)
 				{
 					maxrels *= 2;
-					srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
+					srels = repalloc_array(srels, SMgrRelation, maxrels);
 				}
 
 				srels[nrels++] = srel;
@@ -829,12 +829,12 @@ smgrDoPendingSyncs(bool isCommit, bool isParallelWorker)
 			if (maxrels == 0)
 			{
 				maxrels = 8;
-				srels = palloc(sizeof(SMgrRelation) * maxrels);
+				srels = palloc_array(SMgrRelation, maxrels);
 			}
 			else if (maxrels <= nrels)
 			{
 				maxrels *= 2;
-				srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
+				srels = repalloc_array(srels, SMgrRelation, maxrels);
 			}
 
 			srels[nrels++] = srel;
@@ -909,7 +909,7 @@ smgrGetPendingDeletes(bool forCommit, RelFileLocator **ptr)
 		*ptr = NULL;
 		return 0;
 	}
-	rptr = (RelFileLocator *) palloc(nrels * sizeof(RelFileLocator));
+	rptr = palloc_array(RelFileLocator, nrels);
 	*ptr = rptr;
 	for (pending = pendingDeletes; pending != NULL; pending = pending->next)
 	{
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 25089fae3e0..282c53683ad 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -1073,7 +1073,7 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr)
 	/*
 	 * Create the VacAttrStats struct.
 	 */
-	stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
+	stats = palloc0_object(VacAttrStats);
 	stats->attstattarget = attstattarget;
 
 	/*
@@ -1904,7 +1904,7 @@ std_typanalyze(VacAttrStats *stats)
 							 NULL);
 
 	/* Save the operator info for compute_stats routines */
-	mystats = (StdAnalyzeData *) palloc(sizeof(StdAnalyzeData));
+	mystats = palloc_object(StdAnalyzeData);
 	mystats->eqopr = eqopr;
 	mystats->eqfunc = OidIsValid(eqopr) ? get_opcode(eqopr) : InvalidOid;
 	mystats->ltopr = ltopr;
@@ -2859,7 +2859,7 @@ compute_scalar_stats(VacAttrStatsP stats,
 
 			/* Must copy the target values into anl_context */
 			old_context = MemoryContextSwitchTo(stats->anl_context);
-			corrs = (float4 *) palloc(sizeof(float4));
+			corrs = palloc_object(float4);
 			MemoryContextSwitchTo(old_context);
 
 			/*----------
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index b55221d44cd..a838a734321 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -1672,7 +1672,7 @@ get_tables_to_cluster(MemoryContext cluster_context)
 		/* Use a permanent memory context for the result list */
 		old_context = MemoryContextSwitchTo(cluster_context);
 
-		rtc = (RelToCluster *) palloc(sizeof(RelToCluster));
+		rtc = palloc_object(RelToCluster);
 		rtc->tableOid = index->indrelid;
 		rtc->indexOid = index->indexrelid;
 		rtcs = lappend(rtcs, rtc);
@@ -1726,7 +1726,7 @@ get_tables_to_cluster_partitioned(MemoryContext cluster_context, Oid indexOid)
 		/* Use a permanent memory context for the result list */
 		old_context = MemoryContextSwitchTo(cluster_context);
 
-		rtc = (RelToCluster *) palloc(sizeof(RelToCluster));
+		rtc = palloc_object(RelToCluster);
 		rtc->tableOid = relid;
 		rtc->indexOid = indexrelid;
 		rtcs = lappend(rtcs, rtc);
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 28e878c3688..6454a39a01f 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -561,7 +561,7 @@ ProcessCopyOptions(ParseState *pstate,
 
 	/* Support external use for option sanity checking */
 	if (opts_out == NULL)
-		opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
+		opts_out = palloc0_object(CopyFormatOptions);
 
 	opts_out->file_encoding = -1;
 
diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c
index 12781963b4f..2ae3d2ba86e 100644
--- a/src/backend/commands/copyfrom.c
+++ b/src/backend/commands/copyfrom.c
@@ -364,7 +364,7 @@ CopyMultiInsertBufferInit(ResultRelInfo *rri)
 {
 	CopyMultiInsertBuffer *buffer;
 
-	buffer = (CopyMultiInsertBuffer *) palloc(sizeof(CopyMultiInsertBuffer));
+	buffer = palloc_object(CopyMultiInsertBuffer);
 	memset(buffer->slots, 0, sizeof(TupleTableSlot *) * MAX_BUFFERED_TUPLES);
 	buffer->resultRelInfo = rri;
 	buffer->bistate = (rri->ri_FdwRoutine == NULL) ? GetBulkInsertState() : NULL;
@@ -1558,7 +1558,7 @@ BeginCopyFrom(ParseState *pstate,
 	};
 
 	/* Allocate workspace and zero all fields */
-	cstate = (CopyFromStateData *) palloc0(sizeof(CopyFromStateData));
+	cstate = palloc0_object(CopyFromStateData);
 
 	/*
 	 * We allocate everything used by a cstate in a new memory context. This
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index cef452584e5..dae91630ac3 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -720,7 +720,7 @@ BeginCopyTo(ParseState *pstate,
 
 
 	/* Allocate workspace and zero all fields */
-	cstate = (CopyToStateData *) palloc0(sizeof(CopyToStateData));
+	cstate = palloc0_object(CopyToStateData);
 
 	/*
 	 * We allocate everything used by a cstate in a new memory context. This
@@ -1527,7 +1527,7 @@ copy_dest_destroy(DestReceiver *self)
 DestReceiver *
 CreateCopyDestReceiver(void)
 {
-	DR_copy    *self = (DR_copy *) palloc(sizeof(DR_copy));
+	DR_copy    *self = palloc_object(DR_copy);
 
 	self->pub.receiveSlot = copy_dest_receive;
 	self->pub.rStartup = copy_dest_startup;
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 1ccc2e55c64..ddc45e3aa0d 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -439,7 +439,7 @@ CreateTableAsRelExists(CreateTableAsStmt *ctas)
 DestReceiver *
 CreateIntoRelDestReceiver(IntoClause *intoClause)
 {
-	DR_intorel *self = (DR_intorel *) palloc0(sizeof(DR_intorel));
+	DR_intorel *self = palloc0_object(DR_intorel);
 
 	self->pub.receiveSlot = intorel_receive;
 	self->pub.rStartup = intorel_startup;
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 4d65e8c46c2..c12777f4464 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -431,7 +431,7 @@ ScanSourceDatabasePgClassTuple(HeapTupleData *tuple, Oid tbid, Oid dbid,
 			 classForm->oid);
 
 	/* Prepare a rel info element and add it to the list. */
-	relinfo = (CreateDBRelInfo *) palloc(sizeof(CreateDBRelInfo));
+	relinfo = palloc_object(CreateDBRelInfo);
 	if (OidIsValid(classForm->reltablespace))
 		relinfo->rlocator.spcOid = classForm->reltablespace;
 	else
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index f34868da5ab..e7182308130 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -364,7 +364,7 @@ filter_list_to_array(List *filterlist)
 	int			i = 0,
 				l = list_length(filterlist);
 
-	data = (Datum *) palloc(l * sizeof(Datum));
+	data = palloc_array(Datum, l);
 
 	foreach(lc, filterlist)
 	{
@@ -1286,7 +1286,7 @@ EventTriggerSQLDropAddObject(const ObjectAddress *object, bool original, bool no
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	obj = palloc0(sizeof(SQLDropObject));
+	obj = palloc0_object(SQLDropObject);
 	obj->address = *object;
 	obj->original = original;
 	obj->normal = normal;
@@ -1726,7 +1726,7 @@ EventTriggerCollectSimpleCommand(ObjectAddress address,
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc(sizeof(CollectedCommand));
+	command = palloc_object(CollectedCommand);
 
 	command->type = SCT_Simple;
 	command->in_extension = creating_extension;
@@ -1762,7 +1762,7 @@ EventTriggerAlterTableStart(Node *parsetree)
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc(sizeof(CollectedCommand));
+	command = palloc_object(CollectedCommand);
 
 	command->type = SCT_AlterTable;
 	command->in_extension = creating_extension;
@@ -1818,7 +1818,7 @@ EventTriggerCollectAlterTableSubcmd(Node *subcmd, ObjectAddress address)
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	newsub = palloc(sizeof(CollectedATSubcmd));
+	newsub = palloc_object(CollectedATSubcmd);
 	newsub->address = address;
 	newsub->parsetree = copyObject(subcmd);
 
@@ -1892,7 +1892,7 @@ EventTriggerCollectGrant(InternalGrant *istmt)
 	/*
 	 * This is tedious, but necessary.
 	 */
-	icopy = palloc(sizeof(InternalGrant));
+	icopy = palloc_object(InternalGrant);
 	memcpy(icopy, istmt, sizeof(InternalGrant));
 	icopy->objects = list_copy(istmt->objects);
 	icopy->grantees = list_copy(istmt->grantees);
@@ -1901,7 +1901,7 @@ EventTriggerCollectGrant(InternalGrant *istmt)
 		icopy->col_privs = lappend(icopy->col_privs, copyObject(lfirst(cell)));
 
 	/* Now collect it, using the copied InternalGrant */
-	command = palloc(sizeof(CollectedCommand));
+	command = palloc_object(CollectedCommand);
 	command->type = SCT_Grant;
 	command->in_extension = creating_extension;
 	command->d.grant.istmt = icopy;
@@ -1932,7 +1932,7 @@ EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc(sizeof(CollectedCommand));
+	command = palloc_object(CollectedCommand);
 	command->type = SCT_AlterOpFamily;
 	command->in_extension = creating_extension;
 	ObjectAddressSet(command->d.opfam.address,
@@ -1965,7 +1965,7 @@ EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt, Oid opcoid,
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc0(sizeof(CollectedCommand));
+	command = palloc0_object(CollectedCommand);
 	command->type = SCT_CreateOpClass;
 	command->in_extension = creating_extension;
 	ObjectAddressSet(command->d.createopc.address,
@@ -1999,12 +1999,12 @@ EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId,
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc0(sizeof(CollectedCommand));
+	command = palloc0_object(CollectedCommand);
 	command->type = SCT_AlterTSConfig;
 	command->in_extension = creating_extension;
 	ObjectAddressSet(command->d.atscfg.address,
 					 TSConfigRelationId, cfgId);
-	command->d.atscfg.dictIds = palloc(sizeof(Oid) * ndicts);
+	command->d.atscfg.dictIds = palloc_array(Oid, ndicts);
 	memcpy(command->d.atscfg.dictIds, dictIds, sizeof(Oid) * ndicts);
 	command->d.atscfg.ndicts = ndicts;
 	command->parsetree = (Node *) copyObject(stmt);
@@ -2033,7 +2033,7 @@ EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt)
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc0(sizeof(CollectedCommand));
+	command = palloc0_object(CollectedCommand);
 	command->type = SCT_AlterDefaultPrivileges;
 	command->d.defprivs.objtype = stmt->action->objtype;
 	command->in_extension = creating_extension;
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 7e699f8595e..5a6390631eb 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4980,7 +4980,7 @@ ExplainCreateWorkersState(int num_workers)
 {
 	ExplainWorkersState *wstate;
 
-	wstate = (ExplainWorkersState *) palloc(sizeof(ExplainWorkersState));
+	wstate = palloc_object(ExplainWorkersState);
 	wstate->num_workers = num_workers;
 	wstate->worker_inited = (bool *) palloc0(num_workers * sizeof(bool));
 	wstate->worker_str = (StringInfoData *)
diff --git a/src/backend/commands/explain_dr.c b/src/backend/commands/explain_dr.c
index 95685d7e88d..5833aa80fb5 100644
--- a/src/backend/commands/explain_dr.c
+++ b/src/backend/commands/explain_dr.c
@@ -276,7 +276,7 @@ CreateExplainSerializeDestReceiver(ExplainState *es)
 {
 	SerializeDestReceiver *self;
 
-	self = (SerializeDestReceiver *) palloc0(sizeof(SerializeDestReceiver));
+	self = palloc0_object(SerializeDestReceiver);
 
 	self->pub.receiveSlot = serializeAnalyzeReceive;
 	self->pub.rStartup = serializeAnalyzeStartup;
diff --git a/src/backend/commands/explain_state.c b/src/backend/commands/explain_state.c
index 9fdeeab6436..6e26ec9b31e 100644
--- a/src/backend/commands/explain_state.c
+++ b/src/backend/commands/explain_state.c
@@ -60,7 +60,7 @@ static int	ExplainExtensionOptionsAllocated = 0;
 ExplainState *
 NewExplainState(void)
 {
-	ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
+	ExplainState *es = palloc0_object(ExplainState);
 
 	/* Set default options (most fields can be left as zeroes). */
 	es->costs = true;
@@ -293,10 +293,7 @@ SetExplainExtensionState(ExplainState *es, int extension_id, void *opaque)
 		int			i;
 
 		i = pg_nextpower2_32(extension_id + 1);
-		es->extension_state = (void **)
-			repalloc0(es->extension_state,
-					  es->extension_state_allocated * sizeof(void *),
-					  i * sizeof(void *));
+		es->extension_state = repalloc0_array(es->extension_state, void *, es->extension_state_allocated, i);
 		es->extension_state_allocated = i;
 	}
 
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index ebc204c4462..c43b74e319e 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -724,7 +724,7 @@ read_extension_aux_control_file(const ExtensionControlFile *pcontrol,
 	/*
 	 * Flat-copy the struct.  Pointer fields share values with original.
 	 */
-	acontrol = (ExtensionControlFile *) palloc(sizeof(ExtensionControlFile));
+	acontrol = palloc_object(ExtensionControlFile);
 	memcpy(acontrol, pcontrol, sizeof(ExtensionControlFile));
 
 	/*
@@ -1349,7 +1349,7 @@ get_ext_ver_info(const char *versionname, List **evi_list)
 			return evi;
 	}
 
-	evi = (ExtensionVersionInfo *) palloc(sizeof(ExtensionVersionInfo));
+	evi = palloc_object(ExtensionVersionInfo);
 	evi->name = pstrdup(versionname);
 	evi->reachable = NIL;
 	evi->installable = false;
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 59d00638ee6..8a435cd93db 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -913,7 +913,7 @@ interpret_AS_clause(Oid languageOid, const char *languageName,
 	{
 		SQLFunctionParseInfoPtr pinfo;
 
-		pinfo = (SQLFunctionParseInfoPtr) palloc0(sizeof(SQLFunctionParseInfo));
+		pinfo = palloc0_object(SQLFunctionParseInfo);
 
 		pinfo->fname = funcname;
 		pinfo->nargs = list_length(parameterTypes);
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index ef7c0d624f1..f63f8753b05 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -463,7 +463,7 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
 DestReceiver *
 CreateTransientRelDestReceiver(Oid transientoid)
 {
-	DR_transientrel *self = (DR_transientrel *) palloc0(sizeof(DR_transientrel));
+	DR_transientrel *self = palloc0_object(DR_transientrel);
 
 	self->pub.receiveSlot = transientrel_receive;
 	self->pub.rStartup = transientrel_startup;
@@ -713,7 +713,7 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 	 * include all rows.
 	 */
 	tupdesc = matviewRel->rd_att;
-	opUsedForQual = (Oid *) palloc0(sizeof(Oid) * relnatts);
+	opUsedForQual = palloc0_array(Oid, relnatts);
 	foundUniqueIndex = false;
 
 	indexoidlist = RelationGetIndexList(matviewRel);
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index a6dd8eab518..992ae789b00 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -523,7 +523,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 #endif
 
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = false;
 				member->object = operOid;
 				member->number = item->number;
@@ -547,7 +547,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 								   get_func_name(funcOid));
 #endif
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = true;
 				member->object = funcOid;
 				member->number = item->number;
@@ -940,7 +940,7 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 #endif
 
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = false;
 				member->object = operOid;
 				member->number = item->number;
@@ -970,7 +970,7 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 #endif
 
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = true;
 				member->object = funcOid;
 				member->number = item->number;
@@ -1058,7 +1058,7 @@ AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 									item->number, maxOpNumber)));
 				processTypesSpec(item->class_args, &lefttype, &righttype);
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = false;
 				member->number = item->number;
 				member->lefttype = lefttype;
@@ -1074,7 +1074,7 @@ AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 									item->number, maxProcNumber)));
 				processTypesSpec(item->class_args, &lefttype, &righttype);
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = true;
 				member->number = item->number;
 				member->lefttype = lefttype;
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index 83056960fe4..5bd5f8c9968 100644
--- a/src/backend/commands/policy.c
+++ b/src/backend/commands/policy.c
@@ -144,7 +144,7 @@ policy_role_list_to_array(List *roles, int *num_roles)
 	if (roles == NIL)
 	{
 		*num_roles = 1;
-		role_oids = (Datum *) palloc(*num_roles * sizeof(Datum));
+		role_oids = palloc_array(Datum, *num_roles);
 		role_oids[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
 
 		return role_oids;
@@ -471,7 +471,7 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
 	 * Ordinarily there'd be exactly one, but we must cope with duplicate
 	 * mentions, since CREATE/ALTER POLICY historically have allowed that.
 	 */
-	role_oids = (Datum *) palloc(num_roles * sizeof(Datum));
+	role_oids = palloc_array(Datum, num_roles);
 	for (i = 0, j = 0; i < num_roles; i++)
 	{
 		if (roles[i] != roleid)
@@ -945,7 +945,7 @@ AlterPolicy(AlterPolicyStmt *stmt)
 
 		nitems = ARR_DIMS(policy_roles)[0];
 
-		role_oids = (Datum *) palloc(nitems * sizeof(Datum));
+		role_oids = palloc_array(Datum, nitems);
 
 		for (i = 0; i < nitems; i++)
 			role_oids[i] = ObjectIdGetDatum(roles[i]);
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 1faf3a8c372..a1983508950 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -1345,7 +1345,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
 			 */
 			if (!found)
 			{
-				oldrel = palloc(sizeof(PublicationRelInfo));
+				oldrel = palloc_object(PublicationRelInfo);
 				oldrel->whereClause = NULL;
 				oldrel->columns = NIL;
 				oldrel->relation = table_open(oldrelid,
@@ -1757,7 +1757,7 @@ OpenTableList(List *tables)
 			continue;
 		}
 
-		pub_rel = palloc(sizeof(PublicationRelInfo));
+		pub_rel = palloc_object(PublicationRelInfo);
 		pub_rel->relation = rel;
 		pub_rel->whereClause = t->whereClause;
 		pub_rel->columns = t->columns;
@@ -1826,7 +1826,7 @@ OpenTableList(List *tables)
 
 				/* find_all_inheritors already got lock */
 				rel = table_open(childrelid, NoLock);
-				pub_rel = palloc(sizeof(PublicationRelInfo));
+				pub_rel = palloc_object(PublicationRelInfo);
 				pub_rel->relation = rel;
 				/* child inherits WHERE clause from parent */
 				pub_rel->whereClause = t->whereClause;
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index cee5d7bbb9c..07bed6e1487 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -573,7 +573,7 @@ register_label_provider(const char *provider_name, check_object_relabel_type hoo
 	MemoryContext oldcxt;
 
 	oldcxt = MemoryContextSwitchTo(TopMemoryContext);
-	provider = palloc(sizeof(LabelProvider));
+	provider = palloc_object(LabelProvider);
 	provider->provider_name = pstrdup(provider_name);
 	provider->hook = hook;
 	label_provider_list = lappend(label_provider_list, provider);
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 24b70234b35..68599a6fde5 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -566,7 +566,7 @@ publicationListToArray(List *publist)
 								   ALLOCSET_DEFAULT_SIZES);
 	oldcxt = MemoryContextSwitchTo(memcxt);
 
-	datums = (Datum *) palloc(sizeof(Datum) * list_length(publist));
+	datums = palloc_array(Datum, list_length(publist));
 
 	check_duplicates_in_publist(publist, datums);
 
@@ -1055,7 +1055,7 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data,
 			{
 				char		state;
 				XLogRecPtr	statelsn;
-				SubRemoveRels *remove_rel = palloc(sizeof(SubRemoveRels));
+				SubRemoveRels *remove_rel = palloc_object(SubRemoveRels);
 
 				/*
 				 * Lock pg_subscription_rel with AccessExclusiveLock to
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 23ebaa3f230..804fcdd5537 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -999,7 +999,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 
 			Assert(colDef->cooked_default == NULL);
 
-			rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+			rawEnt = palloc_object(RawColumnDefault);
 			rawEnt->attnum = attnum;
 			rawEnt->raw_default = colDef->raw_default;
 			rawEnt->generated = colDef->generated;
@@ -1009,7 +1009,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 		{
 			CookedConstraint *cooked;
 
-			cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+			cooked = palloc_object(CookedConstraint);
 			cooked->contype = CONSTR_DEFAULT;
 			cooked->conoid = InvalidOid;	/* until created */
 			cooked->name = NULL;
@@ -6568,7 +6568,7 @@ ATGetQueueEntry(List **wqueue, Relation rel)
 	 * Not there, so add it.  Note that we make a copy of the relation's
 	 * existing descriptor before anything interesting can happen to it.
 	 */
-	tab = (AlteredTableInfo *) palloc0(sizeof(AlteredTableInfo));
+	tab = palloc0_object(AlteredTableInfo);
 	tab->relid = relid;
 	tab->rel = NULL;			/* set later */
 	tab->relkind = rel->rd_rel->relkind;
@@ -7406,7 +7406,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	{
 		RawColumnDefault *rawEnt;
 
-		rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+		rawEnt = palloc_object(RawColumnDefault);
 		rawEnt->attnum = attribute->attnum;
 		rawEnt->raw_default = copyObject(colDef->raw_default);
 		rawEnt->generated = colDef->generated;
@@ -7507,7 +7507,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 			defval = expression_planner(defval);
 
 			/* Add the new default to the newvals list */
-			newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
+			newval = palloc0_object(NewColumnValue);
 			newval->attnum = attribute->attnum;
 			newval->expr = defval;
 			newval->is_generated = (colDef->generated != '\0');
@@ -8176,7 +8176,7 @@ ATExecColumnDefault(Relation rel, const char *colName,
 		/* SET DEFAULT */
 		RawColumnDefault *rawEnt;
 
-		rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+		rawEnt = palloc_object(RawColumnDefault);
 		rawEnt->attnum = attnum;
 		rawEnt->raw_default = newDefault;
 		rawEnt->generated = '\0';
@@ -8704,7 +8704,7 @@ ATExecSetExpression(AlteredTableInfo *tab, Relation rel, const char *colName,
 					  false, false);
 
 	/* Prepare to store the new expression, in the catalogs */
-	rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+	rawEnt = palloc_object(RawColumnDefault);
 	rawEnt->attnum = attnum;
 	rawEnt->raw_default = newExpr;
 	rawEnt->generated = attgenerated;
@@ -8721,7 +8721,7 @@ ATExecSetExpression(AlteredTableInfo *tab, Relation rel, const char *colName,
 		/* Prepare for table rewrite */
 		defval = (Expr *) build_column_default(rel, attnum);
 
-		newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
+		newval = palloc0_object(NewColumnValue);
 		newval->attnum = attnum;
 		newval->expr = expression_planner(defval);
 		newval->is_generated = true;
@@ -9949,7 +9949,7 @@ ATAddCheckNNConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		{
 			NewConstraint *newcon;
 
-			newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+			newcon = palloc0_object(NewConstraint);
 			newcon->name = ccon->name;
 			newcon->contype = ccon->contype;
 			newcon->qual = ccon->expr;
@@ -10946,7 +10946,7 @@ addFkRecurseReferenced(Constraint *fkconstraint, Relation rel,
 											   false);
 			if (map)
 			{
-				mapped_pkattnum = palloc(sizeof(AttrNumber) * numfks);
+				mapped_pkattnum = palloc_array(AttrNumber, numfks);
 				for (int j = 0; j < numfks; j++)
 					mapped_pkattnum[j] = map->attnums[pkattnum[j] - 1];
 			}
@@ -11081,7 +11081,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
 
 			tab = ATGetQueueEntry(wqueue, rel);
 
-			newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+			newcon = palloc0_object(NewConstraint);
 			newcon->name = get_constraint_name(parentConstr);
 			newcon->contype = CONSTR_FOREIGN;
 			newcon->refrelid = RelationGetRelid(pkrel);
@@ -12503,7 +12503,7 @@ ATExecAlterConstrEnforceability(List **wqueue, ATAlterConstraint *cmdcon,
 			AlteredTableInfo *tab;
 			NewConstraint *newcon;
 
-			newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+			newcon = palloc0_object(NewConstraint);
 			newcon->name = fkconstraint->conname;
 			newcon->contype = CONSTR_FOREIGN;
 			newcon->refrelid = currcon->confrelid;
@@ -13019,7 +13019,7 @@ QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation fkrel,
 		/* for now this is all we need */
 		fkconstraint->conname = pstrdup(NameStr(con->conname));
 
-		newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+		newcon = palloc0_object(NewConstraint);
 		newcon->name = fkconstraint->conname;
 		newcon->contype = CONSTR_FOREIGN;
 		newcon->refrelid = con->confrelid;
@@ -13167,7 +13167,7 @@ QueueCheckConstraintValidation(List **wqueue, Relation conrel, Relation rel,
 	}
 
 	/* Queue validation for phase 3 */
-	newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+	newcon = palloc0_object(NewConstraint);
 	newcon->name = constrName;
 	newcon->contype = CONSTR_CHECK;
 	newcon->refrelid = InvalidOid;
@@ -14522,7 +14522,7 @@ ATPrepAlterColumnType(List **wqueue,
 		 * Add a work queue item to make ATRewriteTable update the column
 		 * contents.
 		 */
-		newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
+		newval = palloc0_object(NewColumnValue);
 		newval->attnum = attnum;
 		newval->expr = (Expr *) transform;
 		newval->is_generated = false;
@@ -19262,7 +19262,7 @@ register_on_commit_action(Oid relid, OnCommitAction action)
 
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
-	oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
+	oc = palloc_object(OnCommitItem);
 	oc->relid = relid;
 	oc->oncommit = action;
 	oc->creating_subid = GetCurrentSubTransactionId();
@@ -20575,8 +20575,8 @@ AttachPartitionEnsureIndexes(List **wqueue, Relation rel, Relation attachrel)
 
 	idxes = RelationGetIndexList(rel);
 	attachRelIdxs = RelationGetIndexList(attachrel);
-	attachrelIdxRels = palloc(sizeof(Relation) * list_length(attachRelIdxs));
-	attachInfos = palloc(sizeof(IndexInfo *) * list_length(attachRelIdxs));
+	attachrelIdxRels = palloc_array(Relation, list_length(attachRelIdxs));
+	attachInfos = palloc_array(IndexInfo *, list_length(attachRelIdxs));
 
 	/* Build arrays of all existing indexes and their IndexInfos */
 	foreach_oid(cldIdxId, attachRelIdxs)
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 579ac8d76ae..12c97f2c023 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -1991,7 +1991,7 @@ RelationBuildTriggers(Relation relation)
 	}
 
 	/* Build trigdesc */
-	trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
+	trigdesc = palloc0_object(TriggerDesc);
 	trigdesc->triggers = triggers;
 	trigdesc->numtriggers = numtrigs;
 	for (i = 0; i < numtrigs; i++)
@@ -2096,7 +2096,7 @@ CopyTriggerDesc(TriggerDesc *trigdesc)
 	if (trigdesc == NULL || trigdesc->numtriggers <= 0)
 		return NULL;
 
-	newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
+	newdesc = palloc_object(TriggerDesc);
 	memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
 
 	trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
@@ -4901,7 +4901,7 @@ GetAfterTriggersTableData(Oid relid, CmdType cmdType)
 
 	oldcxt = MemoryContextSwitchTo(CurTransactionContext);
 
-	table = (AfterTriggersTableData *) palloc0(sizeof(AfterTriggersTableData));
+	table = palloc0_object(AfterTriggersTableData);
 	table->relid = relid;
 	table->cmdType = cmdType;
 	qs->tables = lappend(qs->tables, table);
@@ -5050,7 +5050,7 @@ MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
 	MemoryContextSwitchTo(oldcxt);
 
 	/* Now build the TransitionCaptureState struct, in caller's context */
-	state = (TransitionCaptureState *) palloc0(sizeof(TransitionCaptureState));
+	state = palloc0_object(TransitionCaptureState);
 	state->tcs_delete_old_table = need_old_del;
 	state->tcs_update_old_table = need_old_upd;
 	state->tcs_update_new_table = need_new_upd;
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index dc7df736fb8..ec4580e17c9 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -1027,7 +1027,7 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
 		 * know that they will be used.
 		 */
 		max_slots = MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_ts_config_map);
-		slot = palloc(sizeof(TupleTableSlot *) * max_slots);
+		slot = palloc_array(TupleTableSlot *, max_slots);
 
 		ScanKeyInit(&skey,
 					Anum_pg_ts_config_map_mapcfg,
@@ -1261,7 +1261,7 @@ getTokenTypes(Oid prsId, List *tokennames)
 		{
 			if (strcmp(strVal(val), list[j].alias) == 0)
 			{
-				TSTokenTypeItem *ts = (TSTokenTypeItem *) palloc0(sizeof(TSTokenTypeItem));
+				TSTokenTypeItem *ts = palloc0_object(TSTokenTypeItem);
 
 				ts->num = list[j].lexid;
 				ts->name = pstrdup(strVal(val));
@@ -1344,7 +1344,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
 	 * Convert list of dictionary names to array of dict OIDs
 	 */
 	ndict = list_length(stmt->dicts);
-	dictIds = (Oid *) palloc(sizeof(Oid) * ndict);
+	dictIds = palloc_array(Oid, ndict);
 	i = 0;
 	foreach(c, stmt->dicts)
 	{
@@ -1432,7 +1432,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
 		/* Allocate the slots to use and initialize them */
 		nslots = Min(ntoken * ndict,
 					 MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_ts_config_map));
-		slot = palloc(sizeof(TupleTableSlot *) * nslots);
+		slot = palloc_array(TupleTableSlot *, nslots);
 		for (i = 0; i < nslots; i++)
 			slot[i] = MakeSingleTupleTableSlot(RelationGetDescr(relMap),
 											   &TTSOpsHeapTuple);
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 47d5047fe8b..0eb8e0a2bb0 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -3447,10 +3447,10 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode)
 			}
 
 			/* Build the RelToCheck entry with enough space for all atts */
-			rtc = (RelToCheck *) palloc(sizeof(RelToCheck));
+			rtc = palloc_object(RelToCheck);
 			rtc->rel = rel;
 			rtc->natts = 0;
-			rtc->atts = (int *) palloc(sizeof(int) * RelationGetNumberOfAttributes(rel));
+			rtc->atts = palloc_array(int, RelationGetNumberOfAttributes(rel));
 			result = lappend(result, rtc);
 		}
 
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 6ae42ea5656..ef4de1e7fd1 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -1904,7 +1904,7 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
 		else
 		{
 			Oid			objectId;
-			Oid		   *newmembers = palloc(sizeof(Oid));
+			Oid		   *newmembers = palloc_object(Oid);
 
 			/*
 			 * The values for these options can be taken directly from 'popt'.
@@ -2295,7 +2295,7 @@ initialize_revoke_actions(CatCList *memlist)
 	if (memlist->n_members == 0)
 		return NULL;
 
-	result = palloc(sizeof(RevokeRoleGrantAction) * memlist->n_members);
+	result = palloc_array(RevokeRoleGrantAction, memlist->n_members);
 	for (i = 0; i < memlist->n_members; i++)
 		result[i] = RRG_NOOP;
 	return result;
diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c
index 0feea1d30ec..8a37c08871a 100644
--- a/src/backend/commands/vacuumparallel.c
+++ b/src/backend/commands/vacuumparallel.c
@@ -268,7 +268,7 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes,
 	/*
 	 * Compute the number of parallel vacuum workers to launch
 	 */
-	will_parallel_vacuum = (bool *) palloc0(sizeof(bool) * nindexes);
+	will_parallel_vacuum = palloc0_array(bool, nindexes);
 	parallel_workers = parallel_vacuum_compute_workers(indrels, nindexes,
 													   nrequested_workers,
 													   will_parallel_vacuum);
@@ -279,7 +279,7 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes,
 		return NULL;
 	}
 
-	pvs = (ParallelVacuumState *) palloc0(sizeof(ParallelVacuumState));
+	pvs = palloc0_object(ParallelVacuumState);
 	pvs->indrels = indrels;
 	pvs->nindexes = nindexes;
 	pvs->will_parallel_vacuum = will_parallel_vacuum;
@@ -444,7 +444,7 @@ parallel_vacuum_end(ParallelVacuumState *pvs, IndexBulkDeleteResult **istats)
 
 		if (indstats->istat_updated)
 		{
-			istats[i] = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+			istats[i] = palloc0_object(IndexBulkDeleteResult);
 			memcpy(istats[i], &indstats->istat, sizeof(IndexBulkDeleteResult));
 		}
 		else
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index f1569879b52..33f1df7764b 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -1312,7 +1312,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				}
 
 				/* Set up the primary fmgr lookup information */
-				finfo = palloc0(sizeof(FmgrInfo));
+				finfo = palloc0_object(FmgrInfo);
 				fcinfo = palloc0(SizeForFunctionCallInfo(2));
 				fmgr_info(cmpfuncid, finfo);
 				fmgr_info_set_expr((Node *) node, finfo);
@@ -1388,7 +1388,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				/* allocate scratch memory used by all steps of AND/OR */
 				if (boolexpr->boolop != NOT_EXPR)
-					scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool));
+					scratch.d.boolexpr.anynull = palloc_object(bool);
 
 				/*
 				 * For each argument evaluate the argument itself, then
@@ -1521,11 +1521,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				ReleaseTupleDesc(tupDesc);
 
 				/* create workspace for column values */
-				values = (Datum *) palloc(sizeof(Datum) * ncolumns);
-				nulls = (bool *) palloc(sizeof(bool) * ncolumns);
+				values = palloc_array(Datum, ncolumns);
+				nulls = palloc_array(bool, ncolumns);
 
 				/* create shared composite-type-lookup cache struct */
-				rowcachep = palloc(sizeof(ExprEvalRowtypeCache));
+				rowcachep = palloc_object(ExprEvalRowtypeCache);
 				rowcachep->cacheptr = NULL;
 
 				/* emit code to evaluate the composite input value */
@@ -1634,7 +1634,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 					scratch.opcode = EEOP_IOCOERCE_SAFE;
 
 				/* lookup the source type's output function */
-				scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
+				scratch.d.iocoerce.finfo_out = palloc0_object(FmgrInfo);
 				scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfo(1));
 
 				getTypeOutputInfo(exprType((Node *) iocoerce->arg),
@@ -1646,7 +1646,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 										 1, InvalidOid, NULL, NULL);
 
 				/* lookup the result type's input function */
-				scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
+				scratch.d.iocoerce.finfo_in = palloc0_object(FmgrInfo);
 				scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3));
 
 				getTypeInputInfo(iocoerce->resulttype,
@@ -1699,8 +1699,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				elemstate->parent = state->parent;
 				elemstate->ext_params = state->ext_params;
 
-				elemstate->innermost_caseval = (Datum *) palloc(sizeof(Datum));
-				elemstate->innermost_casenull = (bool *) palloc(sizeof(bool));
+				elemstate->innermost_caseval = palloc_object(Datum);
+				elemstate->innermost_casenull = palloc_object(bool);
 
 				ExecInitExprRec(acoerce->elemexpr, elemstate,
 								&elemstate->resvalue, &elemstate->resnull);
@@ -1727,8 +1727,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				if (elemstate)
 				{
 					/* Set up workspace for array_map */
-					scratch.d.arraycoerce.amstate =
-						(ArrayMapState *) palloc0(sizeof(ArrayMapState));
+					scratch.d.arraycoerce.amstate = palloc0_object(ArrayMapState);
 				}
 				else
 				{
@@ -1783,8 +1782,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				if (caseExpr->arg != NULL)
 				{
 					/* Evaluate testexpr into caseval/casenull workspace */
-					caseval = palloc(sizeof(Datum));
-					casenull = palloc(sizeof(bool));
+					caseval = palloc_object(Datum);
+					casenull = palloc_object(bool);
 
 					ExecInitExprRec(caseExpr->arg, state,
 									caseval, casenull);
@@ -1930,9 +1929,9 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				 */
 				scratch.opcode = EEOP_ARRAYEXPR;
 				scratch.d.arrayexpr.elemvalues =
-					(Datum *) palloc(sizeof(Datum) * nelems);
+					palloc_array(Datum, nelems);
 				scratch.d.arrayexpr.elemnulls =
-					(bool *) palloc(sizeof(bool) * nelems);
+					palloc_array(bool, nelems);
 				scratch.d.arrayexpr.nelems = nelems;
 
 				/* fill remaining fields of step */
@@ -2006,9 +2005,9 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				/* space for the individual field datums */
 				scratch.d.row.elemvalues =
-					(Datum *) palloc(sizeof(Datum) * nelems);
+					palloc_array(Datum, nelems);
 				scratch.d.row.elemnulls =
-					(bool *) palloc(sizeof(bool) * nelems);
+					palloc_array(bool, nelems);
 				/* as explained above, make sure any extra columns are null */
 				memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems);
 
@@ -2109,7 +2108,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 							 BTORDER_PROC, lefttype, righttype, opfamily);
 
 					/* Set up the primary fmgr lookup information */
-					finfo = palloc0(sizeof(FmgrInfo));
+					finfo = palloc0_object(FmgrInfo);
 					fcinfo = palloc0(SizeForFunctionCallInfo(2));
 					fmgr_info(proc, finfo);
 					fmgr_info_set_expr((Node *) node, finfo);
@@ -2252,7 +2251,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				 */
 
 				/* Perform function lookup */
-				finfo = palloc0(sizeof(FmgrInfo));
+				finfo = palloc0_object(FmgrInfo);
 				fcinfo = palloc0(SizeForFunctionCallInfo(2));
 				fmgr_info(typentry->cmp_proc, finfo);
 				fmgr_info_set_expr((Node *) node, finfo);
@@ -2261,10 +2260,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				scratch.opcode = EEOP_MINMAX;
 				/* allocate space to store arguments */
-				scratch.d.minmax.values =
-					(Datum *) palloc(sizeof(Datum) * nelems);
-				scratch.d.minmax.nulls =
-					(bool *) palloc(sizeof(bool) * nelems);
+				scratch.d.minmax.values = palloc_array(Datum, nelems);
+				scratch.d.minmax.nulls = palloc_array(bool, nelems);
 				scratch.d.minmax.nelems = nelems;
 
 				scratch.d.minmax.op = minmaxexpr->op;
@@ -2313,10 +2310,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				/* allocate space for storing all the arguments */
 				if (nnamed)
 				{
-					scratch.d.xmlexpr.named_argvalue =
-						(Datum *) palloc(sizeof(Datum) * nnamed);
-					scratch.d.xmlexpr.named_argnull =
-						(bool *) palloc(sizeof(bool) * nnamed);
+					scratch.d.xmlexpr.named_argvalue = palloc_array(Datum, nnamed);
+					scratch.d.xmlexpr.named_argnull = palloc_array(bool, nnamed);
 				}
 				else
 				{
@@ -2326,10 +2321,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				if (nargs)
 				{
-					scratch.d.xmlexpr.argvalue =
-						(Datum *) palloc(sizeof(Datum) * nargs);
-					scratch.d.xmlexpr.argnull =
-						(bool *) palloc(sizeof(bool) * nargs);
+					scratch.d.xmlexpr.argvalue = palloc_array(Datum, nargs);
+					scratch.d.xmlexpr.argnull = palloc_array(bool, nargs);
 				}
 				else
 				{
@@ -2398,15 +2391,15 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				{
 					JsonConstructorExprState *jcstate;
 
-					jcstate = palloc0(sizeof(JsonConstructorExprState));
+					jcstate = palloc0_object(JsonConstructorExprState);
 
 					scratch.opcode = EEOP_JSON_CONSTRUCTOR;
 					scratch.d.json_constructor.jcstate = jcstate;
 
 					jcstate->constructor = ctor;
-					jcstate->arg_values = (Datum *) palloc(sizeof(Datum) * nargs);
-					jcstate->arg_nulls = (bool *) palloc(sizeof(bool) * nargs);
-					jcstate->arg_types = (Oid *) palloc(sizeof(Oid) * nargs);
+					jcstate->arg_values = palloc_array(Datum, nargs);
+					jcstate->arg_nulls = palloc_array(bool, nargs);
+					jcstate->arg_types = palloc_array(Oid, nargs);
 					jcstate->nargs = nargs;
 
 					foreach(lc, args)
@@ -2680,7 +2673,7 @@ ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
 	if (es->steps_alloc == 0)
 	{
 		es->steps_alloc = 16;
-		es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
+		es->steps = palloc_array(ExprEvalStep, es->steps_alloc);
 	}
 	else if (es->steps_alloc == es->steps_len)
 	{
@@ -2732,7 +2725,7 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
 							   FUNC_MAX_ARGS)));
 
 	/* Allocate function lookup data and parameter workspace for this call */
-	scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
+	scratch->d.func.finfo = palloc0_object(FmgrInfo);
 	scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs));
 	flinfo = scratch->d.func.finfo;
 	fcinfo = scratch->d.func.fcinfo_data;
@@ -3557,8 +3550,7 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
 	 * during executor initialization.  That means we don't need typcache.c to
 	 * provide compiled exprs.
 	 */
-	constraint_ref = (DomainConstraintRef *)
-		palloc(sizeof(DomainConstraintRef));
+	constraint_ref = palloc_object(DomainConstraintRef);
 	InitDomainConstraintRef(ctest->resulttype,
 							constraint_ref,
 							CurrentMemoryContext,
@@ -3588,9 +3580,9 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
 				if (scratch->d.domaincheck.checkvalue == NULL)
 				{
 					scratch->d.domaincheck.checkvalue =
-						(Datum *) palloc(sizeof(Datum));
+						palloc_object(Datum);
 					scratch->d.domaincheck.checknull =
-						(bool *) palloc(sizeof(bool));
+						palloc_object(bool);
 				}
 
 				/*
@@ -3608,8 +3600,8 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
 						ExprEvalStep scratch2 = {0};
 
 						/* Yes, so make output workspace for MAKE_READONLY */
-						domainval = (Datum *) palloc(sizeof(Datum));
-						domainnull = (bool *) palloc(sizeof(bool));
+						domainval = palloc_object(Datum);
+						domainnull = palloc_object(bool);
 
 						/* Emit MAKE_READONLY */
 						scratch2.opcode = EEOP_MAKE_READONLY;
@@ -4159,7 +4151,7 @@ ExecBuildHash32FromAttrs(TupleDesc desc, const TupleTableSlotOps *ops,
 	 * one column to hash or an initial value plus one column.
 	 */
 	if ((int64) numCols + (init_value != 0) > 1)
-		iresult = palloc(sizeof(NullableDatum));
+		iresult = palloc_object(NullableDatum);
 
 	/* find the highest attnum so we deform the tuple to that point */
 	for (int i = 0; i < numCols; i++)
@@ -4325,7 +4317,7 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops,
 	 * than one expression to hash or an initial value plus one expression.
 	 */
 	if ((int64) num_exprs + (init_value != 0) > 1)
-		iresult = palloc(sizeof(NullableDatum));
+		iresult = palloc_object(NullableDatum);
 
 	if (init_value == 0)
 	{
@@ -4371,7 +4363,7 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops,
 		funcid = hashfunc_oids[i];
 
 		/* Allocate hash function lookup data. */
-		finfo = palloc0(sizeof(FmgrInfo));
+		finfo = palloc0_object(FmgrInfo);
 		fcinfo = palloc0(SizeForFunctionCallInfo(1));
 
 		fmgr_info(funcid, finfo);
@@ -4540,7 +4532,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
 		InvokeFunctionExecuteHook(foid);
 
 		/* Set up the primary fmgr lookup information */
-		finfo = palloc0(sizeof(FmgrInfo));
+		finfo = palloc0_object(FmgrInfo);
 		fcinfo = palloc0(SizeForFunctionCallInfo(2));
 		fmgr_info(foid, finfo);
 		fmgr_info_set_expr(NULL, finfo);
@@ -4676,7 +4668,7 @@ ExecBuildParamSetEqual(TupleDesc desc,
 		InvokeFunctionExecuteHook(foid);
 
 		/* Set up the primary fmgr lookup information */
-		finfo = palloc0(sizeof(FmgrInfo));
+		finfo = palloc0_object(FmgrInfo);
 		fcinfo = palloc0(SizeForFunctionCallInfo(2));
 		fmgr_info(foid, finfo);
 		fmgr_info_set_expr(NULL, finfo);
@@ -4749,7 +4741,7 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
 				 Datum *resv, bool *resnull,
 				 ExprEvalStep *scratch)
 {
-	JsonExprState *jsestate = palloc0(sizeof(JsonExprState));
+	JsonExprState *jsestate = palloc0_object(JsonExprState);
 	ListCell   *argexprlc;
 	ListCell   *argnamelc;
 	List	   *jumps_return_null = NIL;
@@ -4800,7 +4792,7 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
 	{
 		Expr	   *argexpr = (Expr *) lfirst(argexprlc);
 		String	   *argname = lfirst_node(String, argnamelc);
-		JsonPathVariable *var = palloc(sizeof(*var));
+		JsonPathVariable *var = palloc_object(JsonPathVariable);
 
 		var->name = argname->sval;
 		var->namelen = strlen(var->name);
@@ -4874,7 +4866,7 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
 		FunctionCallInfo fcinfo;
 
 		getTypeInputInfo(jsexpr->returning->typid, &typinput, &typioparam);
-		finfo = palloc0(sizeof(FmgrInfo));
+		finfo = palloc0_object(FmgrInfo);
 		fcinfo = palloc0(SizeForFunctionCallInfo(3));
 		fmgr_info(typinput, finfo);
 		fmgr_info_set_expr((Node *) jsexpr->returning, finfo);
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 8b64a625ca5..3336ddaff79 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -224,7 +224,7 @@ BuildTupleHashTable(PlanState *parent,
 
 	oldcontext = MemoryContextSwitchTo(metacxt);
 
-	hashtable = (TupleHashTable) palloc(sizeof(TupleHashTableData));
+	hashtable = (TupleHashTable) palloc_object(TupleHashTableData);
 
 	hashtable->numCols = numCols;
 	hashtable->keyColIdx = keyColIdx;
diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c
index d1cbab58799..99581baeeb0 100644
--- a/src/backend/executor/execIndexing.c
+++ b/src/backend/executor/execIndexing.c
@@ -188,8 +188,8 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
 	/*
 	 * allocate space for result arrays
 	 */
-	relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
-	indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));
+	relationDescs = palloc_array(Relation, len);
+	indexInfoArray = palloc_array(IndexInfo *, len);
 
 	resultRelInfo->ri_NumIndices = len;
 	resultRelInfo->ri_IndexRelationDescs = relationDescs;
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 27c9eec697b..3ae349cc8f8 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -189,7 +189,7 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
 
 		nParamExec = list_length(queryDesc->plannedstmt->paramExecTypes);
 		estate->es_param_exec_vals = (ParamExecData *)
-			palloc0(nParamExec * sizeof(ParamExecData));
+			palloc0_array(ParamExecData, nParamExec);
 	}
 
 	/* We now require all callers to provide sourceText */
@@ -876,7 +876,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
 	if (plannedstmt->rowMarks)
 	{
 		estate->es_rowmarks = (ExecRowMark **)
-			palloc0(estate->es_range_table_size * sizeof(ExecRowMark *));
+			palloc0_array(ExecRowMark *, estate->es_range_table_size);
 		foreach(l, plannedstmt->rowMarks)
 		{
 			PlanRowMark *rc = (PlanRowMark *) lfirst(l);
@@ -920,7 +920,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
 			if (relation)
 				CheckValidRowMarkRel(relation, rc->markType);
 
-			erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
+			erm = palloc_object(ExecRowMark);
 			erm->relation = relation;
 			erm->relid = relid;
 			erm->rti = rc->rti;
@@ -1262,9 +1262,9 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
 		int			n = resultRelInfo->ri_TrigDesc->numtriggers;
 
 		resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
-			palloc0(n * sizeof(FmgrInfo));
+			palloc0_array(FmgrInfo, n);
 		resultRelInfo->ri_TrigWhenExprs = (ExprState **)
-			palloc0(n * sizeof(ExprState *));
+			palloc0_array(ExprState *, n);
 		if (instrument_options)
 			resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options, false);
 	}
@@ -2578,7 +2578,7 @@ ExecFindRowMark(EState *estate, Index rti, bool missing_ok)
 ExecAuxRowMark *
 ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
 {
-	ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
+	ExecAuxRowMark *aerm = palloc0_object(ExecAuxRowMark);
 	char		resname[32];
 
 	aerm->rowmark = erm;
@@ -2735,7 +2735,7 @@ EvalPlanQualInit(EPQState *epqstate, EState *parentestate,
 	 */
 	epqstate->tuple_table = NIL;
 	epqstate->relsubs_slot = (TupleTableSlot **)
-		palloc0(rtsize * sizeof(TupleTableSlot *));
+		palloc0_array(TupleTableSlot *, rtsize);
 
 	/* ... and remember data that EvalPlanQualBegin will need */
 	epqstate->plan = subplan;
@@ -3075,7 +3075,7 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
 		/* now make the internal param workspace ... */
 		i = list_length(parentestate->es_plannedstmt->paramExecTypes);
 		rcestate->es_param_exec_vals = (ParamExecData *)
-			palloc0(i * sizeof(ParamExecData));
+			palloc0_array(ParamExecData, i);
 		/* ... and copy down all values, whether really needed or not */
 		while (--i >= 0)
 		{
@@ -3131,7 +3131,7 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
 	 * rowmark.
 	 */
 	epqstate->relsubs_rowmark = (ExecAuxRowMark **)
-		palloc0(rtsize * sizeof(ExecAuxRowMark *));
+		palloc0_array(ExecAuxRowMark *, rtsize);
 	foreach(l, epqstate->arowMarks)
 	{
 		ExecAuxRowMark *earm = (ExecAuxRowMark *) lfirst(l);
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index f098a5557cf..d084c325979 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -636,7 +636,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate,
 	ExecSetParamPlanMulti(sendParams, GetPerTupleExprContext(estate));
 
 	/* Allocate object for return value. */
-	pei = palloc0(sizeof(ParallelExecutorInfo));
+	pei = palloc0_object(ParallelExecutorInfo);
 	pei->finished = false;
 	pei->planstate = planstate;
 
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 0dcce181f09..0f8e352280d 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -226,7 +226,7 @@ ExecSetupPartitionTupleRouting(EState *estate, Relation rel)
 	 * The reason for this is that a common case is for INSERT to insert a
 	 * single tuple into a partitioned table and this must be fast.
 	 */
-	proute = (PartitionTupleRouting *) palloc0(sizeof(PartitionTupleRouting));
+	proute = palloc0_object(PartitionTupleRouting);
 	proute->partition_root = rel;
 	proute->memcxt = CurrentMemoryContext;
 	/* Rest of members initialized by zeroing */
@@ -1066,10 +1066,8 @@ ExecInitRoutingInfo(ModifyTableState *mtstate,
 		if (proute->max_partitions == 0)
 		{
 			proute->max_partitions = 8;
-			proute->partitions = (ResultRelInfo **)
-				palloc(sizeof(ResultRelInfo *) * proute->max_partitions);
-			proute->is_borrowed_rel = (bool *)
-				palloc(sizeof(bool) * proute->max_partitions);
+			proute->partitions = palloc_array(ResultRelInfo *, proute->max_partitions);
+			proute->is_borrowed_rel = palloc_array(bool, proute->max_partitions);
 		}
 		else
 		{
@@ -1184,10 +1182,8 @@ ExecInitPartitionDispatchInfo(EState *estate,
 		if (proute->max_dispatch == 0)
 		{
 			proute->max_dispatch = 4;
-			proute->partition_dispatch_info = (PartitionDispatch *)
-				palloc(sizeof(PartitionDispatch) * proute->max_dispatch);
-			proute->nonleaf_partitions = (ResultRelInfo **)
-				palloc(sizeof(ResultRelInfo *) * proute->max_dispatch);
+			proute->partition_dispatch_info = palloc_array(PartitionDispatch, proute->max_dispatch);
+			proute->nonleaf_partitions = palloc_array(ResultRelInfo *, proute->max_dispatch);
 		}
 		else
 		{
@@ -2079,7 +2075,7 @@ CreatePartitionPruneState(EState *estate, PartitionPruneInfo *pruneinfo,
 			 * arrays are in partition bounds order.
 			 */
 			pprune->nparts = partdesc->nparts;
-			pprune->subplan_map = palloc(sizeof(int) * partdesc->nparts);
+			pprune->subplan_map = palloc_array(int, partdesc->nparts);
 
 			if (partdesc->nparts == pinfo->nparts &&
 				memcmp(partdesc->oids, pinfo->relid_map,
@@ -2106,8 +2102,8 @@ CreatePartitionPruneState(EState *estate, PartitionPruneInfo *pruneinfo,
 				 * attached.  Cope with that by creating a map that skips any
 				 * mismatches.
 				 */
-				pprune->subpart_map = palloc(sizeof(int) * partdesc->nparts);
-				pprune->leafpart_rti_map = palloc(sizeof(int) * partdesc->nparts);
+				pprune->subpart_map = palloc_array(int, partdesc->nparts);
+				pprune->leafpart_rti_map = palloc_array(int, partdesc->nparts);
 
 				for (pp_idx = 0; pp_idx < partdesc->nparts; pp_idx++)
 				{
@@ -2258,16 +2254,14 @@ InitPartitionPruneContext(PartitionPruneContext *context,
 	context->partsupfunc = partkey->partsupfunc;
 
 	/* We'll look up type-specific support functions as needed */
-	context->stepcmpfuncs = (FmgrInfo *)
-		palloc0(sizeof(FmgrInfo) * n_steps * partnatts);
+	context->stepcmpfuncs = palloc0_array(FmgrInfo, n_steps * partnatts);
 
 	context->ppccontext = CurrentMemoryContext;
 	context->planstate = planstate;
 	context->exprcontext = econtext;
 
 	/* Initialize expression state for each expression we need */
-	context->exprstates = (ExprState **)
-		palloc0(sizeof(ExprState *) * n_steps * partnatts);
+	context->exprstates = palloc0_array(ExprState *, n_steps * partnatts);
 	foreach(lc, pruning_steps)
 	{
 		PartitionPruneStepOp *step = (PartitionPruneStepOp *) lfirst(lc);
@@ -2368,7 +2362,7 @@ InitExecPartitionPruneContexts(PartitionPruneState *prunestate,
 		 * indexes to new ones.  For convenience of initialization, we use
 		 * 1-based indexes in this array and leave pruned items as 0.
 		 */
-		new_subplan_indexes = (int *) palloc0(sizeof(int) * n_total_subplans);
+		new_subplan_indexes = palloc0_array(int, n_total_subplans);
 		newidx = 1;
 		i = -1;
 		while ((i = bms_next_member(initially_valid_subplans, i)) >= 0)
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
index def32774c90..860f79f9cc1 100644
--- a/src/backend/executor/execReplication.c
+++ b/src/backend/executor/execReplication.c
@@ -221,7 +221,7 @@ retry:
 		if (!isIdxSafeToSkipDuplicates)
 		{
 			if (eq == NULL)
-				eq = palloc0(sizeof(*eq) * outslot->tts_tupleDescriptor->natts);
+				eq = palloc0_array(TypeCacheEntry *, outslot->tts_tupleDescriptor->natts);
 
 			if (!tuples_equal(outslot, searchslot, eq, NULL))
 				continue;
@@ -378,7 +378,7 @@ RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode,
 
 	Assert(equalTupleDescs(desc, outslot->tts_tupleDescriptor));
 
-	eq = palloc0(sizeof(*eq) * outslot->tts_tupleDescriptor->natts);
+	eq = palloc0_array(TypeCacheEntry *, outslot->tts_tupleDescriptor->natts);
 
 	/* Start a heap scan. */
 	InitDirtySnapshot(snap);
@@ -593,7 +593,7 @@ RelationFindDeletedTupleInfoSeq(Relation rel, TupleTableSlot *searchslot,
 		indexbitmap = RelationGetIndexAttrBitmap(rel,
 												 INDEX_ATTR_BITMAP_PRIMARY_KEY);
 
-	eq = palloc0(sizeof(*eq) * searchslot->tts_tupleDescriptor->natts);
+	eq = palloc0_array(TypeCacheEntry *, searchslot->tts_tupleDescriptor->natts);
 
 	/*
 	 * Start a heap scan using SnapshotAny to identify dead tuples that are
@@ -679,7 +679,7 @@ RelationFindDeletedTupleInfoByIndex(Relation rel, Oid idxoid,
 		if (!isIdxSafeToSkipDuplicates)
 		{
 			if (eq == NULL)
-				eq = palloc0(sizeof(*eq) * scanslot->tts_tupleDescriptor->natts);
+				eq = palloc0_array(TypeCacheEntry *, scanslot->tts_tupleDescriptor->natts);
 
 			if (!tuples_equal(scanslot, searchslot, eq, NULL))
 				continue;
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 8e02d68824f..b0dc2cfa66f 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -2283,7 +2283,7 @@ TupleDescGetAttInMetadata(TupleDesc tupdesc)
 	int32	   *atttypmods;
 	AttInMetadata *attinmeta;
 
-	attinmeta = (AttInMetadata *) palloc(sizeof(AttInMetadata));
+	attinmeta = palloc_object(AttInMetadata);
 
 	/* "Bless" the tupledesc so that we can make rowtype datums with it */
 	attinmeta->tupdesc = BlessTupleDesc(tupdesc);
@@ -2447,7 +2447,7 @@ begin_tup_output_tupdesc(DestReceiver *dest,
 {
 	TupOutputState *tstate;
 
-	tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
+	tstate = palloc_object(TupOutputState);
 
 	tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
 	tstate->dest = dest;
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 630d708d2a3..64e2ada7960 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -256,7 +256,7 @@ prepare_sql_fn_parse_info(HeapTuple procedureTuple,
 	Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
 	int			nargs;
 
-	pinfo = (SQLFunctionParseInfoPtr) palloc0(sizeof(SQLFunctionParseInfo));
+	pinfo = (SQLFunctionParseInfoPtr) palloc0_object(SQLFunctionParseInfo); 
 
 	/* Function's name (only) can be used to qualify argument names */
 	pinfo->fname = pstrdup(NameStr(procedureStruct->proname));
@@ -2616,7 +2616,7 @@ get_sql_fn_result_tlist(List *queryTreeList)
 DestReceiver *
 CreateSQLFunctionDestReceiver(void)
 {
-	DR_sqlfunction *self = (DR_sqlfunction *) palloc0(sizeof(DR_sqlfunction));
+	DR_sqlfunction *self = palloc0_object(DR_sqlfunction);
 
 	self->pub.receiveSlot = sqlfunction_receive;
 	self->pub.rStartup = sqlfunction_startup;
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 0b02fd32107..a18556f62ec 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1920,7 +1920,7 @@ hash_agg_enter_spill_mode(AggState *aggstate)
 
 		aggstate->hash_tapeset = LogicalTapeSetCreate(true, NULL, -1);
 
-		aggstate->hash_spills = palloc(sizeof(HashAggSpill) * aggstate->num_hashes);
+		aggstate->hash_spills = palloc_array(HashAggSpill, aggstate->num_hashes);
 
 		for (int setno = 0; setno < aggstate->num_hashes; setno++)
 		{
@@ -2999,9 +2999,9 @@ hashagg_spill_init(HashAggSpill *spill, LogicalTapeSet *tapeset, int used_bits,
 	}
 #endif
 
-	spill->partitions = palloc0(sizeof(LogicalTape *) * npartitions);
-	spill->ntuples = palloc0(sizeof(int64) * npartitions);
-	spill->hll_card = palloc0(sizeof(hyperLogLogState) * npartitions);
+	spill->partitions = palloc0_array(LogicalTape *, npartitions);
+	spill->ntuples = palloc0_array(int64, npartitions);
+	spill->hll_card = palloc0_array(hyperLogLogState, npartitions);
 
 	for (int i = 0; i < npartitions; i++)
 		spill->partitions[i] = LogicalTapeCreate(tapeset);
@@ -3097,7 +3097,7 @@ static HashAggBatch *
 hashagg_batch_new(LogicalTape *input_tape, int setno,
 				  int64 input_tuples, double input_card, int used_bits)
 {
-	HashAggBatch *batch = palloc0(sizeof(HashAggBatch));
+	HashAggBatch *batch = palloc0_object(HashAggBatch);
 
 	batch->setno = setno;
 	batch->used_bits = used_bits;
@@ -3368,8 +3368,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	aggstate->maxsets = numGroupingSets;
 	aggstate->numphases = numPhases;
 
-	aggstate->aggcontexts = (ExprContext **)
-		palloc0(sizeof(ExprContext *) * numGroupingSets);
+	aggstate->aggcontexts = palloc0_array(ExprContext *, numGroupingSets);
 
 	/*
 	 * Create expression contexts.  We need three or more, one for
@@ -3492,15 +3491,15 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	 * For each phase, prepare grouping set data and fmgr lookup data for
 	 * compare functions.  Accumulate all_grouped_cols in passing.
 	 */
-	aggstate->phases = palloc0(numPhases * sizeof(AggStatePerPhaseData));
+	aggstate->phases = palloc0_array(AggStatePerPhaseData, numPhases);
 
 	aggstate->num_hashes = numHashes;
 	if (numHashes)
 	{
-		aggstate->perhash = palloc0(sizeof(AggStatePerHashData) * numHashes);
+		aggstate->perhash = palloc0_array(AggStatePerHashData, numHashes);
 		aggstate->phases[0].numsets = 0;
-		aggstate->phases[0].gset_lengths = palloc(numHashes * sizeof(int));
-		aggstate->phases[0].grouped_cols = palloc(numHashes * sizeof(Bitmapset *));
+		aggstate->phases[0].gset_lengths = palloc_array(int, numHashes);
+		aggstate->phases[0].grouped_cols = palloc_array(Bitmapset *, numHashes);
 	}
 
 	phase = 0;
@@ -3598,8 +3597,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 				 * Build a separate function for each subset of columns that
 				 * need to be compared.
 				 */
-				phasedata->eqfunctions =
-					(ExprState **) palloc0(aggnode->numCols * sizeof(ExprState *));
+				phasedata->eqfunctions = palloc0_array(ExprState *, aggnode->numCols);
 
 				/* for each grouping set */
 				for (int k = 0; k < phasedata->numsets; k++)
@@ -3655,27 +3653,24 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	 * allocate my private per-agg working storage
 	 */
 	econtext = aggstate->ss.ps.ps_ExprContext;
-	econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
-	econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
+	econtext->ecxt_aggvalues = palloc0_array(Datum, numaggs);
+	econtext->ecxt_aggnulls = palloc0_array(bool, numaggs);
 
-	peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
-	pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numtrans);
+	peraggs = palloc0_array(AggStatePerAggData, numaggs);
+	pertransstates = palloc0_array(AggStatePerTransData, numtrans);
 
 	aggstate->peragg = peraggs;
 	aggstate->pertrans = pertransstates;
 
 
-	aggstate->all_pergroups =
-		(AggStatePerGroup *) palloc0(sizeof(AggStatePerGroup)
-									 * (numGroupingSets + numHashes));
+	aggstate->all_pergroups = palloc0_array(AggStatePerGroup, numGroupingSets + numHashes);
 	pergroups = aggstate->all_pergroups;
 
 	if (node->aggstrategy != AGG_HASHED)
 	{
 		for (i = 0; i < numGroupingSets; i++)
 		{
-			pergroups[i] = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
-													  * numaggs);
+			pergroups[i] = palloc0_array(AggStatePerGroupData, numaggs);
 		}
 
 		aggstate->pergroups = pergroups;
@@ -4375,8 +4370,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 		pfree(ops);
 	}
 
-	pertrans->sortstates = (Tuplesortstate **)
-		palloc0(sizeof(Tuplesortstate *) * numGroupingSets);
+	pertrans->sortstates = palloc0_array(Tuplesortstate *, numGroupingSets);
 }
 
 
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index a11b36c7176..77c4dd9e4b1 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -263,7 +263,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
 		{
 			AsyncRequest *areq;
 
-			areq = palloc(sizeof(AsyncRequest));
+			areq = palloc_object(AsyncRequest);
 			areq->requestor = (PlanState *) appendstate;
 			areq->requestee = appendplanstates[i];
 			areq->request_index = i;
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 644363582d9..af75dd8fc5e 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -333,7 +333,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 	 */
 	ExecAssignExprContext(estate, &scanstate->ss.ps);
 
-	scanstate->funcstates = palloc(nfuncs * sizeof(FunctionScanPerFuncState));
+	scanstate->funcstates = palloc_array(FunctionScanPerFuncState, nfuncs);
 
 	natts = 0;
 	i = 0;
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
index 93f3dbc6cf4..c04522fea4d 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -145,8 +145,7 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
 		int			i;
 
 		gm_state->gm_nkeys = node->numCols;
-		gm_state->gm_sortkeys =
-			palloc0(sizeof(SortSupportData) * node->numCols);
+		gm_state->gm_sortkeys = palloc0_array(SortSupportData, node->numCols);
 
 		for (i = 0; i < node->numCols; i++)
 		{
@@ -418,8 +417,7 @@ gather_merge_setup(GatherMergeState *gm_state)
 	for (i = 0; i < nreaders; i++)
 	{
 		/* Allocate the tuple array with length MAX_TUPLE_STORE */
-		gm_state->gm_tuple_buffers[i].tuple =
-			(MinimalTuple *) palloc0(sizeof(MinimalTuple) * MAX_TUPLE_STORE);
+		gm_state->gm_tuple_buffers[i].tuple = palloc0_array(MinimalTuple, MAX_TUPLE_STORE);
 
 		/* Initialize tuple slot for worker */
 		gm_state->gm_slots[i + 1] =
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 5661ad76830..cc50bee19eb 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -899,7 +899,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
 		 */
 		if (OidIsValid(hash->skewTable))
 		{
-			hashstate->skew_hashfunction = palloc0(sizeof(FmgrInfo));
+			hashstate->skew_hashfunction = palloc0_object(FmgrInfo);
 			hashstate->skew_collation = linitial_oid(node->hashcollations);
 			fmgr_info(outer_hashfuncid[0], hashstate->skew_hashfunction);
 		}
@@ -1541,8 +1541,7 @@ ExecReScanHashJoin(HashJoinState *node)
 			/* accumulate stats from old hash table, if wanted */
 			/* (this should match ExecShutdownHash) */
 			if (hashNode->ps.instrument && !hashNode->hinstrument)
-				hashNode->hinstrument = (HashInstrumentation *)
-					palloc0(sizeof(HashInstrumentation));
+				hashNode->hinstrument = palloc0_object(HashInstrumentation);
 			if (hashNode->hinstrument)
 				ExecHashAccumInstrumentation(hashNode->hinstrument,
 											 hashNode->hashtable);
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index f464cca9507..6bea42f128f 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -693,8 +693,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 		 * Now create an array to mark the attribute numbers of the keys that
 		 * need to be converted from cstring to name.
 		 */
-		indexstate->ioss_NameCStringAttNums = (AttrNumber *)
-			palloc(sizeof(AttrNumber) * namecount);
+		indexstate->ioss_NameCStringAttNums = palloc_array(AttrNumber, namecount);
 
 		for (int attnum = 0; attnum < indnkeyatts; attnum++)
 		{
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index f36929deec3..72b135e5dcf 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -466,12 +466,10 @@ reorderqueue_push(IndexScanState *node, TupleTableSlot *slot,
 	ReorderTuple *rt;
 	int			i;
 
-	rt = (ReorderTuple *) palloc(sizeof(ReorderTuple));
+	rt = palloc_object(ReorderTuple);
 	rt->htup = ExecCopySlotHeapTuple(slot);
-	rt->orderbyvals =
-		(Datum *) palloc(sizeof(Datum) * scandesc->numberOfOrderBys);
-	rt->orderbynulls =
-		(bool *) palloc(sizeof(bool) * scandesc->numberOfOrderBys);
+	rt->orderbyvals = palloc_array(Datum, scandesc->numberOfOrderBys);
+	rt->orderbynulls = palloc_array(bool, scandesc->numberOfOrderBys);
 	for (i = 0; i < node->iss_NumOrderByKeys; i++)
 	{
 		if (!orderbynulls[i])
diff --git a/src/backend/executor/nodeMemoize.c b/src/backend/executor/nodeMemoize.c
index d652663cb6a..7444391e8a1 100644
--- a/src/backend/executor/nodeMemoize.c
+++ b/src/backend/executor/nodeMemoize.c
@@ -555,7 +555,7 @@ cache_lookup(MemoizeState *mstate, bool *found)
 	oldcontext = MemoryContextSwitchTo(mstate->tableContext);
 
 	/* Allocate a new key */
-	entry->key = key = (MemoizeKey *) palloc(sizeof(MemoizeKey));
+	entry->key = key = palloc_object(MemoizeKey);
 	key->params = ExecCopySlotMinimalTuple(mstate->probeslot);
 
 	/* Update the total cache memory utilization */
@@ -634,7 +634,7 @@ cache_store_tuple(MemoizeState *mstate, TupleTableSlot *slot)
 
 	oldcontext = MemoryContextSwitchTo(mstate->tableContext);
 
-	tuple = (MemoizeTuple *) palloc(sizeof(MemoizeTuple));
+	tuple = palloc_object(MemoizeTuple);
 	tuple->mintuple = ExecCopySlotMinimalTuple(slot);
 	tuple->next = NULL;
 
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index 405e8f94285..300bcd5cf33 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -122,11 +122,11 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
 		mergestate->ms_prune_state = NULL;
 	}
 
-	mergeplanstates = (PlanState **) palloc(nplans * sizeof(PlanState *));
+	mergeplanstates = palloc_array(PlanState *, nplans);
 	mergestate->mergeplans = mergeplanstates;
 	mergestate->ms_nplans = nplans;
 
-	mergestate->ms_slots = (TupleTableSlot **) palloc0(sizeof(TupleTableSlot *) * nplans);
+	mergestate->ms_slots = palloc0_array(TupleTableSlot *, nplans);
 	mergestate->ms_heap = binaryheap_allocate(nplans, heap_compare_slots,
 											  mergestate);
 
@@ -174,7 +174,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
 	 * initialize sort-key information
 	 */
 	mergestate->ms_nkeys = node->numCols;
-	mergestate->ms_sortkeys = palloc0(sizeof(SortSupportData) * node->numCols);
+	mergestate->ms_sortkeys = palloc0_array(SortSupportData, node->numCols);
 
 	for (i = 0; i < node->numCols; i++)
 	{
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index e44f1223886..874b71e6608 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -581,8 +581,8 @@ ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo,
 
 	oldContext = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
 
-	values = palloc(sizeof(*values) * natts);
-	nulls = palloc(sizeof(*nulls) * natts);
+	values = palloc_array(Datum, natts);
+	nulls = palloc_array(bool, natts);
 
 	slot_getallattrs(slot);
 	memcpy(nulls, slot->tts_isnull, sizeof(*nulls) * natts);
@@ -962,10 +962,8 @@ ExecInsert(ModifyTableContext *context,
 
 			if (resultRelInfo->ri_Slots == NULL)
 			{
-				resultRelInfo->ri_Slots = palloc(sizeof(TupleTableSlot *) *
-												 resultRelInfo->ri_BatchSize);
-				resultRelInfo->ri_PlanSlots = palloc(sizeof(TupleTableSlot *) *
-													 resultRelInfo->ri_BatchSize);
+				resultRelInfo->ri_Slots = palloc_array(TupleTableSlot *, resultRelInfo->ri_BatchSize);
+				resultRelInfo->ri_PlanSlots = palloc_array(TupleTableSlot *, resultRelInfo->ri_BatchSize);
 			}
 
 			/*
@@ -4745,8 +4743,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 	mtstate->mt_done = false;
 
 	mtstate->mt_nrels = nrels;
-	mtstate->resultRelInfo = (ResultRelInfo *)
-		palloc(nrels * sizeof(ResultRelInfo));
+	mtstate->resultRelInfo = palloc_array(ResultRelInfo, nrels);
 
 	mtstate->mt_merge_pending_not_matched = NULL;
 	mtstate->mt_merge_inserted = 0;
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index 880f39fb2ff..7d621cebc7b 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -267,10 +267,8 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
 
 	/* Create workspace for per-tlist-entry expr state & SRF-is-done state */
 	state->nelems = list_length(node->plan.targetlist);
-	state->elems = (Node **)
-		palloc(sizeof(Node *) * state->nelems);
-	state->elemdone = (ExprDoneCond *)
-		palloc(sizeof(ExprDoneCond) * state->nelems);
+	state->elems = palloc_array(Node *, state->nelems);
+	state->elemdone = palloc_array(ExprDoneCond, state->nelems);
 
 	/*
 	 * Build expressions to evaluate targetlist.  We can't use
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index 6b3db7548ed..c28bc6fc620 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -228,7 +228,7 @@ tablesample_init(SampleScanState *scanstate)
 	ListCell   *arg;
 
 	scanstate->donetuples = 0;
-	params = (Datum *) palloc(list_length(scanstate->args) * sizeof(Datum));
+	params = palloc_array(Datum, list_length(scanstate->args));
 
 	i = 0;
 	foreach(arg, scanstate->args)
diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c
index 83ade3f9437..dfad19052a6 100644
--- a/src/backend/executor/nodeTableFuncscan.c
+++ b/src/backend/executor/nodeTableFuncscan.c
@@ -192,8 +192,8 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
 	scanstate->notnulls = tf->notnulls;
 
 	/* these are allocated now and initialized later */
-	scanstate->in_functions = palloc(sizeof(FmgrInfo) * tupdesc->natts);
-	scanstate->typioparams = palloc(sizeof(Oid) * tupdesc->natts);
+	scanstate->in_functions = palloc_array(FmgrInfo, tupdesc->natts);
+	scanstate->typioparams = palloc_array(Oid, tupdesc->natts);
 
 	/*
 	 * Fill in the necessary fmgr infos.
diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c
index 1bce8d6cbfe..0e43fdedb7f 100644
--- a/src/backend/executor/nodeTidrangescan.c
+++ b/src/backend/executor/nodeTidrangescan.c
@@ -72,7 +72,7 @@ MakeTidOpExpr(OpExpr *expr, TidRangeScanState *tidstate)
 	else
 		elog(ERROR, "could not identify CTID variable");
 
-	tidopexpr = (TidOpExpr *) palloc(sizeof(TidOpExpr));
+	tidopexpr = palloc_object(TidOpExpr);
 	tidopexpr->inclusive = false;	/* for now */
 
 	switch (expr->opno)
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index d50c6600358..35fcd5625db 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -78,7 +78,7 @@ TidExprListCreate(TidScanState *tidstate)
 	foreach(l, node->tidquals)
 	{
 		Expr	   *expr = (Expr *) lfirst(l);
-		TidExpr    *tidexpr = (TidExpr *) palloc0(sizeof(TidExpr));
+		TidExpr    *tidexpr = palloc0_object(TidExpr);
 
 		if (is_opclause(expr))
 		{
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 3a0d1f0c922..c0e5ab8dbbf 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -2661,14 +2661,14 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 	numfuncs = winstate->numfuncs;
 	numaggs = winstate->numaggs;
 	econtext = winstate->ss.ps.ps_ExprContext;
-	econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numfuncs);
-	econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numfuncs);
+	econtext->ecxt_aggvalues = palloc0_array(Datum, numfuncs);
+	econtext->ecxt_aggnulls = palloc0_array(bool, numfuncs);
 
 	/*
 	 * allocate per-wfunc/per-agg state information.
 	 */
-	perfunc = (WindowStatePerFunc) palloc0(sizeof(WindowStatePerFuncData) * numfuncs);
-	peragg = (WindowStatePerAgg) palloc0(sizeof(WindowStatePerAggData) * numaggs);
+	perfunc = palloc0_array(WindowStatePerFuncData, numfuncs);
+	peragg = palloc0_array(WindowStatePerAggData, numaggs);
 	winstate->perfunc = perfunc;
 	winstate->peragg = peragg;
 
@@ -3467,8 +3467,8 @@ init_notnull_info(WindowObject winobj, WindowStatePerFunc perfuncstate)
 
 	if (winobj->ignore_nulls == PARSER_IGNORE_NULLS)
 	{
-		winobj->notnull_info = palloc0(sizeof(uint8 *) * numargs);
-		winobj->num_notnull_info = palloc0(sizeof(int64) * numargs);
+		winobj->notnull_info = palloc0_array(uint8 *, numargs);
+		winobj->num_notnull_info = palloc0_array(int64, numargs);
 	}
 }
 
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 653500b38dc..34a63a977b6 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1130,8 +1130,8 @@ SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
 	SPI_result = 0;
 
 	numberOfAttributes = rel->rd_att->natts;
-	v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
-	n = (bool *) palloc(numberOfAttributes * sizeof(bool));
+	v = palloc_array(Datum, numberOfAttributes);
+	n = palloc_array(bool, numberOfAttributes);
 
 	/* fetch old values and nulls */
 	heap_deform_tuple(tuple, rel->rd_att, v, n);
@@ -2141,8 +2141,7 @@ spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
 									  ALLOCSET_DEFAULT_SIZES);
 	MemoryContextSwitchTo(tuptabcxt);
 
-	_SPI_current->tuptable = tuptable = (SPITupleTable *)
-		palloc0(sizeof(SPITupleTable));
+	_SPI_current->tuptable = tuptable = palloc0_object(SPITupleTable);
 	tuptable->tuptabcxt = tuptabcxt;
 	tuptable->subid = GetCurrentSubTransactionId();
 
@@ -2155,7 +2154,7 @@ spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
 
 	/* set up initial allocations */
 	tuptable->alloced = 128;
-	tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
+	tuptable->vals = palloc_array(HeapTuple, tuptable->alloced);
 	tuptable->numvals = 0;
 	tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
 
@@ -3162,7 +3161,7 @@ _SPI_make_plan_non_temp(SPIPlanPtr plan)
 	oldcxt = MemoryContextSwitchTo(plancxt);
 
 	/* Copy the _SPI_plan struct and subsidiary data into the new context */
-	newplan = (SPIPlanPtr) palloc0(sizeof(_SPI_plan));
+	newplan = palloc0_object(_SPI_plan);
 	newplan->magic = _SPI_PLAN_MAGIC;
 	newplan->plancxt = plancxt;
 	newplan->parse_mode = plan->parse_mode;
@@ -3170,7 +3169,7 @@ _SPI_make_plan_non_temp(SPIPlanPtr plan)
 	newplan->nargs = plan->nargs;
 	if (plan->nargs > 0)
 	{
-		newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
+		newplan->argtypes = palloc_array(Oid, plan->nargs);
 		memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
 	}
 	else
@@ -3227,7 +3226,7 @@ _SPI_save_plan(SPIPlanPtr plan)
 	oldcxt = MemoryContextSwitchTo(plancxt);
 
 	/* Copy the SPI plan into its own context */
-	newplan = (SPIPlanPtr) palloc0(sizeof(_SPI_plan));
+	newplan = palloc0_object(_SPI_plan);
 	newplan->magic = _SPI_PLAN_MAGIC;
 	newplan->plancxt = plancxt;
 	newplan->parse_mode = plan->parse_mode;
@@ -3235,7 +3234,7 @@ _SPI_save_plan(SPIPlanPtr plan)
 	newplan->nargs = plan->nargs;
 	if (plan->nargs > 0)
 	{
-		newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
+		newplan->argtypes = palloc_array(Oid, plan->nargs);
 		memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
 	}
 	else
@@ -3369,7 +3368,7 @@ SPI_register_trigger_data(TriggerData *tdata)
 	if (tdata->tg_newtable)
 	{
 		EphemeralNamedRelation enr =
-			palloc(sizeof(EphemeralNamedRelationData));
+			palloc_object(EphemeralNamedRelationData);
 		int			rc;
 
 		enr->md.name = tdata->tg_trigger->tgnewtable;
@@ -3386,7 +3385,7 @@ SPI_register_trigger_data(TriggerData *tdata)
 	if (tdata->tg_oldtable)
 	{
 		EphemeralNamedRelation enr =
-			palloc(sizeof(EphemeralNamedRelationData));
+			palloc_object(EphemeralNamedRelationData);
 		int			rc;
 
 		enr->md.name = tdata->tg_trigger->tgoldtable;
diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c
index 6c5e1f1262d..d9bf59f672d 100644
--- a/src/backend/executor/tqueue.c
+++ b/src/backend/executor/tqueue.c
@@ -120,7 +120,7 @@ CreateTupleQueueDestReceiver(shm_mq_handle *handle)
 {
 	TQueueDestReceiver *self;
 
-	self = (TQueueDestReceiver *) palloc0(sizeof(TQueueDestReceiver));
+	self = palloc0_object(TQueueDestReceiver);
 
 	self->pub.receiveSlot = tqueueReceiveSlot;
 	self->pub.rStartup = tqueueStartupReceiver;
@@ -138,7 +138,7 @@ CreateTupleQueueDestReceiver(shm_mq_handle *handle)
 TupleQueueReader *
 CreateTupleQueueReader(shm_mq_handle *handle)
 {
-	TupleQueueReader *reader = palloc0(sizeof(TupleQueueReader));
+	TupleQueueReader *reader = palloc0_object(TupleQueueReader);
 
 	reader->queue = handle;
 
diff --git a/src/backend/executor/tstoreReceiver.c b/src/backend/executor/tstoreReceiver.c
index 02a3ad3aa68..2012618e230 100644
--- a/src/backend/executor/tstoreReceiver.c
+++ b/src/backend/executor/tstoreReceiver.c
@@ -238,7 +238,7 @@ tstoreDestroyReceiver(DestReceiver *self)
 DestReceiver *
 CreateTuplestoreDestReceiver(void)
 {
-	TStoreState *self = (TStoreState *) palloc0(sizeof(TStoreState));
+	TStoreState *self = palloc0_object(TStoreState);
 
 	self->pub.receiveSlot = tstoreReceiveSlot_notoast;	/* might change */
 	self->pub.rStartup = tstoreStartupReceiver;
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index a57e59f27ea..fa3f4c75247 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -66,7 +66,7 @@ GetForeignDataWrapperExtended(Oid fdwid, bits16 flags)
 
 	fdwform = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp);
 
-	fdw = (ForeignDataWrapper *) palloc(sizeof(ForeignDataWrapper));
+	fdw = palloc_object(ForeignDataWrapper);
 	fdw->fdwid = fdwid;
 	fdw->owner = fdwform->fdwowner;
 	fdw->fdwname = pstrdup(NameStr(fdwform->fdwname));
@@ -140,7 +140,7 @@ GetForeignServerExtended(Oid serverid, bits16 flags)
 
 	serverform = (Form_pg_foreign_server) GETSTRUCT(tp);
 
-	server = (ForeignServer *) palloc(sizeof(ForeignServer));
+	server = palloc_object(ForeignServer);
 	server->serverid = serverid;
 	server->servername = pstrdup(NameStr(serverform->srvname));
 	server->owner = serverform->srvowner;
@@ -227,7 +227,7 @@ GetUserMapping(Oid userid, Oid serverid)
 						MappingUserName(userid), server->servername)));
 	}
 
-	um = (UserMapping *) palloc(sizeof(UserMapping));
+	um = palloc_object(UserMapping);
 	um->umid = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
 	um->userid = userid;
 	um->serverid = serverid;
@@ -265,7 +265,7 @@ GetForeignTable(Oid relid)
 		elog(ERROR, "cache lookup failed for foreign table %u", relid);
 	tableform = (Form_pg_foreign_table) GETSTRUCT(tp);
 
-	ft = (ForeignTable *) palloc(sizeof(ForeignTable));
+	ft = palloc_object(ForeignTable);
 	ft->relid = relid;
 	ft->serverid = tableform->ftserver;
 
@@ -463,7 +463,7 @@ GetFdwRoutineForRelation(Relation relation, bool makecopy)
 	/* We have valid cached data --- does the caller want a copy? */
 	if (makecopy)
 	{
-		fdwroutine = (FdwRoutine *) palloc(sizeof(FdwRoutine));
+		fdwroutine = palloc_object(FdwRoutine);
 		memcpy(fdwroutine, relation->rd_fdwroutine, sizeof(FdwRoutine));
 		return fdwroutine;
 	}
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index e978b996bae..15c3475ede2 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -500,7 +500,7 @@ llvm_copy_attributes_at_index(LLVMValueRef v_from, LLVMValueRef v_to, uint32 ind
 	if (num_attributes == 0)
 		return;
 
-	attrs = palloc(sizeof(LLVMAttributeRef) * num_attributes);
+	attrs = palloc_array(LLVMAttributeRef, num_attributes);
 	LLVMGetAttributesAtIndex(v_from, index, attrs);
 
 	for (int attno = 0; attno < num_attributes; attno++)
@@ -1123,9 +1123,9 @@ llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx,
 					 LLVMOrcCLookupSet LookupSet, size_t LookupSetSize)
 {
 #if LLVM_VERSION_MAJOR > 14
-	LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMOrcCSymbolMapPair) * LookupSetSize);
+	LLVMOrcCSymbolMapPairs symbols = palloc0_array(LLVMOrcCSymbolMapPair, LookupSetSize);
 #else
-	LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMJITCSymbolMapPair) * LookupSetSize);
+	LLVMOrcCSymbolMapPairs symbols = palloc0_array(LLVMJITCSymbolMapPair, LookupSetSize);
 #endif
 	LLVMErrorRef error;
 	LLVMOrcMaterializationUnitRef mu;
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index f500cbda893..89167d15c3f 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -156,12 +156,12 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 	b = LLVMCreateBuilderInContext(lc);
 
-	attcheckattnoblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
-	attstartblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
-	attisnullblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
-	attcheckalignblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
-	attalignblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
-	attstoreblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
+	attcheckattnoblocks = palloc_array(LLVMBasicBlockRef, natts);
+	attstartblocks = palloc_array(LLVMBasicBlockRef, natts);
+	attisnullblocks = palloc_array(LLVMBasicBlockRef, natts);
+	attcheckalignblocks = palloc_array(LLVMBasicBlockRef, natts);
+	attalignblocks = palloc_array(LLVMBasicBlockRef, natts);
+	attstoreblocks = palloc_array(LLVMBasicBlockRef, natts);
 
 	known_alignment = 0;
 
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index ac88881e995..c058583bcb6 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -297,7 +297,7 @@ llvm_compile_expr(ExprState *state)
 								   "v.econtext.aggnulls");
 
 	/* allocate blocks for each op upfront, so we can do jumps easily */
-	opblocks = palloc(sizeof(LLVMBasicBlockRef) * state->steps_len);
+	opblocks = palloc_array(LLVMBasicBlockRef, state->steps_len);
 	for (int opno = 0; opno < state->steps_len; opno++)
 		opblocks[opno] = l_bb_append_v(eval_fn, "b.op.%d.start", opno);
 
@@ -699,7 +699,7 @@ llvm_compile_expr(ExprState *state)
 
 						/* create blocks for checking args, one for each */
 						b_checkargnulls =
-							palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
+							palloc_array(LLVMBasicBlockRef *, op->d.func.nargs);
 						for (int argno = 0; argno < op->d.func.nargs; argno++)
 							b_checkargnulls[argno] =
 								l_bb_before_v(b_nonull, "b.%d.isnull.%d", opno,
@@ -2505,7 +2505,7 @@ llvm_compile_expr(ExprState *state)
 					v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
 
 					/* create blocks for checking args */
-					b_checknulls = palloc(sizeof(LLVMBasicBlockRef) * nargs);
+					b_checknulls = palloc_array(LLVMBasicBlockRef, nargs);
 					for (int argno = 0; argno < nargs; argno++)
 					{
 						b_checknulls[argno] =
@@ -2956,7 +2956,7 @@ llvm_compile_expr(ExprState *state)
 	 */
 	{
 
-		CompiledExprState *cstate = palloc0(sizeof(CompiledExprState));
+		CompiledExprState *cstate = palloc0_object(CompiledExprState);
 
 		cstate->context = context;
 		cstate->funcname = funcname;
@@ -3068,7 +3068,7 @@ build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
 		elog(ERROR, "parameter mismatch: %s expects %d passed %d",
 			 funcname, LLVMCountParams(v_fn), nargs + 2);
 
-	params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
+	params = palloc_array(LLVMValueRef, (2 + nargs));
 
 	params[argno++] = v_state;
 	params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
diff --git a/src/backend/lib/bipartite_match.c b/src/backend/lib/bipartite_match.c
index 5af789652c7..ed54f190494 100644
--- a/src/backend/lib/bipartite_match.c
+++ b/src/backend/lib/bipartite_match.c
@@ -38,7 +38,7 @@ static bool hk_depth_search(BipartiteMatchState *state, int u);
 BipartiteMatchState *
 BipartiteMatch(int u_size, int v_size, short **adjacency)
 {
-	BipartiteMatchState *state = palloc(sizeof(BipartiteMatchState));
+	BipartiteMatchState *state = palloc_object(BipartiteMatchState);
 
 	if (u_size < 0 || u_size >= SHRT_MAX ||
 		v_size < 0 || v_size >= SHRT_MAX)
diff --git a/src/backend/lib/dshash.c b/src/backend/lib/dshash.c
index e1ba367cf17..82f6aa966de 100644
--- a/src/backend/lib/dshash.c
+++ b/src/backend/lib/dshash.c
@@ -211,7 +211,7 @@ dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
 	dsa_pointer control;
 
 	/* Allocate the backend-local object representing the hash table. */
-	hash_table = palloc(sizeof(dshash_table));
+	hash_table = palloc_object(dshash_table);
 
 	/* Allocate the control object in shared memory. */
 	control = dsa_allocate(area, sizeof(dshash_table_control));
@@ -276,7 +276,7 @@ dshash_attach(dsa_area *area, const dshash_parameters *params,
 	dsa_pointer control;
 
 	/* Allocate the backend-local object representing the hash table. */
-	hash_table = palloc(sizeof(dshash_table));
+	hash_table = palloc_object(dshash_table);
 
 	/* Find the control object in shared memory. */
 	control = handle;
diff --git a/src/backend/lib/integerset.c b/src/backend/lib/integerset.c
index f4153b0e15a..aca1df2ad5a 100644
--- a/src/backend/lib/integerset.c
+++ b/src/backend/lib/integerset.c
@@ -284,7 +284,7 @@ intset_create(void)
 {
 	IntegerSet *intset;
 
-	intset = (IntegerSet *) palloc(sizeof(IntegerSet));
+	intset = palloc_object(IntegerSet);
 	intset->context = CurrentMemoryContext;
 	intset->mem_used = GetMemoryChunkSpace(intset);
 
diff --git a/src/backend/lib/pairingheap.c b/src/backend/lib/pairingheap.c
index fa8431f7946..3497dc7902a 100644
--- a/src/backend/lib/pairingheap.c
+++ b/src/backend/lib/pairingheap.c
@@ -43,7 +43,7 @@ pairingheap_allocate(pairingheap_comparator compare, void *arg)
 {
 	pairingheap *heap;
 
-	heap = (pairingheap *) palloc(sizeof(pairingheap));
+	heap = palloc_object(pairingheap);
 	pairingheap_initialize(heap, compare, arg);
 
 	return heap;
diff --git a/src/backend/lib/rbtree.c b/src/backend/lib/rbtree.c
index 1f0553f914d..8fe6bfc539a 100644
--- a/src/backend/lib/rbtree.c
+++ b/src/backend/lib/rbtree.c
@@ -106,7 +106,7 @@ rbt_create(Size node_size,
 		   rbt_freefunc freefunc,
 		   void *arg)
 {
-	RBTree	   *tree = (RBTree *) palloc(sizeof(RBTree));
+	RBTree	   *tree = palloc_object(RBTree);
 
 	Assert(node_size > sizeof(RBTNode));
 
diff --git a/src/backend/libpq/auth-oauth.c b/src/backend/libpq/auth-oauth.c
index 27f7af7be00..32a370ede11 100644
--- a/src/backend/libpq/auth-oauth.c
+++ b/src/backend/libpq/auth-oauth.c
@@ -108,7 +108,7 @@ oauth_init(Port *port, const char *selected_mech, const char *shadow_pass)
 				errcode(ERRCODE_PROTOCOL_VIOLATION),
 				errmsg("client selected an invalid SASL authentication mechanism"));
 
-	ctx = palloc0(sizeof(*ctx));
+	ctx = palloc0_object(struct oauth_ctx);
 
 	ctx->state = OAUTH_STATE_INIT;
 	ctx->port = port;
@@ -656,7 +656,7 @@ validate(Port *port, const char *auth)
 				errmsg("validation of OAuth token requested without a validator loaded"));
 
 	/* Call the validation function from the validator module */
-	ret = palloc0(sizeof(ValidatorModuleResult));
+	ret = palloc0_object(ValidatorModuleResult);
 	if (!ValidatorCallbacks->validate_cb(validator_module_state, token,
 										 port->user_name, ret))
 	{
@@ -785,14 +785,14 @@ load_validator_library(const char *libname)
 					   "OAuth validator", libname, "validate_cb"));
 
 	/* Allocate memory for validator library private state data */
-	validator_module_state = (ValidatorModuleState *) palloc0(sizeof(ValidatorModuleState));
+	validator_module_state = palloc0_object(ValidatorModuleState);
 	validator_module_state->sversion = PG_VERSION_NUM;
 
 	if (ValidatorCallbacks->startup_cb != NULL)
 		ValidatorCallbacks->startup_cb(validator_module_state);
 
 	/* Shut down the library before cleaning up its state. */
-	mcb = palloc0(sizeof(*mcb));
+	mcb = palloc0_object(MemoryContextCallback);
 	mcb->func = shutdown_validator_library;
 
 	MemoryContextRegisterResetCallback(CurrentMemoryContext, mcb);
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index db778405724..5f094efc46d 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -242,7 +242,7 @@ scram_init(Port *port, const char *selected_mech, const char *shadow_pass)
 	scram_state *state;
 	bool		got_secret;
 
-	state = (scram_state *) palloc0(sizeof(scram_state));
+	state = palloc0_object(scram_state);
 	state->port = port;
 	state->state = SCRAM_AUTH_INIT;
 
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 97a3586000b..61e1e6bafb4 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -312,7 +312,7 @@ regcomp_auth_token(AuthToken *token, char *filename, int line_num,
 	if (token->string[0] != '/')
 		return 0;				/* nothing to compile */
 
-	token->regex = (regex_t *) palloc0(sizeof(regex_t));
+	token->regex = palloc0_object(regex_t);
 	wstr = palloc((strlen(token->string + 1) + 1) * sizeof(pg_wchar));
 	wlen = pg_mb2wchar_with_len(token->string + 1,
 								wstr, strlen(token->string + 1));
@@ -894,7 +894,7 @@ process_line:
 		 * to this list.
 		 */
 		oldcxt = MemoryContextSwitchTo(tokenize_context);
-		tok_line = (TokenizedAuthLine *) palloc0(sizeof(TokenizedAuthLine));
+		tok_line = palloc0_object(TokenizedAuthLine);
 		tok_line->fields = current_line;
 		tok_line->file_name = pstrdup(filename);
 		tok_line->line_num = line_number;
@@ -1342,7 +1342,7 @@ parse_hba_line(TokenizedAuthLine *tok_line, int elevel)
 	AuthToken  *token;
 	HbaLine    *parsedline;
 
-	parsedline = palloc0(sizeof(HbaLine));
+	parsedline = palloc0_object(HbaLine);
 	parsedline->sourcefile = pstrdup(file_name);
 	parsedline->linenumber = line_num;
 	parsedline->rawline = pstrdup(tok_line->raw_line);
@@ -2625,7 +2625,7 @@ check_hba(Port *port)
 	}
 
 	/* If no matching entry was found, then implicitly reject. */
-	hba = palloc0(sizeof(HbaLine));
+	hba = palloc0_object(HbaLine);
 	hba->auth_method = uaImplicitReject;
 	port->hba = hba;
 }
@@ -2761,7 +2761,7 @@ parse_ident_line(TokenizedAuthLine *tok_line, int elevel)
 	Assert(tok_line->fields != NIL);
 	field = list_head(tok_line->fields);
 
-	parsedline = palloc0(sizeof(IdentLine));
+	parsedline = palloc0_object(IdentLine);
 	parsedline->linenumber = line_num;
 
 	/* Get the map token (must exist) */
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 25f739a6a17..899d8bef9dc 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -178,7 +178,7 @@ pq_init(ClientSocket *client_sock)
 	int			latch_pos PG_USED_FOR_ASSERTS_ONLY;
 
 	/* allocate the Port struct and copy the ClientSocket contents to it */
-	port = palloc0(sizeof(Port));
+	port = palloc0_object(Port);
 	port->sock = client_sock->sock;
 	memcpy(&port->raddr.addr, &client_sock->raddr.addr, client_sock->raddr.salen);
 	port->raddr.salen = client_sock->raddr.salen;
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index d228318dc72..024a2b2fd84 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -2953,7 +2953,7 @@ expression_tree_mutator_impl(Node *node,
 	 */
 
 #define FLATCOPY(newnode, node, nodetype)  \
-	( (newnode) = (nodetype *) palloc(sizeof(nodetype)), \
+	( (newnode) = palloc_object(nodetype), \
 	  memcpy((newnode), (node), sizeof(nodetype)) )
 
 #define MUTATE(newfield, oldfield, fieldtype)  \
diff --git a/src/backend/nodes/queryjumblefuncs.c b/src/backend/nodes/queryjumblefuncs.c
index 31f97151977..ffc230af427 100644
--- a/src/backend/nodes/queryjumblefuncs.c
+++ b/src/backend/nodes/queryjumblefuncs.c
@@ -181,7 +181,7 @@ InitJumble(void)
 {
 	JumbleState *jstate;
 
-	jstate = (JumbleState *) palloc(sizeof(JumbleState));
+	jstate = palloc_object(JumbleState);
 
 	/* Set up workspace for query jumbling */
 	jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE);
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 1f83d0d55f5..a2fa96317db 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -683,7 +683,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
+	iterator = palloc_object(TBMPrivateIterator);
 	iterator->tbm = tbm;
 
 	/*
@@ -1468,7 +1468,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
+	iterator = palloc0_object(TBMSharedIterator);
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/backend/optimizer/geqo/geqo_erx.c b/src/backend/optimizer/geqo/geqo_erx.c
index af289f7eeb7..f11a59e4a28 100644
--- a/src/backend/optimizer/geqo/geqo_erx.c
+++ b/src/backend/optimizer/geqo/geqo_erx.c
@@ -62,7 +62,7 @@ alloc_edge_table(PlannerInfo *root, int num_gene)
 	 * directly; 0 will not be used
 	 */
 
-	edge_table = (Edge *) palloc((num_gene + 1) * sizeof(Edge));
+	edge_table = palloc_array(Edge, num_gene + 1);
 
 	return edge_table;
 }
diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c
index 8005754c8c6..c65a31d0679 100644
--- a/src/backend/optimizer/geqo/geqo_eval.c
+++ b/src/backend/optimizer/geqo/geqo_eval.c
@@ -191,7 +191,7 @@ gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
 										  cur_rel_index - 1);
 
 		/* Make it into a single-rel clump */
-		cur_clump = (Clump *) palloc(sizeof(Clump));
+		cur_clump = palloc_object(Clump);
 		cur_clump->joinrel = cur_rel;
 		cur_clump->size = 1;
 
diff --git a/src/backend/optimizer/geqo/geqo_pmx.c b/src/backend/optimizer/geqo/geqo_pmx.c
index 01d55711925..af1cb868391 100644
--- a/src/backend/optimizer/geqo/geqo_pmx.c
+++ b/src/backend/optimizer/geqo/geqo_pmx.c
@@ -48,10 +48,10 @@
 void
 pmx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene)
 {
-	int		   *failed = (int *) palloc((num_gene + 1) * sizeof(int));
-	int		   *from = (int *) palloc((num_gene + 1) * sizeof(int));
-	int		   *indx = (int *) palloc((num_gene + 1) * sizeof(int));
-	int		   *check_list = (int *) palloc((num_gene + 1) * sizeof(int));
+	int		   *failed = palloc_array(int, num_gene + 1);
+	int		   *from = palloc_array(int, num_gene + 1);
+	int		   *indx = palloc_array(int, num_gene + 1);
+	int		   *check_list = palloc_array(int, num_gene + 1);
 
 	int			left,
 				right,
diff --git a/src/backend/optimizer/geqo/geqo_pool.c b/src/backend/optimizer/geqo/geqo_pool.c
index b6de0d93f28..ecb17514b62 100644
--- a/src/backend/optimizer/geqo/geqo_pool.c
+++ b/src/backend/optimizer/geqo/geqo_pool.c
@@ -46,17 +46,17 @@ alloc_pool(PlannerInfo *root, int pool_size, int string_length)
 	int			i;
 
 	/* pool */
-	new_pool = (Pool *) palloc(sizeof(Pool));
+	new_pool = palloc_object(Pool);
 	new_pool->size = (int) pool_size;
 	new_pool->string_length = (int) string_length;
 
 	/* all chromosome */
-	new_pool->data = (Chromosome *) palloc(pool_size * sizeof(Chromosome));
+	new_pool->data = palloc_array(Chromosome, pool_size);
 
 	/* all gene */
 	chromo = (Chromosome *) new_pool->data; /* vector of all chromos */
 	for (i = 0; i < pool_size; i++)
-		chromo[i].string = palloc((string_length + 1) * sizeof(Gene));
+		chromo[i].string = palloc_array(Gene, string_length + 1);
 
 	return new_pool;
 }
@@ -163,8 +163,8 @@ alloc_chromo(PlannerInfo *root, int string_length)
 {
 	Chromosome *chromo;
 
-	chromo = (Chromosome *) palloc(sizeof(Chromosome));
-	chromo->string = (Gene *) palloc((string_length + 1) * sizeof(Gene));
+	chromo = palloc_object(Chromosome);
+	chromo->string = palloc_array(Gene, string_length + 1);
 
 	return chromo;
 }
diff --git a/src/backend/optimizer/geqo/geqo_recombination.c b/src/backend/optimizer/geqo/geqo_recombination.c
index a5d3e47ad11..41d35c179e1 100644
--- a/src/backend/optimizer/geqo/geqo_recombination.c
+++ b/src/backend/optimizer/geqo/geqo_recombination.c
@@ -74,7 +74,7 @@ alloc_city_table(PlannerInfo *root, int num_gene)
 	 * palloc one extra location so that nodes numbered 1..n can be indexed
 	 * directly; 0 will not be used
 	 */
-	city_table = (City *) palloc((num_gene + 1) * sizeof(City));
+	city_table = palloc_array(City, num_gene + 1);
 
 	return city_table;
 }
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index d0f516b7645..eb9b7f3eabd 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -495,7 +495,7 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
 	}
 
 	/* No matching var found, so make a new clause-pair data structure */
-	rqelem = (RangeQueryClause *) palloc(sizeof(RangeQueryClause));
+	rqelem = palloc_object(RangeQueryClause);
 	rqelem->var = var;
 	if (is_lobound)
 	{
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 8335cf5b5c5..6f228c60bb4 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -2163,7 +2163,7 @@ append_nonpartial_cost(List *subpaths, int numpaths, int parallel_workers)
 	 * whichever is less.
 	 */
 	arrlen = Min(parallel_workers, numpaths);
-	costarr = (Cost *) palloc(sizeof(Cost) * arrlen);
+	costarr = palloc_array(Cost, arrlen);
 
 	/* The first few paths will each be claimed by a different worker. */
 	path_index = 0;
@@ -4121,7 +4121,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey)
 	/* Cache the result in suitably long-lived workspace */
 	oldcontext = MemoryContextSwitchTo(root->planner_cxt);
 
-	cache = (MergeScanSelCache *) palloc(sizeof(MergeScanSelCache));
+	cache = palloc_object(MergeScanSelCache);
 	cache->opfamily = pathkey->pk_opfamily;
 	cache->collation = pathkey->pk_eclass->ec_collation;
 	cache->cmptype = pathkey->pk_cmptype;
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index c62e3f87724..0cb0ce35128 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -1291,7 +1291,7 @@ group_similar_or_args(PlannerInfo *root, RelOptInfo *rel, RestrictInfo *rinfo)
 	 * which will be used to sort these arguments at the next step.
 	 */
 	i = -1;
-	matches = (OrArgIndexMatch *) palloc(sizeof(OrArgIndexMatch) * n);
+	matches = palloc_array(OrArgIndexMatch, n);
 	foreach(lc, orargs)
 	{
 		Node	   *arg = lfirst(lc);
@@ -1853,8 +1853,7 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
 	 * same set of clauses; keep only the cheapest-to-scan of any such groups.
 	 * The surviving paths are put into an array for qsort'ing.
 	 */
-	pathinfoarray = (PathClauseUsage **)
-		palloc(npaths * sizeof(PathClauseUsage *));
+	pathinfoarray = palloc_array(PathClauseUsage *, npaths);
 	clauselist = NIL;
 	npaths = 0;
 	foreach(l, paths)
@@ -2090,7 +2089,7 @@ classify_index_clause_usage(Path *path, List **clauselist)
 	Bitmapset  *clauseids;
 	ListCell   *lc;
 
-	result = (PathClauseUsage *) palloc(sizeof(PathClauseUsage));
+	result = palloc_object(PathClauseUsage);
 	result->path = path;
 
 	/* Recursively find the quals and preds used by the path */
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 5d1fc3899da..8827b9a5245 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -1990,8 +1990,7 @@ compute_partition_bounds(PlannerInfo *root, RelOptInfo *rel1,
 		Assert(nparts > 0);
 		joinrel->boundinfo = boundinfo;
 		joinrel->nparts = nparts;
-		joinrel->part_rels =
-			(RelOptInfo **) palloc0(sizeof(RelOptInfo *) * nparts);
+		joinrel->part_rels = palloc0_array(RelOptInfo *, nparts);
 	}
 	else
 	{
diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index e592e1ac3d1..a6af61f929c 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -2358,8 +2358,7 @@ remove_self_joins_recurse(PlannerInfo *root, List *joinlist, Relids toRemove)
 	 * In order to find relations with the same oid we first build an array of
 	 * candidates and then sort it by oid.
 	 */
-	candidates = (SelfJoinCandidate *) palloc(sizeof(SelfJoinCandidate) *
-											  numRels);
+	candidates = palloc_array(SelfJoinCandidate, numRels);
 	i = -1;
 	j = 0;
 	while ((i = bms_next_member(relids, i)) >= 0)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 8af091ba647..bc417f93840 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -2207,7 +2207,7 @@ remap_groupColIdx(PlannerInfo *root, List *groupClause)
 
 	Assert(grouping_map);
 
-	new_grpColIdx = palloc0(sizeof(AttrNumber) * list_length(groupClause));
+	new_grpColIdx = palloc0_array(AttrNumber, list_length(groupClause));
 
 	i = 0;
 	foreach(lc, groupClause)
@@ -2496,9 +2496,9 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
 	 * Convert SortGroupClause lists into arrays of attr indexes and equality
 	 * operators, as wanted by executor.
 	 */
-	partColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numPart);
-	partOperators = (Oid *) palloc(sizeof(Oid) * numPart);
-	partCollations = (Oid *) palloc(sizeof(Oid) * numPart);
+	partColIdx = palloc_array(AttrNumber, numPart);
+	partOperators = palloc_array(Oid, numPart);
+	partCollations = palloc_array(Oid, numPart);
 
 	partNumCols = 0;
 	foreach(lc, wc->partitionClause)
@@ -2513,9 +2513,9 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
 		partNumCols++;
 	}
 
-	ordColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numOrder);
-	ordOperators = (Oid *) palloc(sizeof(Oid) * numOrder);
-	ordCollations = (Oid *) palloc(sizeof(Oid) * numOrder);
+	ordColIdx = palloc_array(AttrNumber, numOrder);
+	ordOperators = palloc_array(Oid, numOrder);
+	ordCollations = palloc_array(Oid, numOrder);
 
 	ordNumCols = 0;
 	foreach(lc, wc->orderClause)
@@ -5862,9 +5862,9 @@ make_recursive_union(List *tlist,
 		Oid		   *dupCollations;
 		ListCell   *slitem;
 
-		dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
-		dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
-		dupCollations = (Oid *) palloc(sizeof(Oid) * numCols);
+		dupColIdx = palloc_array(AttrNumber, numCols);
+		dupOperators = palloc_array(Oid, numCols);
+		dupCollations = palloc_array(Oid, numCols);
 
 		foreach(slitem, distinctList)
 		{
@@ -6694,9 +6694,9 @@ make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols,
 	 * prepare_sort_from_pathkeys ... maybe unify sometime?
 	 */
 	Assert(numCols >= 0 && numCols <= list_length(pathkeys));
-	uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
-	uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
-	uniqCollations = (Oid *) palloc(sizeof(Oid) * numCols);
+	uniqColIdx = palloc_array(AttrNumber, numCols);
+	uniqOperators = palloc_array(Oid, numCols);
+	uniqCollations = palloc_array(Oid, numCols);
 
 	foreach(lc, pathkeys)
 	{
@@ -6831,10 +6831,10 @@ make_setop(SetOpCmd cmd, SetOpStrategy strategy,
 	 * convert SortGroupClause list into arrays of attr indexes and comparison
 	 * operators, as wanted by executor
 	 */
-	cmpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
-	cmpOperators = (Oid *) palloc(sizeof(Oid) * numCols);
-	cmpCollations = (Oid *) palloc(sizeof(Oid) * numCols);
-	cmpNullsFirst = (bool *) palloc(sizeof(bool) * numCols);
+	cmpColIdx = palloc_array(AttrNumber, numCols);
+	cmpOperators = palloc_array(Oid, numCols);
+	cmpCollations = palloc_array(Oid, numCols);
+	cmpNullsFirst = palloc_array(bool, numCols);
 
 	foreach(slitem, groupList)
 	{
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 65d473d95b6..1d859ab1a1c 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -438,8 +438,7 @@ remove_useless_groupby_columns(PlannerInfo *root)
 	 * Fill groupbyattnos[k] with a bitmapset of the column attnos of RTE k
 	 * that are GROUP BY items.
 	 */
-	groupbyattnos = (Bitmapset **) palloc0(sizeof(Bitmapset *) *
-										   (list_length(parse->rtable) + 1));
+	groupbyattnos = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
 	foreach(lc, root->processed_groupClause)
 	{
 		SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
@@ -597,8 +596,7 @@ remove_useless_groupby_columns(PlannerInfo *root)
 			 * allocate the surplusvars[] array until we find something.
 			 */
 			if (surplusvars == NULL)
-				surplusvars = (Bitmapset **) palloc0(sizeof(Bitmapset *) *
-													 (list_length(parse->rtable) + 1));
+				surplusvars = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
 
 			/* Remember the attnos of the removable columns */
 			surplusvars[relid] = bms_difference(relattnos, best_keycolumns);
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index a2ac58d246e..1a35c269e04 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -336,7 +336,7 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo,
 	 * than before.  (This means that when we are done, there will be no Vars
 	 * of level 1, which is why the subquery can become an initplan.)
 	 */
-	subroot = (PlannerInfo *) palloc(sizeof(PlannerInfo));
+	subroot = palloc_object(PlannerInfo);
 	memcpy(subroot, root, sizeof(PlannerInfo));
 	subroot->query_level++;
 	subroot->parent_root = root;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index c4fd646b999..95e4c42eea3 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -2213,7 +2213,7 @@ preprocess_grouping_sets(PlannerInfo *root)
 	List	   *sets;
 	int			maxref = 0;
 	ListCell   *lc_set;
-	grouping_sets_data *gd = palloc0(sizeof(grouping_sets_data));
+	grouping_sets_data *gd = palloc0_object(grouping_sets_data);
 
 	/*
 	 * We don't currently make any attempt to optimize the groupClause when
@@ -5977,8 +5977,7 @@ select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
 	List	   *result = NIL;
 	ListCell   *lc;
 	int			nActive = 0;
-	WindowClauseSortData *actives = palloc(sizeof(WindowClauseSortData)
-										   * list_length(windowClause));
+	WindowClauseSortData *actives = palloc_array(WindowClauseSortData, list_length(windowClause));
 
 	/* First, construct an array of the active windows */
 	foreach(lc, windowClause)
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index ccdc9bc264a..cd7ea1e6b58 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -312,7 +312,7 @@ set_plan_references(PlannerInfo *root, Plan *plan)
 			   root->simple_rte_array[rc->rti] != NULL);
 
 		/* flat copy is enough since all fields are scalars */
-		newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
+		newrc = palloc_object(PlanRowMark);
 		memcpy(newrc, rc, sizeof(PlanRowMark));
 
 		/* adjust indexes ... but *not* the rowmarkId */
@@ -545,7 +545,7 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos,
 	RangeTblEntry *newrte;
 
 	/* flat copy to duplicate all the scalar fields */
-	newrte = (RangeTblEntry *) palloc(sizeof(RangeTblEntry));
+	newrte = palloc_object(RangeTblEntry);
 	memcpy(newrte, rte, sizeof(RangeTblEntry));
 
 	/* zap unneeded sub-structure */
@@ -2028,7 +2028,7 @@ offset_relid_set(Relids relids, int rtoffset)
 static inline Var *
 copyVar(Var *var)
 {
-	Var		   *newvar = (Var *) palloc(sizeof(Var));
+	Var		   *newvar = palloc_object(Var);
 
 	*newvar = *var;
 	return newvar;
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 7581695647d..c3b726e93e7 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -741,7 +741,7 @@ pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
 		 * Make a modifiable copy of join node, but don't bother copying its
 		 * subnodes (yet).
 		 */
-		j = (JoinExpr *) palloc(sizeof(JoinExpr));
+		j = palloc_object(JoinExpr);
 		memcpy(j, jtnode, sizeof(JoinExpr));
 		jtlink = (Node *) j;
 
@@ -3240,8 +3240,7 @@ reduce_outer_joins_pass1(Node *jtnode)
 {
 	reduce_outer_joins_pass1_state *result;
 
-	result = (reduce_outer_joins_pass1_state *)
-		palloc(sizeof(reduce_outer_joins_pass1_state));
+	result = palloc_object(reduce_outer_joins_pass1_state);
 	result->relids = NULL;
 	result->contains_outer = false;
 	result->sub_states = NIL;
@@ -3593,7 +3592,7 @@ report_reduced_full_join(reduce_outer_joins_pass2_state *state2,
 {
 	reduce_outer_joins_partial_state *statep;
 
-	statep = palloc(sizeof(reduce_outer_joins_partial_state));
+	statep = palloc_object(reduce_outer_joins_partial_state);
 	statep->full_join_rti = rtindex;
 	statep->unreduced_side = relids;
 	state2->partial_reduced = lappend(state2->partial_reduced, statep);
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index f528f096a56..a01b02f3a7b 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -1629,7 +1629,7 @@ generate_append_tlist(List *colTypes, List *colCollations,
 	 * If the inputs all agree on type and typmod of a particular column, use
 	 * that typmod; else use -1.
 	 */
-	colTypmods = (int32 *) palloc(list_length(colTypes) * sizeof(int32));
+	colTypmods = palloc_array(int32, list_length(colTypes));
 
 	foreach(tlistl, input_tlists)
 	{
diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c
index 69b8b0c2ae0..271bb4e6828 100644
--- a/src/backend/optimizer/util/appendinfo.c
+++ b/src/backend/optimizer/util/appendinfo.c
@@ -808,8 +808,7 @@ find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
 	int			i;
 
 	/* Allocate an array that's certainly big enough */
-	appinfos = (AppendRelInfo **)
-		palloc(sizeof(AppendRelInfo *) * bms_num_members(relids));
+	appinfos = palloc_array(AppendRelInfo *, bms_num_members(relids));
 
 	i = -1;
 	while ((i = bms_next_member(relids, i)) >= 0)
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 202ba8ed4bb..43cfa197e6c 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -237,7 +237,7 @@ contain_window_function(Node *clause)
 WindowFuncLists *
 find_window_functions(Node *clause, Index maxWinRef)
 {
-	WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
+	WindowFuncLists *lists = palloc_object(WindowFuncLists);
 
 	lists->numWindowFuncs = 0;
 	lists->maxWinRef = maxWinRef;
@@ -5669,8 +5669,8 @@ make_SAOP_expr(Oid oper, Node *leftexpr, Oid coltype, Oid arraycollid,
 
 		get_typlenbyvalalign(coltype, &typlen, &typbyval, &typalign);
 
-		elems = (Datum *) palloc(sizeof(Datum) * list_length(exprs));
-		nulls = (bool *) palloc(sizeof(bool) * list_length(exprs));
+		elems = palloc_array(Datum, list_length(exprs));
+		nulls = palloc_array(bool, list_length(exprs));
 		foreach_node(Const, value, exprs)
 		{
 			elems[i] = value->constvalue;
diff --git a/src/backend/optimizer/util/extendplan.c b/src/backend/optimizer/util/extendplan.c
index 03d32277ba1..4e2f8d4dada 100644
--- a/src/backend/optimizer/util/extendplan.c
+++ b/src/backend/optimizer/util/extendplan.c
@@ -98,10 +98,7 @@ SetPlannerGlobalExtensionState(PlannerGlobal *glob, int extension_id,
 		int			i;
 
 		i = pg_nextpower2_32(extension_id + 1);
-		glob->extension_state = (void **)
-			repalloc0(glob->extension_state,
-					  glob->extension_state_allocated * sizeof(void *),
-					  i * sizeof(void *));
+		glob->extension_state = repalloc0_array(glob->extension_state, void *, glob->extension_state_allocated, i);
 		glob->extension_state_allocated = i;
 	}
 
@@ -134,10 +131,7 @@ SetPlannerInfoExtensionState(PlannerInfo *root, int extension_id,
 		int			i;
 
 		i = pg_nextpower2_32(extension_id + 1);
-		root->extension_state = (void **)
-			repalloc0(root->extension_state,
-					  root->extension_state_allocated * sizeof(void *),
-					  i * sizeof(void *));
+		root->extension_state = repalloc0_array(root->extension_state, void *, root->extension_state_allocated, i);
 		root->extension_state_allocated = i;
 	}
 
@@ -172,10 +166,7 @@ SetRelOptInfoExtensionState(RelOptInfo *rel, int extension_id,
 		int			i;
 
 		i = pg_nextpower2_32(extension_id + 1);
-		rel->extension_state = (void **)
-			repalloc0(rel->extension_state,
-					  rel->extension_state_allocated * sizeof(void *),
-					  i * sizeof(void *));
+		rel->extension_state = repalloc0_array(rel->extension_state, void *, rel->extension_state_allocated, i);
 		rel->extension_state_allocated = i;
 	}
 
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 7af9a2064e3..0c5a732d6b3 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -279,11 +279,11 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 			info->ncolumns = ncolumns = index->indnatts;
 			info->nkeycolumns = nkeycolumns = index->indnkeyatts;
 
-			info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
-			info->indexcollations = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
-			info->opfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
-			info->opcintype = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
-			info->canreturn = (bool *) palloc(sizeof(bool) * ncolumns);
+			info->indexkeys = palloc_array(int, ncolumns);
+			info->indexcollations = palloc_array(Oid, nkeycolumns);
+			info->opfamily = palloc_array(Oid, nkeycolumns);
+			info->opcintype = palloc_array(Oid, nkeycolumns);
+			info->canreturn = palloc_array(bool, ncolumns);
 
 			for (i = 0; i < ncolumns; i++)
 			{
@@ -336,8 +336,8 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 					Assert(amroutine->amcanorder);
 
 					info->sortopfamily = info->opfamily;
-					info->reverse_sort = (bool *) palloc(sizeof(bool) * nkeycolumns);
-					info->nulls_first = (bool *) palloc(sizeof(bool) * nkeycolumns);
+					info->reverse_sort = palloc_array(bool, nkeycolumns);
+					info->nulls_first = palloc_array(bool, nkeycolumns);
 
 					for (i = 0; i < nkeycolumns; i++)
 					{
@@ -356,13 +356,13 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 					 * order, this is a sufficient test.
 					 *
 					 * XXX This method is rather slow and complicated.  It'd
-					 * be better to have a way to explicitly declare the
-					 * corresponding btree opfamily for each opfamily of the
-					 * other index type.
+					* be better to have a way to explicitly declare the
+					* corresponding btree opfamily for each opfamily of the
+					* other index type.
 					 */
-					info->sortopfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
-					info->reverse_sort = (bool *) palloc(sizeof(bool) * nkeycolumns);
-					info->nulls_first = (bool *) palloc(sizeof(bool) * nkeycolumns);
+					info->sortopfamily = palloc_array(Oid, nkeycolumns);
+					info->reverse_sort = palloc_array(bool, nkeycolumns);
+					info->nulls_first = palloc_array(bool, nkeycolumns);
 
 					for (i = 0; i < nkeycolumns; i++)
 					{
@@ -2649,32 +2649,31 @@ find_partition_scheme(PlannerInfo *root, Relation relation)
 	 * array since the relcache entry may not survive after we have closed the
 	 * relation.
 	 */
-	part_scheme = (PartitionScheme) palloc0(sizeof(PartitionSchemeData));
+	part_scheme = palloc0_object(PartitionSchemeData);
 	part_scheme->strategy = partkey->strategy;
 	part_scheme->partnatts = partkey->partnatts;
 
-	part_scheme->partopfamily = (Oid *) palloc(sizeof(Oid) * partnatts);
+	part_scheme->partopfamily = palloc_array(Oid, partnatts);
 	memcpy(part_scheme->partopfamily, partkey->partopfamily,
 		   sizeof(Oid) * partnatts);
 
-	part_scheme->partopcintype = (Oid *) palloc(sizeof(Oid) * partnatts);
+	part_scheme->partopcintype = palloc_array(Oid, partnatts);
 	memcpy(part_scheme->partopcintype, partkey->partopcintype,
 		   sizeof(Oid) * partnatts);
 
-	part_scheme->partcollation = (Oid *) palloc(sizeof(Oid) * partnatts);
+	part_scheme->partcollation = palloc_array(Oid, partnatts);
 	memcpy(part_scheme->partcollation, partkey->partcollation,
 		   sizeof(Oid) * partnatts);
 
-	part_scheme->parttyplen = (int16 *) palloc(sizeof(int16) * partnatts);
+	part_scheme->parttyplen = palloc_array(int16, partnatts);
 	memcpy(part_scheme->parttyplen, partkey->parttyplen,
 		   sizeof(int16) * partnatts);
 
-	part_scheme->parttypbyval = (bool *) palloc(sizeof(bool) * partnatts);
+	part_scheme->parttypbyval = palloc_array(bool, partnatts);
 	memcpy(part_scheme->parttypbyval, partkey->parttypbyval,
 		   sizeof(bool) * partnatts);
 
-	part_scheme->partsupfunc = (FmgrInfo *)
-		palloc(sizeof(FmgrInfo) * partnatts);
+	part_scheme->partsupfunc = palloc_array(FmgrInfo, partnatts);
 	for (i = 0; i < partnatts; i++)
 		fmgr_info_copy(&part_scheme->partsupfunc[i], &partkey->partsupfunc[i],
 					   CurrentMemoryContext);
@@ -2708,7 +2707,7 @@ set_baserel_partition_key_exprs(Relation relation,
 	Assert(partkey != NULL);
 
 	partnatts = partkey->partnatts;
-	partexprs = (List **) palloc(sizeof(List *) * partnatts);
+	partexprs = palloc_array(List *, partnatts);
 	lc = list_head(partkey->partexprs);
 
 	for (cnt = 0; cnt < partnatts; cnt++)
@@ -2749,7 +2748,7 @@ set_baserel_partition_key_exprs(Relation relation,
 	 * expression lists to keep partition key expression handling code simple.
 	 * See build_joinrel_partition_info() and match_expr_to_partition_keys().
 	 */
-	rel->nullable_partexprs = (List **) palloc0(sizeof(List *) * partnatts);
+	rel->nullable_partexprs = palloc0_array(List *, partnatts);
 }
 
 /*
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index ac28573cd0a..0a14658ed7d 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -967,7 +967,7 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info)
 	char		elmalign;
 
 	/* Create working state struct */
-	state = (ArrayConstIterState *) palloc(sizeof(ArrayConstIterState));
+	state = palloc_object(ArrayConstIterState);
 	info->state = state;
 
 	/* Deconstruct the array literal */
@@ -1046,7 +1046,7 @@ arrayexpr_startup_fn(Node *clause, PredIterInfo info)
 	ArrayExpr  *arrayexpr;
 
 	/* Create working state struct */
-	state = (ArrayExprIterState *) palloc(sizeof(ArrayExprIterState));
+	state = palloc_object(ArrayExprIterState);
 	info->state = state;
 
 	/* Set up a dummy OpExpr to return as the per-item node */
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 1158bc194c3..2f423fc42b1 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -120,11 +120,11 @@ setup_simple_rel_arrays(PlannerInfo *root)
 	 * exist yet.  It'll be filled by later calls to build_simple_rel().
 	 */
 	root->simple_rel_array = (RelOptInfo **)
-		palloc0(size * sizeof(RelOptInfo *));
+		palloc0_array(RelOptInfo *, size);
 
 	/* simple_rte_array is an array equivalent of the rtable list */
 	root->simple_rte_array = (RangeTblEntry **)
-		palloc0(size * sizeof(RangeTblEntry *));
+		palloc0_array(RangeTblEntry *, size);
 	rti = 1;
 	foreach(lc, root->parse->rtable)
 	{
@@ -141,7 +141,7 @@ setup_simple_rel_arrays(PlannerInfo *root)
 	}
 
 	root->append_rel_array = (AppendRelInfo **)
-		palloc0(size * sizeof(AppendRelInfo *));
+		palloc0_array(AppendRelInfo *, size);
 
 	/*
 	 * append_rel_array is filled with any already-existing AppendRelInfos,
@@ -373,9 +373,9 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
 			rel->min_attr = 0;
 			rel->max_attr = list_length(rte->eref->colnames);
 			rel->attr_needed = (Relids *)
-				palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
+				palloc0_array(Relids, rel->max_attr - rel->min_attr + 1);
 			rel->attr_widths = (int32 *)
-				palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
+				palloc0_array(int32, rel->max_attr - rel->min_attr + 1);
 			break;
 		case RTE_RESULT:
 			/* RTE_RESULT has no columns, nor could it have whole-row Var */
@@ -2486,9 +2486,9 @@ set_joinrel_partition_key_exprs(RelOptInfo *joinrel,
 	PartitionScheme part_scheme = joinrel->part_scheme;
 	int			partnatts = part_scheme->partnatts;
 
-	joinrel->partexprs = (List **) palloc0(sizeof(List *) * partnatts);
+	joinrel->partexprs = (List **) palloc0_array(List *, partnatts);
 	joinrel->nullable_partexprs =
-		(List **) palloc0(sizeof(List *) * partnatts);
+		(List **) palloc0_array(List *, partnatts);
 
 	/*
 	 * The joinrel's partition expressions are the same as those of the input
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index d2b4ecc5e51..af7b19be5c7 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -467,7 +467,7 @@ extract_grouping_ops(List *groupClause)
 	Oid		   *groupOperators;
 	ListCell   *glitem;
 
-	groupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
+	groupOperators = palloc_array(Oid, numCols);
 
 	foreach(glitem, groupClause)
 	{
@@ -493,7 +493,7 @@ extract_grouping_collations(List *groupClause, List *tlist)
 	Oid		   *grpCollations;
 	ListCell   *glitem;
 
-	grpCollations = (Oid *) palloc(sizeof(Oid) * numCols);
+	grpCollations = palloc_array(Oid, numCols);
 
 	foreach(glitem, groupClause)
 	{
@@ -518,7 +518,7 @@ extract_grouping_cols(List *groupClause, List *tlist)
 	int			colno = 0;
 	ListCell   *glitem;
 
-	grpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
+	grpColIdx = palloc_array(AttrNumber, numCols);
 
 	foreach(glitem, groupClause)
 	{
@@ -1089,7 +1089,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
 	 */
 	if (list_member(context->input_target_exprs, node))
 	{
-		split_pathtarget_item *item = palloc(sizeof(split_pathtarget_item));
+		split_pathtarget_item *item = palloc_object(split_pathtarget_item);
 
 		item->expr = node;
 		item->sortgroupref = context->current_sgref;
@@ -1109,7 +1109,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
 		IsA(node, GroupingFunc) ||
 		IsA(node, WindowFunc))
 	{
-		split_pathtarget_item *item = palloc(sizeof(split_pathtarget_item));
+		split_pathtarget_item *item = palloc_object(split_pathtarget_item);
 
 		item->expr = node;
 		item->sortgroupref = context->current_sgref;
@@ -1124,7 +1124,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
 	 */
 	if (IS_SRF_CALL(node))
 	{
-		split_pathtarget_item *item = palloc(sizeof(split_pathtarget_item));
+		split_pathtarget_item *item = palloc_object(split_pathtarget_item);
 		List	   *save_input_vars = context->current_input_vars;
 		List	   *save_input_srfs = context->current_input_srfs;
 		int			save_current_depth = context->current_depth;
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 7843a0c857e..8910cac6a99 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -2641,8 +2641,7 @@ addNSItemForReturning(ParseState *pstate, const char *aliasname,
 	colnames = pstate->p_target_nsitem->p_rte->eref->colnames;
 	numattrs = list_length(colnames);
 
-	nscolumns = (ParseNamespaceColumn *)
-		palloc(numattrs * sizeof(ParseNamespaceColumn));
+	nscolumns = palloc_array(ParseNamespaceColumn, numattrs);
 
 	memcpy(nscolumns, pstate->p_target_nsitem->p_nscolumns,
 		   numattrs * sizeof(ParseNamespaceColumn));
@@ -2652,7 +2651,7 @@ addNSItemForReturning(ParseState *pstate, const char *aliasname,
 		nscolumns[i].p_varreturningtype = returning_type;
 
 	/* build the nsitem, copying most fields from the target relation */
-	nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+	nsitem = palloc_object(ParseNamespaceItem);
 	nsitem->p_names = makeAlias(aliasname, colnames);
 	nsitem->p_rte = pstate->p_target_nsitem->p_rte;
 	nsitem->p_rtindex = pstate->p_target_nsitem->p_rtindex;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c3a0a354a9c..7856ce9d78f 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -4555,19 +4555,19 @@ OptWhereClause:
 key_actions:
 			key_update
 				{
-					KeyActions *n = palloc(sizeof(KeyActions));
+					KeyActions *n = palloc_object(KeyActions);
 
 					n->updateAction = $1;
-					n->deleteAction = palloc(sizeof(KeyAction));
+					n->deleteAction = palloc_object(KeyAction);
 					n->deleteAction->action = FKCONSTR_ACTION_NOACTION;
 					n->deleteAction->cols = NIL;
 					$$ = n;
 				}
 			| key_delete
 				{
-					KeyActions *n = palloc(sizeof(KeyActions));
+					KeyActions *n = palloc_object(KeyActions);
 
-					n->updateAction = palloc(sizeof(KeyAction));
+					n->updateAction = palloc_object(KeyAction);
 					n->updateAction->action = FKCONSTR_ACTION_NOACTION;
 					n->updateAction->cols = NIL;
 					n->deleteAction = $1;
@@ -4575,7 +4575,7 @@ key_actions:
 				}
 			| key_update key_delete
 				{
-					KeyActions *n = palloc(sizeof(KeyActions));
+					KeyActions *n = palloc_object(KeyActions);
 
 					n->updateAction = $1;
 					n->deleteAction = $2;
@@ -4583,7 +4583,7 @@ key_actions:
 				}
 			| key_delete key_update
 				{
-					KeyActions *n = palloc(sizeof(KeyActions));
+					KeyActions *n = palloc_object(KeyActions);
 
 					n->updateAction = $2;
 					n->deleteAction = $1;
@@ -4591,12 +4591,12 @@ key_actions:
 				}
 			| /*EMPTY*/
 				{
-					KeyActions *n = palloc(sizeof(KeyActions));
+					KeyActions *n = palloc_object(KeyActions);
 
-					n->updateAction = palloc(sizeof(KeyAction));
+					n->updateAction = palloc_object(KeyAction);
 					n->updateAction->action = FKCONSTR_ACTION_NOACTION;
 					n->updateAction->cols = NIL;
-					n->deleteAction = palloc(sizeof(KeyAction));
+					n->deleteAction = palloc_object(KeyAction);
 					n->deleteAction->action = FKCONSTR_ACTION_NOACTION;
 					n->deleteAction->cols = NIL;
 					$$ = n;
@@ -4624,7 +4624,7 @@ key_delete: ON DELETE_P key_action
 key_action:
 			NO ACTION
 				{
-					KeyAction *n = palloc(sizeof(KeyAction));
+					KeyAction *n = palloc_object(KeyAction);
 
 					n->action = FKCONSTR_ACTION_NOACTION;
 					n->cols = NIL;
@@ -4632,7 +4632,7 @@ key_action:
 				}
 			| RESTRICT
 				{
-					KeyAction *n = palloc(sizeof(KeyAction));
+					KeyAction *n = palloc_object(KeyAction);
 
 					n->action = FKCONSTR_ACTION_RESTRICT;
 					n->cols = NIL;
@@ -4640,7 +4640,7 @@ key_action:
 				}
 			| CASCADE
 				{
-					KeyAction *n = palloc(sizeof(KeyAction));
+					KeyAction *n = palloc_object(KeyAction);
 
 					n->action = FKCONSTR_ACTION_CASCADE;
 					n->cols = NIL;
@@ -4648,7 +4648,7 @@ key_action:
 				}
 			| SET NULL_P opt_column_list
 				{
-					KeyAction *n = palloc(sizeof(KeyAction));
+					KeyAction *n = palloc_object(KeyAction);
 
 					n->action = FKCONSTR_ACTION_SETNULL;
 					n->cols = $3;
@@ -4656,7 +4656,7 @@ key_action:
 				}
 			| SET DEFAULT opt_column_list
 				{
-					KeyAction *n = palloc(sizeof(KeyAction));
+					KeyAction *n = palloc_object(KeyAction);
 
 					n->action = FKCONSTR_ACTION_SETDEFAULT;
 					n->cols = $3;
@@ -5853,7 +5853,7 @@ import_qualification_type:
 import_qualification:
 		import_qualification_type '(' relation_expr_list ')'
 			{
-				ImportQual *n = (ImportQual *) palloc(sizeof(ImportQual));
+				ImportQual *n = palloc_object(ImportQual);
 
 				n->type = $1;
 				n->table_names = $3;
@@ -5861,7 +5861,7 @@ import_qualification:
 			}
 		| /*EMPTY*/
 			{
-				ImportQual *n = (ImportQual *) palloc(sizeof(ImportQual));
+				ImportQual *n = palloc_object(ImportQual);
 				n->type = FDW_IMPORT_SCHEMA_ALL;
 				n->table_names = NIL;
 				$$ = n;
@@ -7914,7 +7914,7 @@ parameter_name:
 privilege_target:
 			qualified_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_TABLE;
@@ -7923,7 +7923,7 @@ privilege_target:
 				}
 			| TABLE qualified_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_TABLE;
@@ -7932,7 +7932,7 @@ privilege_target:
 				}
 			| SEQUENCE qualified_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_SEQUENCE;
@@ -7941,7 +7941,7 @@ privilege_target:
 				}
 			| FOREIGN DATA_P WRAPPER name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_FDW;
@@ -7950,7 +7950,7 @@ privilege_target:
 				}
 			| FOREIGN SERVER name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_FOREIGN_SERVER;
@@ -7959,7 +7959,7 @@ privilege_target:
 				}
 			| FUNCTION function_with_argtypes_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_FUNCTION;
@@ -7968,7 +7968,7 @@ privilege_target:
 				}
 			| PROCEDURE function_with_argtypes_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_PROCEDURE;
@@ -7977,7 +7977,7 @@ privilege_target:
 				}
 			| ROUTINE function_with_argtypes_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_ROUTINE;
@@ -7986,7 +7986,7 @@ privilege_target:
 				}
 			| DATABASE name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_DATABASE;
@@ -7995,7 +7995,7 @@ privilege_target:
 				}
 			| DOMAIN_P any_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_DOMAIN;
@@ -8004,7 +8004,7 @@ privilege_target:
 				}
 			| LANGUAGE name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_LANGUAGE;
@@ -8013,7 +8013,7 @@ privilege_target:
 				}
 			| LARGE_P OBJECT_P NumericOnly_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_LARGEOBJECT;
@@ -8022,7 +8022,7 @@ privilege_target:
 				}
 			| PARAMETER parameter_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_PARAMETER_ACL;
 					n->objs = $2;
@@ -8030,7 +8030,7 @@ privilege_target:
 				}
 			| SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_SCHEMA;
@@ -8039,7 +8039,7 @@ privilege_target:
 				}
 			| TABLESPACE name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_TABLESPACE;
@@ -8048,7 +8048,7 @@ privilege_target:
 				}
 			| TYPE_P any_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_TYPE;
@@ -8057,7 +8057,7 @@ privilege_target:
 				}
 			| ALL TABLES IN_P SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
 					n->objtype = OBJECT_TABLE;
@@ -8066,7 +8066,7 @@ privilege_target:
 				}
 			| ALL SEQUENCES IN_P SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
 					n->objtype = OBJECT_SEQUENCE;
@@ -8075,7 +8075,7 @@ privilege_target:
 				}
 			| ALL FUNCTIONS IN_P SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
 					n->objtype = OBJECT_FUNCTION;
@@ -8084,7 +8084,7 @@ privilege_target:
 				}
 			| ALL PROCEDURES IN_P SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
 					n->objtype = OBJECT_PROCEDURE;
@@ -8093,7 +8093,7 @@ privilege_target:
 				}
 			| ALL ROUTINES IN_P SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
 					n->objtype = OBJECT_ROUTINE;
@@ -13393,7 +13393,7 @@ select_limit:
 				}
 			| offset_clause
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = $1;
 					n->limitCount = NULL;
@@ -13413,7 +13413,7 @@ opt_select_limit:
 limit_clause:
 			LIMIT select_limit_value
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = NULL;
 					n->limitCount = $2;
@@ -13441,7 +13441,7 @@ limit_clause:
 			 */
 			| FETCH first_or_next select_fetch_first_value row_or_rows ONLY
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = NULL;
 					n->limitCount = $3;
@@ -13453,7 +13453,7 @@ limit_clause:
 				}
 			| FETCH first_or_next select_fetch_first_value row_or_rows WITH TIES
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = NULL;
 					n->limitCount = $3;
@@ -13465,7 +13465,7 @@ limit_clause:
 				}
 			| FETCH first_or_next row_or_rows ONLY
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = NULL;
 					n->limitCount = makeIntConst(1, -1);
@@ -13477,7 +13477,7 @@ limit_clause:
 				}
 			| FETCH first_or_next row_or_rows WITH TIES
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = NULL;
 					n->limitCount = makeIntConst(1, -1);
@@ -13572,7 +13572,7 @@ first_or_next: FIRST_P								{ $$ = 0; }
 group_clause:
 			GROUP_P BY set_quantifier group_by_list
 				{
-					GroupClause *n = (GroupClause *) palloc(sizeof(GroupClause));
+					GroupClause *n = palloc_object(GroupClause);
 
 					n->distinct = $3 == SET_QUANTIFIER_DISTINCT;
 					n->all = false;
@@ -13581,7 +13581,7 @@ group_clause:
 				}
 			| GROUP_P BY ALL
 				{
-					GroupClause *n = (GroupClause *) palloc(sizeof(GroupClause));
+					GroupClause *n = palloc_object(GroupClause);
 					n->distinct = false;
 					n->all = true;
 					n->list = NIL;
@@ -13589,7 +13589,7 @@ group_clause:
 				}
 			| /*EMPTY*/
 				{
-					GroupClause *n = (GroupClause *) palloc(sizeof(GroupClause));
+					GroupClause *n = palloc_object(GroupClause);
 
 					n->distinct = false;
 					n->all = false;
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index ca26f6f61f2..944482207f3 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -733,7 +733,7 @@ transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf)
 	tf->ordinalitycol = -1;
 
 	/* Process column specs */
-	names = palloc(sizeof(char *) * list_length(rtf->columns));
+	names = palloc_array(char *, list_length(rtf->columns));
 
 	colno = 0;
 	foreach(col, rtf->columns)
@@ -1573,7 +1573,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
 		{
 			ParseNamespaceItem *jnsitem;
 
-			jnsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+			jnsitem = palloc_object(ParseNamespaceItem);
 			jnsitem->p_names = j->join_using_alias;
 			jnsitem->p_rte = nsitem->p_rte;
 			jnsitem->p_rtindex = nsitem->p_rtindex;
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 32d6ae918ca..f3fbb6b7382 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -2906,7 +2906,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
 	 * operators, and see which interpretations (cmptypes) exist for each
 	 * operator.
 	 */
-	opinfo_lists = (List **) palloc(nopers * sizeof(List *));
+	opinfo_lists = palloc_array(List *, nopers);
 	cmptypes = NULL;
 	i = 0;
 	foreach(l, opexprs)
@@ -3241,7 +3241,7 @@ getJsonEncodingConst(JsonFormat *format)
 {
 	JsonEncoding encoding;
 	const char *enc;
-	Name		encname = palloc(sizeof(NameData));
+	Name		encname = palloc_object(NameData);
 
 	if (!format ||
 		format->format_type == JS_FORMAT_DEFAULT ||
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 203b7a32178..cafeb87217c 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -40,7 +40,7 @@ make_parsestate(ParseState *parentParseState)
 {
 	ParseState *pstate;
 
-	pstate = palloc0(sizeof(ParseState));
+	pstate = palloc0_object(ParseState);
 
 	pstate->parentParseState = parentParseState;
 
diff --git a/src/backend/parser/parse_param.c b/src/backend/parser/parse_param.c
index 930921626b6..772f3e3c1d8 100644
--- a/src/backend/parser/parse_param.c
+++ b/src/backend/parser/parse_param.c
@@ -68,7 +68,7 @@ void
 setup_parse_fixed_parameters(ParseState *pstate,
 							 const Oid *paramTypes, int numParams)
 {
-	FixedParamState *parstate = palloc(sizeof(FixedParamState));
+	FixedParamState *parstate = palloc_object(FixedParamState);
 
 	parstate->paramTypes = paramTypes;
 	parstate->numParams = numParams;
@@ -84,7 +84,7 @@ void
 setup_parse_variable_parameters(ParseState *pstate,
 								Oid **paramTypes, int *numParams)
 {
-	VarParamState *parstate = palloc(sizeof(VarParamState));
+	VarParamState *parstate = palloc_object(VarParamState);
 
 	parstate->paramTypes = paramTypes;
 	parstate->numParams = numParams;
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index d544a69fc80..dd64f45478a 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -964,7 +964,7 @@ searchRangeTableForCol(ParseState *pstate, const char *alias, const char *colnam
 					   int location)
 {
 	ParseState *orig_pstate = pstate;
-	FuzzyAttrMatchState *fuzzystate = palloc(sizeof(FuzzyAttrMatchState));
+	FuzzyAttrMatchState *fuzzystate = palloc_object(FuzzyAttrMatchState);
 
 	fuzzystate->distance = MAX_FUZZY_DISTANCE + 1;
 	fuzzystate->rfirst = NULL;
@@ -1336,7 +1336,7 @@ buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex,
 	}
 
 	/* ... and build the nsitem */
-	nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+	nsitem = palloc_object(ParseNamespaceItem);
 	nsitem->p_names = rte->eref;
 	nsitem->p_rte = rte;
 	nsitem->p_rtindex = rtindex;
@@ -1400,7 +1400,7 @@ buildNSItemFromLists(RangeTblEntry *rte, Index rtindex,
 	}
 
 	/* ... and build the nsitem */
-	nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+	nsitem = palloc_object(ParseNamespaceItem);
 	nsitem->p_names = rte->eref;
 	nsitem->p_rte = rte;
 	nsitem->p_rtindex = rtindex;
@@ -1791,7 +1791,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
 	rte->eref = eref;
 
 	/* Process each function ... */
-	functupdescs = (TupleDesc *) palloc(nfuncs * sizeof(TupleDesc));
+	functupdescs = palloc_array(TupleDesc, nfuncs);
 
 	totalatts = 0;
 	funcno = 0;
@@ -2302,7 +2302,7 @@ addRangeTableEntryForJoin(ParseState *pstate,
 	 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
 	 * list --- caller must do that if appropriate.
 	 */
-	nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+	nsitem = palloc_object(ParseNamespaceItem);
 	nsitem->p_names = rte->eref;
 	nsitem->p_rte = rte;
 	nsitem->p_perminfo = NULL;
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 7713bdc6af0..c7335ad9db1 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -369,7 +369,7 @@ typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ)
 	 * Currently, we allow simple numeric constants, string literals, and
 	 * identifiers; possibly this list could be extended.
 	 */
-	datums = (Datum *) palloc(list_length(typeName->typmods) * sizeof(Datum));
+	datums = palloc_array(Datum, list_length(typeName->typmods));
 	n = 0;
 	foreach(l, typeName->typmods)
 	{
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 8ba038c5ef4..687a337320e 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -319,7 +319,7 @@ partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts,
 	 * Initialize mapping array with invalid values, this is filled within
 	 * each sub-routine below depending on the bound type.
 	 */
-	*mapping = (int *) palloc(sizeof(int) * nparts);
+	*mapping = palloc_array(int, nparts);
 	for (i = 0; i < nparts; i++)
 		(*mapping)[i] = -1;
 
@@ -353,8 +353,7 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	int			greatest_modulus;
 	Datum	   *boundDatums;
 
-	boundinfo = (PartitionBoundInfoData *)
-		palloc0(sizeof(PartitionBoundInfoData));
+	boundinfo = palloc0_object(PartitionBoundInfoData);
 	boundinfo->strategy = key->strategy;
 	/* No special hash partitions. */
 	boundinfo->null_index = -1;
@@ -384,7 +383,7 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	greatest_modulus = hbounds[nparts - 1].modulus;
 
 	boundinfo->ndatums = nparts;
-	boundinfo->datums = (Datum **) palloc0(nparts * sizeof(Datum *));
+	boundinfo->datums = (Datum **) palloc0_array(Datum *, nparts);
 	boundinfo->kind = NULL;
 	boundinfo->interleaved_parts = NULL;
 	boundinfo->nindexes = greatest_modulus;
@@ -472,8 +471,7 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	int			null_index = -1;
 	Datum	   *boundDatums;
 
-	boundinfo = (PartitionBoundInfoData *)
-		palloc0(sizeof(PartitionBoundInfoData));
+	boundinfo = palloc0_object(PartitionBoundInfoData);
 	boundinfo->strategy = key->strategy;
 	/* Will be set correctly below. */
 	boundinfo->null_index = -1;
@@ -533,7 +531,7 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
 			  qsort_partition_list_value_cmp, key);
 
 	boundinfo->ndatums = ndatums;
-	boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
+	boundinfo->datums = (Datum **) palloc0_array(Datum *, ndatums);
 	boundinfo->kind = NULL;
 	boundinfo->interleaved_parts = NULL;
 	boundinfo->nindexes = ndatums;
@@ -690,8 +688,7 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	Datum	   *boundDatums;
 	PartitionRangeDatumKind *boundKinds;
 
-	boundinfo = (PartitionBoundInfoData *)
-		palloc0(sizeof(PartitionBoundInfoData));
+	boundinfo = palloc0_object(PartitionBoundInfoData);
 	boundinfo->strategy = key->strategy;
 	/* There is no special null-accepting range partition. */
 	boundinfo->null_index = -1;
@@ -699,7 +696,7 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	boundinfo->default_index = -1;
 
 	all_bounds = (PartitionRangeBound **)
-		palloc0(2 * nparts * sizeof(PartitionRangeBound *));
+		palloc0_array(PartitionRangeBound *, 2 * nparts);
 
 	/* Create a unified list of range bounds across all the partitions. */
 	ndatums = 0;
@@ -803,7 +800,7 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	 * bound.
 	 */
 	boundinfo->ndatums = ndatums;
-	boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
+	boundinfo->datums = (Datum **) palloc0_array(Datum *, ndatums);
 	boundinfo->kind = (PartitionRangeDatumKind **)
 		palloc(ndatums *
 			   sizeof(PartitionRangeDatumKind *));
@@ -1008,7 +1005,7 @@ partition_bounds_copy(PartitionBoundInfo src,
 	int			nindexes;
 	int			partnatts;
 
-	dest = (PartitionBoundInfo) palloc(sizeof(PartitionBoundInfoData));
+	dest = (PartitionBoundInfo) palloc_object(PartitionBoundInfoData);
 
 	dest->strategy = src->strategy;
 	ndatums = dest->ndatums = src->ndatums;
@@ -1018,7 +1015,7 @@ partition_bounds_copy(PartitionBoundInfo src,
 	/* List partitioned tables have only a single partition key. */
 	Assert(key->strategy != PARTITION_STRATEGY_LIST || partnatts == 1);
 
-	dest->datums = (Datum **) palloc(sizeof(Datum *) * ndatums);
+	dest->datums = palloc_array(Datum *, ndatums);
 
 	if (src->kind != NULL && ndatums > 0)
 	{
@@ -1092,7 +1089,7 @@ partition_bounds_copy(PartitionBoundInfo src,
 		}
 	}
 
-	dest->indexes = (int *) palloc(sizeof(int) * nindexes);
+	dest->indexes = palloc_array(int, nindexes);
 	memcpy(dest->indexes, src->indexes, sizeof(int) * nindexes);
 
 	dest->null_index = src->null_index;
@@ -1815,10 +1812,10 @@ init_partition_map(RelOptInfo *rel, PartitionMap *map)
 	int			i;
 
 	map->nparts = nparts;
-	map->merged_indexes = (int *) palloc(sizeof(int) * nparts);
-	map->merged = (bool *) palloc(sizeof(bool) * nparts);
+	map->merged_indexes = palloc_array(int, nparts);
+	map->merged = palloc_array(bool, nparts);
 	map->did_remapping = false;
-	map->old_indexes = (int *) palloc(sizeof(int) * nparts);
+	map->old_indexes = palloc_array(int, nparts);
 	for (i = 0; i < nparts; i++)
 	{
 		map->merged_indexes[i] = map->old_indexes[i] = -1;
@@ -2393,7 +2390,7 @@ fix_merged_indexes(PartitionMap *outer_map, PartitionMap *inner_map,
 
 	Assert(nmerged > 0);
 
-	new_indexes = (int *) palloc(sizeof(int) * nmerged);
+	new_indexes = palloc_array(int, nmerged);
 	for (i = 0; i < nmerged; i++)
 		new_indexes[i] = -1;
 
@@ -2453,8 +2450,8 @@ generate_matching_part_pairs(RelOptInfo *outer_rel, RelOptInfo *inner_rel,
 	Assert(*outer_parts == NIL);
 	Assert(*inner_parts == NIL);
 
-	outer_indexes = (int *) palloc(sizeof(int) * nmerged);
-	inner_indexes = (int *) palloc(sizeof(int) * nmerged);
+	outer_indexes = palloc_array(int, nmerged);
+	inner_indexes = palloc_array(int, nmerged);
 	for (i = 0; i < nmerged; i++)
 		outer_indexes[i] = inner_indexes[i] = -1;
 
@@ -2525,11 +2522,11 @@ build_merged_partition_bounds(char strategy, List *merged_datums,
 	int			pos;
 	ListCell   *lc;
 
-	merged_bounds = (PartitionBoundInfo) palloc(sizeof(PartitionBoundInfoData));
+	merged_bounds = (PartitionBoundInfo) palloc_object(PartitionBoundInfoData);
 	merged_bounds->strategy = strategy;
 	merged_bounds->ndatums = ndatums;
 
-	merged_bounds->datums = (Datum **) palloc(sizeof(Datum *) * ndatums);
+	merged_bounds->datums = palloc_array(Datum *, ndatums);
 	pos = 0;
 	foreach(lc, merged_datums)
 		merged_bounds->datums[pos++] = (Datum *) lfirst(lc);
@@ -2537,8 +2534,7 @@ build_merged_partition_bounds(char strategy, List *merged_datums,
 	if (strategy == PARTITION_STRATEGY_RANGE)
 	{
 		Assert(list_length(merged_kinds) == ndatums);
-		merged_bounds->kind = (PartitionRangeDatumKind **)
-			palloc(sizeof(PartitionRangeDatumKind *) * ndatums);
+		merged_bounds->kind = palloc_array(PartitionRangeDatumKind *, ndatums);
 		pos = 0;
 		foreach(lc, merged_kinds)
 			merged_bounds->kind[pos++] = (PartitionRangeDatumKind *) lfirst(lc);
@@ -2559,7 +2555,7 @@ build_merged_partition_bounds(char strategy, List *merged_datums,
 
 	Assert(list_length(merged_indexes) == ndatums);
 	merged_bounds->nindexes = ndatums;
-	merged_bounds->indexes = (int *) palloc(sizeof(int) * ndatums);
+	merged_bounds->indexes = palloc_array(int, ndatums);
 	pos = 0;
 	foreach(lc, merged_indexes)
 		merged_bounds->indexes[pos++] = lfirst_int(lc);
@@ -3434,11 +3430,10 @@ make_one_partition_rbound(PartitionKey key, int index, List *datums, bool lower)
 
 	Assert(datums != NIL);
 
-	bound = (PartitionRangeBound *) palloc0(sizeof(PartitionRangeBound));
+	bound = palloc0_object(PartitionRangeBound);
 	bound->index = index;
-	bound->datums = (Datum *) palloc0(key->partnatts * sizeof(Datum));
-	bound->kind = (PartitionRangeDatumKind *) palloc0(key->partnatts *
-													  sizeof(PartitionRangeDatumKind));
+	bound->datums = palloc0_array(Datum, key->partnatts);
+	bound->kind = palloc0_array(PartitionRangeDatumKind, key->partnatts);
 	bound->lower = lower;
 
 	i = 0;
diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c
index 328b4d450e4..5624f503fec 100644
--- a/src/backend/partitioning/partdesc.c
+++ b/src/backend/partitioning/partdesc.c
@@ -426,7 +426,7 @@ CreatePartitionDirectory(MemoryContext mcxt, bool omit_detached)
 	PartitionDirectory pdir;
 	HASHCTL		ctl;
 
-	pdir = palloc(sizeof(PartitionDirectoryData));
+	pdir = palloc_object(PartitionDirectoryData);
 	pdir->pdir_mcxt = mcxt;
 
 	ctl.keysize = sizeof(Oid);
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 6fff4034c24..bf3f6d80c7a 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -246,7 +246,7 @@ make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
 	 * that zero can represent an un-filled array entry.
 	 */
 	allpartrelids = NIL;
-	relid_subplan_map = palloc0(sizeof(int) * root->simple_rel_array_size);
+	relid_subplan_map = palloc0_array(int, root->simple_rel_array_size);
 
 	i = 1;
 	foreach(lc, subpaths)
@@ -465,7 +465,7 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
 	 * In this phase we discover whether runtime pruning is needed at all; if
 	 * not, we can avoid doing further work.
 	 */
-	relid_subpart_map = palloc0(sizeof(int) * root->simple_rel_array_size);
+	relid_subpart_map = palloc0_array(int, root->simple_rel_array_size);
 
 	i = 1;
 	rti = -1;
@@ -818,9 +818,9 @@ prune_append_rel_partitions(RelOptInfo *rel)
 	context.boundinfo = rel->boundinfo;
 	context.partcollation = rel->part_scheme->partcollation;
 	context.partsupfunc = rel->part_scheme->partsupfunc;
-	context.stepcmpfuncs = (FmgrInfo *) palloc0(sizeof(FmgrInfo) *
-												context.partnatts *
-												list_length(pruning_steps));
+	context.stepcmpfuncs = palloc0_array(FmgrInfo,
+											 context.partnatts *
+												 list_length(pruning_steps));
 	context.ppccontext = CurrentMemoryContext;
 
 	/* These are not valid when being called from the planner */
@@ -1890,7 +1890,7 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
 			return PARTCLAUSE_MATCH_STEPS;
 		}
 
-		partclause = (PartClauseInfo *) palloc(sizeof(PartClauseInfo));
+		partclause = palloc_object(PartClauseInfo);
 		partclause->keyno = partkeyidx;
 		/* Do pruning with the Boolean equality operator. */
 		partclause->opno = BooleanEqualOperator;
@@ -2147,7 +2147,7 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
 		/*
 		 * Build the clause, passing the negator if applicable.
 		 */
-		partclause = (PartClauseInfo *) palloc(sizeof(PartClauseInfo));
+		partclause = palloc_object(PartClauseInfo);
 		partclause->keyno = partkeyidx;
 		if (is_opne_listp)
 		{
@@ -2693,7 +2693,7 @@ get_matching_hash_bounds(PartitionPruneContext *context,
 						 StrategyNumber opstrategy, const Datum *values, int nvalues,
 						 FmgrInfo *partsupfunc, Bitmapset *nullkeys)
 {
-	PruneStepResult *result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
+	PruneStepResult *result = palloc0_object(PruneStepResult);
 	PartitionBoundInfo boundinfo = context->boundinfo;
 	int		   *partindices = boundinfo->indexes;
 	int			partnatts = context->partnatts;
@@ -2770,7 +2770,7 @@ get_matching_list_bounds(PartitionPruneContext *context,
 						 StrategyNumber opstrategy, Datum value, int nvalues,
 						 FmgrInfo *partsupfunc, Bitmapset *nullkeys)
 {
-	PruneStepResult *result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
+	PruneStepResult *result = palloc0_object(PruneStepResult);
 	PartitionBoundInfo boundinfo = context->boundinfo;
 	int			off,
 				minoff,
@@ -2981,7 +2981,7 @@ get_matching_range_bounds(PartitionPruneContext *context,
 						  StrategyNumber opstrategy, const Datum *values, int nvalues,
 						  FmgrInfo *partsupfunc, Bitmapset *nullkeys)
 {
-	PruneStepResult *result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
+	PruneStepResult *result = palloc0_object(PruneStepResult);
 	PartitionBoundInfo boundinfo = context->boundinfo;
 	Oid		   *partcollation = context->partcollation;
 	int			partnatts = context->partnatts;
@@ -3504,7 +3504,7 @@ perform_pruning_base_step(PartitionPruneContext *context,
 			{
 				PruneStepResult *result;
 
-				result = (PruneStepResult *) palloc(sizeof(PruneStepResult));
+				result = palloc_object(PruneStepResult);
 				result->bound_offsets = NULL;
 				result->scan_default = false;
 				result->scan_null = false;
@@ -3593,7 +3593,7 @@ perform_pruning_combine_step(PartitionPruneContext *context,
 							 PartitionPruneStepCombine *cstep,
 							 PruneStepResult **step_results)
 {
-	PruneStepResult *result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
+	PruneStepResult *result = palloc0_object(PruneStepResult);
 	bool		firststep;
 	ListCell   *lc1;
 
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 1c38488f2cb..ed3e7255442 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -1865,7 +1865,7 @@ get_database_list(void)
 		 */
 		oldcxt = MemoryContextSwitchTo(resultcxt);
 
-		avdb = (avw_dbase *) palloc(sizeof(avw_dbase));
+		avdb = palloc_object(avw_dbase);
 
 		avdb->adw_datid = pgdatabase->oid;
 		avdb->adw_name = pstrdup(NameStr(pgdatabase->datname));
@@ -2753,7 +2753,7 @@ extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
 	if (relopts == NULL)
 		return NULL;
 
-	av = palloc(sizeof(AutoVacOpts));
+	av = palloc_object(AutoVacOpts);
 	memcpy(av, &(((StdRdOptions *) relopts)->autovacuum), sizeof(AutoVacOpts));
 	pfree(relopts);
 
@@ -2857,7 +2857,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
-		tab = palloc(sizeof(autovac_table));
+		tab = palloc_object(autovac_table);
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
 
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 142a02eb5e9..8e1068969ae 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -1132,7 +1132,7 @@ RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
 	 */
 	if (success && handle)
 	{
-		*handle = palloc(sizeof(BackgroundWorkerHandle));
+		*handle = palloc_object(BackgroundWorkerHandle);
 		(*handle)->slot = slotno;
 		(*handle)->generation = generation;
 	}
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index e84e8663e96..f9d1d5ec93c 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -1316,7 +1316,7 @@ CompactCheckpointerRequestQueue(void)
 	num_requests = CheckpointerShmem->num_requests;
 
 	/* Initialize skip_slot array */
-	skip_slot = palloc0(sizeof(bool) * max_requests);
+	skip_slot = palloc0_array(bool, max_requests);
 
 	head = CheckpointerShmem->head;
 
diff --git a/src/backend/postmaster/launch_backend.c b/src/backend/postmaster/launch_backend.c
index 976638a58ac..98f7c4848c9 100644
--- a/src/backend/postmaster/launch_backend.c
+++ b/src/backend/postmaster/launch_backend.c
@@ -258,7 +258,7 @@ postmaster_child_launch(BackendType child_type, int child_slot,
 		MyPMChildSlot = child_slot;
 		if (client_sock)
 		{
-			MyClientSocket = palloc(sizeof(ClientSocket));
+			MyClientSocket = palloc_object(ClientSocket);
 			memcpy(MyClientSocket, client_sock, sizeof(ClientSocket));
 		}
 
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index ce6b5299324..3a65d841725 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -257,7 +257,7 @@ PgArchiverMain(const void *startup_data, size_t startup_data_len)
 	PgArch->pgprocno = MyProcNumber;
 
 	/* Create workspace for pgarch_readyXlog() */
-	arch_files = palloc(sizeof(struct arch_files_state));
+	arch_files = palloc_object(struct arch_files_state);
 	arch_files->arch_files_size = 0;
 
 	/* Initialize our max-heap for prioritizing files to archive. */
@@ -945,7 +945,7 @@ LoadArchiveLibrary(void)
 		ereport(ERROR,
 				(errmsg("archive modules must register an archive callback")));
 
-	archive_module_state = (ArchiveModuleState *) palloc0(sizeof(ArchiveModuleState));
+	archive_module_state = palloc0_object(ArchiveModuleState);
 	if (ArchiveCallbacks->startup_cb != NULL)
 		ArchiveCallbacks->startup_cb(archive_module_state);
 
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 7c064cf9fbb..55dca3dba79 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4562,7 +4562,7 @@ pgwin32_register_deadchild_callback(HANDLE procHandle, DWORD procId)
 {
 	win32_deadchild_waitinfo *childinfo;
 
-	childinfo = palloc(sizeof(win32_deadchild_waitinfo));
+	childinfo = palloc_object(win32_deadchild_waitinfo);
 	childinfo->procHandle = procHandle;
 	childinfo->procId = procId;
 
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 50c2edec1f6..526ad053a45 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -960,7 +960,7 @@ process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
 						 * Need a free slot, but there isn't one in the list,
 						 * so create a new one and extend the list with it.
 						 */
-						free_slot = palloc(sizeof(save_buffer));
+						free_slot = palloc_object(save_buffer);
 						buffer_list = lappend(buffer_list, free_slot);
 						buffer_lists[p.pid % NBUFFER_LISTS] = buffer_list;
 					}
diff --git a/src/backend/postmaster/walsummarizer.c b/src/backend/postmaster/walsummarizer.c
index c4a888a081c..e7e4d652f97 100644
--- a/src/backend/postmaster/walsummarizer.c
+++ b/src/backend/postmaster/walsummarizer.c
@@ -920,8 +920,7 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact,
 	bool		fast_forward = true;
 
 	/* Initialize private data for xlogreader. */
-	private_data = (SummarizerReadLocalXLogPrivate *)
-		palloc0(sizeof(SummarizerReadLocalXLogPrivate));
+	private_data = palloc0_object(SummarizerReadLocalXLogPrivate);
 	private_data->tli = tli;
 	private_data->historic = XLogRecPtrIsValid(switch_lsn);
 	private_data->read_upto = maximum_lsn;
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 239641bfbb6..5ddc9e812e7 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -211,7 +211,7 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
 
 	Assert(i < lengthof(keys));
 
-	conn = palloc0(sizeof(WalReceiverConn));
+	conn = palloc0_object(WalReceiverConn);
 	conn->streamConn =
 		libpqsrv_connect_params(keys, vals,
 								 /* expand_dbname = */ true,
@@ -1102,7 +1102,7 @@ libpqrcv_exec(WalReceiverConn *conn, const char *query,
 			  const int nRetTypes, const Oid *retTypes)
 {
 	PGresult   *pgres = NULL;
-	WalRcvExecResult *walres = palloc0(sizeof(WalRcvExecResult));
+	WalRcvExecResult *walres = palloc0_object(WalRcvExecResult);
 	char	   *diag_sqlstate;
 
 	if (MyDatabaseId == InvalidOid)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index baa68c1ab6c..43bea31f177 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -425,7 +425,7 @@ pa_launch_parallel_worker(void)
 	 */
 	oldcontext = MemoryContextSwitchTo(ApplyContext);
 
-	winfo = (ParallelApplyWorkerInfo *) palloc0(sizeof(ParallelApplyWorkerInfo));
+	winfo = palloc0_object(ParallelApplyWorkerInfo);
 
 	/* Setup shared memory. */
 	if (!pa_setup_dsm(winfo))
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index fdf1ccad462..3991e1495d4 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -147,7 +147,7 @@ get_subscription_list(void)
 		 */
 		oldcxt = MemoryContextSwitchTo(resultcxt);
 
-		sub = (Subscription *) palloc0(sizeof(Subscription));
+		sub = palloc0_object(Subscription);
 		sub->oid = subform->oid;
 		sub->dbid = subform->subdbid;
 		sub->owner = subform->subowner;
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index 866f92cf799..1b11ed63dc6 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -172,7 +172,7 @@ StartupDecodingContext(List *output_plugin_options,
 									"Logical decoding context",
 									ALLOCSET_DEFAULT_SIZES);
 	old_context = MemoryContextSwitchTo(context);
-	ctx = palloc0(sizeof(LogicalDecodingContext));
+	ctx = palloc0_object(LogicalDecodingContext);
 
 	ctx->context = context;
 
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
index 25b2b795925..cf77ee28dfe 100644
--- a/src/backend/replication/logical/logicalfuncs.c
+++ b/src/backend/replication/logical/logicalfuncs.c
@@ -140,7 +140,7 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
 	arr = PG_GETARG_ARRAYTYPE_P(3);
 
 	/* state to write output to */
-	p = palloc0(sizeof(DecodingOutputState));
+	p = palloc0_object(DecodingOutputState);
 
 	p->binary_output = binary;
 
diff --git a/src/backend/replication/logical/proto.c b/src/backend/replication/logical/proto.c
index f0a913892b9..27ad74fd759 100644
--- a/src/backend/replication/logical/proto.c
+++ b/src/backend/replication/logical/proto.c
@@ -697,7 +697,7 @@ logicalrep_write_rel(StringInfo out, TransactionId xid, Relation rel,
 LogicalRepRelation *
 logicalrep_read_rel(StringInfo in)
 {
-	LogicalRepRelation *rel = palloc(sizeof(LogicalRepRelation));
+	LogicalRepRelation *rel = palloc_object(LogicalRepRelation);
 
 	rel->remoteid = pq_getmsgint(in, 4);
 
@@ -871,7 +871,7 @@ logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple)
 
 	/* Allocate space for per-column values; zero out unused StringInfoDatas */
 	tuple->colvalues = (StringInfoData *) palloc0(natts * sizeof(StringInfoData));
-	tuple->colstatus = (char *) palloc(natts * sizeof(char));
+	tuple->colstatus = palloc_array(char, natts);
 	tuple->ncols = natts;
 
 	/* Read the data */
@@ -994,8 +994,8 @@ logicalrep_read_attrs(StringInfo in, LogicalRepRelation *rel)
 	Bitmapset  *attkeys = NULL;
 
 	natts = pq_getmsgint(in, 2);
-	attnames = palloc(natts * sizeof(char *));
-	atttyps = palloc(natts * sizeof(Oid));
+	attnames = palloc_array(char *, natts);
+	atttyps = palloc_array(Oid, natts);
 
 	/* read the attributes */
 	for (i = 0; i < natts; i++)
diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c
index 10b3d0d9b82..2c8485b881f 100644
--- a/src/backend/replication/logical/relation.c
+++ b/src/backend/replication/logical/relation.c
@@ -188,8 +188,8 @@ logicalrep_relmap_update(LogicalRepRelation *remoterel)
 	entry->remoterel.nspname = pstrdup(remoterel->nspname);
 	entry->remoterel.relname = pstrdup(remoterel->relname);
 	entry->remoterel.natts = remoterel->natts;
-	entry->remoterel.attnames = palloc(remoterel->natts * sizeof(char *));
-	entry->remoterel.atttyps = palloc(remoterel->natts * sizeof(Oid));
+	entry->remoterel.attnames = palloc_array(char *, remoterel->natts);
+	entry->remoterel.atttyps = palloc_array(Oid, remoterel->natts);
 	for (i = 0; i < remoterel->natts; i++)
 	{
 		entry->remoterel.attnames[i] = pstrdup(remoterel->attnames[i]);
@@ -704,8 +704,8 @@ logicalrep_partition_open(LogicalRepRelMapEntry *root,
 		entry->remoterel.nspname = pstrdup(remoterel->nspname);
 		entry->remoterel.relname = pstrdup(remoterel->relname);
 		entry->remoterel.natts = remoterel->natts;
-		entry->remoterel.attnames = palloc(remoterel->natts * sizeof(char *));
-		entry->remoterel.atttyps = palloc(remoterel->natts * sizeof(Oid));
+		entry->remoterel.attnames = palloc_array(char *, remoterel->natts);
+		entry->remoterel.atttyps = palloc_array(Oid, remoterel->natts);
 		for (i = 0; i < remoterel->natts; i++)
 		{
 			entry->remoterel.attnames[i] = pstrdup(remoterel->attnames[i]);
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index eb6a84554b7..f18c6fb52b5 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -3489,8 +3489,7 @@ ReorderBufferQueueInvalidations(ReorderBuffer *rb, TransactionId xid,
 	change = ReorderBufferAllocChange(rb);
 	change->action = REORDER_BUFFER_CHANGE_INVALIDATION;
 	change->data.inval.ninvalidations = nmsgs;
-	change->data.inval.invalidations = (SharedInvalidationMessage *)
-		palloc(sizeof(SharedInvalidationMessage) * nmsgs);
+	change->data.inval.invalidations = palloc_array(SharedInvalidationMessage, nmsgs);
 	memcpy(change->data.inval.invalidations, msgs,
 		   sizeof(SharedInvalidationMessage) * nmsgs);
 
@@ -3511,8 +3510,7 @@ ReorderBufferAccumulateInvalidations(SharedInvalidationMessage **invals_out,
 	if (*ninvals_out == 0)
 	{
 		*ninvals_out = nmsgs_new;
-		*invals_out = (SharedInvalidationMessage *)
-			palloc(sizeof(SharedInvalidationMessage) * nmsgs_new);
+		*invals_out = palloc_array(SharedInvalidationMessage, nmsgs_new);
 		memcpy(*invals_out, msgs_new, sizeof(SharedInvalidationMessage) * nmsgs_new);
 	}
 	else
@@ -3701,8 +3699,7 @@ ReorderBufferGetCatalogChangesXacts(ReorderBuffer *rb)
 		return NULL;
 
 	/* Initialize XID array */
-	xids = (TransactionId *) palloc(sizeof(TransactionId) *
-									dclist_count(&rb->catchange_txns));
+	xids = palloc_array(TransactionId, dclist_count(&rb->catchange_txns));
 	dclist_foreach(iter, &rb->catchange_txns)
 	{
 		ReorderBufferTXN *txn = dclist_container(ReorderBufferTXN,
@@ -5124,9 +5121,9 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
 	toast_desc = RelationGetDescr(toast_rel);
 
 	/* should we allocate from stack instead? */
-	attrs = palloc0(sizeof(Datum) * desc->natts);
-	isnull = palloc0(sizeof(bool) * desc->natts);
-	free = palloc0(sizeof(bool) * desc->natts);
+	attrs = palloc0_array(Datum, desc->natts);
+	isnull = palloc0_array(bool, desc->natts);
+	free = palloc0_array(bool, desc->natts);
 
 	newtup = change->data.tp.newtuple;
 
@@ -5531,7 +5528,7 @@ UpdateLogicalMappings(HTAB *tuplecid_data, Oid relid, Snapshot snapshot)
 			continue;
 
 		/* ok, relevant, queue for apply */
-		f = palloc(sizeof(RewriteMappingFile));
+		f = palloc_object(RewriteMappingFile);
 		f->lsn = f_lsn;
 		strcpy(f->fname, mapping_de->d_name);
 		files = lappend(files, f);
diff --git a/src/backend/replication/logical/slotsync.c b/src/backend/replication/logical/slotsync.c
index 1f4f06d467b..6c982d8ca17 100644
--- a/src/backend/replication/logical/slotsync.c
+++ b/src/backend/replication/logical/slotsync.c
@@ -886,7 +886,7 @@ synchronize_slots(WalReceiverConn *wrconn)
 	while (tuplestore_gettupleslot(res->tuplestore, true, false, tupslot))
 	{
 		bool		isnull;
-		RemoteSlot *remote_slot = palloc0(sizeof(RemoteSlot));
+		RemoteSlot *remote_slot = palloc0_object(RemoteSlot);
 		Datum		d;
 		int			col = 0;
 
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index 6e18baa33cb..d6ab1e017eb 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -199,7 +199,7 @@ AllocateSnapshotBuilder(ReorderBuffer *reorder,
 									ALLOCSET_DEFAULT_SIZES);
 	oldcontext = MemoryContextSwitchTo(context);
 
-	builder = palloc0(sizeof(SnapBuild));
+	builder = palloc0_object(SnapBuild);
 
 	builder->state = SNAPBUILD_START;
 	builder->context = context;
@@ -486,8 +486,7 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
 	MyProc->xmin = snap->xmin;
 
 	/* allocate in transaction context */
-	newxip = (TransactionId *)
-		palloc(sizeof(TransactionId) * GetMaxSnapshotXidCount());
+	newxip = palloc_array(TransactionId, GetMaxSnapshotXidCount());
 
 	/*
 	 * snapbuild.c builds transactions in an "inverted" manner, which means it
diff --git a/src/backend/replication/logical/syncutils.c b/src/backend/replication/logical/syncutils.c
index a696b1f2dc0..332819804be 100644
--- a/src/backend/replication/logical/syncutils.c
+++ b/src/backend/replication/logical/syncutils.c
@@ -243,7 +243,7 @@ FetchRelationStates(bool *has_pending_subtables,
 				has_subsequences_non_ready = true;
 			else
 			{
-				rstate = palloc(sizeof(SubscriptionRelState));
+				rstate = palloc_object(SubscriptionRelState);
 				memcpy(rstate, subrel, sizeof(SubscriptionRelState));
 				table_states_not_ready = lappend(table_states_not_ready,
 												 rstate);
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 93970c6af29..ffde284dd3c 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -875,7 +875,7 @@ create_edata_for_relation(LogicalRepRelMapEntry *rel)
 	List	   *perminfos = NIL;
 	ResultRelInfo *resultRelInfo;
 
-	edata = (ApplyExecutionData *) palloc0(sizeof(ApplyExecutionData));
+	edata = palloc0_object(ApplyExecutionData);
 	edata->targetRel = rel;
 
 	edata->estate = estate = CreateExecutorState();
@@ -1702,7 +1702,7 @@ stream_start_internal(TransactionId xid, bool first_segment)
 
 		oldctx = MemoryContextSwitchTo(ApplyContext);
 
-		MyLogicalRepWorker->stream_fileset = palloc(sizeof(FileSet));
+		MyLogicalRepWorker->stream_fileset = palloc_object(FileSet);
 		FileSetInit(MyLogicalRepWorker->stream_fileset);
 
 		MemoryContextSwitchTo(oldctx);
@@ -3951,7 +3951,7 @@ store_flush_position(XLogRecPtr remote_lsn, XLogRecPtr local_lsn)
 	MemoryContextSwitchTo(ApplyContext);
 
 	/* Track commit lsn  */
-	flushpos = (FlushPosition *) palloc(sizeof(FlushPosition));
+	flushpos = palloc_object(FlushPosition);
 	flushpos->local_end = local_lsn;
 	flushpos->remote_end = remote_lsn;
 
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 942e1abdb58..787998abb8a 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -447,7 +447,7 @@ static void
 pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 				 bool is_init)
 {
-	PGOutputData *data = palloc0(sizeof(PGOutputData));
+	PGOutputData *data = palloc0_object(PGOutputData);
 	static bool publication_callback_registered = false;
 	MemoryContextCallback *mcallback;
 
@@ -468,7 +468,7 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 	 * Ensure to cleanup RelationSyncCache even when logical decoding invoked
 	 * via SQL interface ends up with an error.
 	 */
-	mcallback = palloc0(sizeof(MemoryContextCallback));
+	mcallback = palloc0_object(MemoryContextCallback);
 	mcallback->func = pgoutput_memory_context_reset;
 	MemoryContextRegisterResetCallback(ctx->context, mcallback);
 
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index a0c79958fd5..298a3766d76 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -705,9 +705,9 @@ SyncRepGetNthLatestSyncRecPtr(XLogRecPtr *writePtr,
 	/* Should have enough candidates, or somebody messed up */
 	Assert(nth > 0 && nth <= num_standbys);
 
-	write_array = (XLogRecPtr *) palloc(sizeof(XLogRecPtr) * num_standbys);
-	flush_array = (XLogRecPtr *) palloc(sizeof(XLogRecPtr) * num_standbys);
-	apply_array = (XLogRecPtr *) palloc(sizeof(XLogRecPtr) * num_standbys);
+	write_array = palloc_array(XLogRecPtr, num_standbys);
+	flush_array = palloc_array(XLogRecPtr, num_standbys);
+	apply_array = palloc_array(XLogRecPtr, num_standbys);
 
 	for (i = 0; i < num_standbys; i++)
 	{
@@ -757,8 +757,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys)
 	int			n;
 
 	/* Create result array */
-	*standbys = (SyncRepStandbyData *)
-		palloc(max_wal_senders * sizeof(SyncRepStandbyData));
+	*standbys = palloc_array(SyncRepStandbyData, max_wal_senders);
 
 	/* Quick exit if sync replication is not requested */
 	if (SyncRepConfig == NULL)
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 4217fc54e2e..3ac48a847b3 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -1450,8 +1450,8 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS)
 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
 		elog(ERROR, "return type must be a row type");
 
-	values = palloc0(sizeof(Datum) * tupdesc->natts);
-	nulls = palloc0(sizeof(bool) * tupdesc->natts);
+	values = palloc0_array(Datum, tupdesc->natts);
+	nulls = palloc0_array(bool, tupdesc->natts);
 
 	/* Fetch values */
 	values[0] = Int32GetDatum(pid);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index fc8f8559073..e5accc3d3b0 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -3973,7 +3973,7 @@ WalSndGetStateString(WalSndState state)
 static Interval *
 offset_to_interval(TimeOffset offset)
 {
-	Interval   *result = palloc(sizeof(Interval));
+	Interval   *result = palloc_object(Interval);
 
 	result->month = 0;
 	result->day = 0;
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index adc9e7600e1..a89c4554c19 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -4267,7 +4267,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events, int orig_rt_length)
 									RelationGetRelationName(rt_entry_relation))));
 			}
 
-			rev = (rewrite_event *) palloc(sizeof(rewrite_event));
+			rev = palloc_object(rewrite_event);
 			rev->relation = RelationGetRelid(rt_entry_relation);
 			rev->event = event;
 			rewrite_events = lappend(rewrite_events, rev);
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index 0fcd1fbd14e..f3c2886ed54 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -1590,7 +1590,7 @@ map_variable_attnos_mutator(Node *node,
 			var->varlevelsup == context->sublevels_up)
 		{
 			/* Found a matching variable, make the substitution */
-			Var		   *newvar = (Var *) palloc(sizeof(Var));
+			Var		   *newvar = palloc_object(Var);
 			int			attno = var->varattno;
 
 			*newvar = *var;		/* initially copy all fields of the Var */
@@ -1661,7 +1661,7 @@ map_variable_attnos_mutator(Node *node,
 			context->to_rowtype != var->vartype)
 		{
 			ConvertRowtypeExpr *newnode;
-			Var		   *newvar = (Var *) palloc(sizeof(Var));
+			Var		   *newvar = palloc_object(Var);
 
 			/* whole-row variable, warn caller */
 			*(context->found_whole_row) = true;
@@ -1674,7 +1674,7 @@ map_variable_attnos_mutator(Node *node,
 			/* Var itself is changed to the requested type. */
 			newvar->vartype = context->to_rowtype;
 
-			newnode = (ConvertRowtypeExpr *) palloc(sizeof(ConvertRowtypeExpr));
+			newnode = palloc_object(ConvertRowtypeExpr);
 			*newnode = *r;		/* initially copy all fields of the CRE */
 			newnode->arg = (Expr *) newvar;
 
diff --git a/src/backend/snowball/dict_snowball.c b/src/backend/snowball/dict_snowball.c
index e2b811a3806..d3c022ae548 100644
--- a/src/backend/snowball/dict_snowball.c
+++ b/src/backend/snowball/dict_snowball.c
@@ -229,7 +229,7 @@ dsnowball_init(PG_FUNCTION_ARGS)
 	bool		stoploaded = false;
 	ListCell   *l;
 
-	d = (DictSnowball *) palloc0(sizeof(DictSnowball));
+	d = palloc0_object(DictSnowball);
 
 	foreach(l, dictoptions)
 	{
@@ -278,7 +278,7 @@ dsnowball_lexize(PG_FUNCTION_ARGS)
 	char	   *in = (char *) PG_GETARG_POINTER(1);
 	int32		len = PG_GETARG_INT32(2);
 	char	   *txt = str_tolower(in, len, DEFAULT_COLLATION_OID);
-	TSLexeme   *res = palloc0(sizeof(TSLexeme) * 2);
+	TSLexeme   *res = palloc0_array(TSLexeme, 2);
 
 	/*
 	 * Do not pass strings exceeding 1000 bytes to the stemmer, as they're
diff --git a/src/backend/statistics/dependencies.c b/src/backend/statistics/dependencies.c
index 6f63b4f3ffb..6cfa4478d28 100644
--- a/src/backend/statistics/dependencies.c
+++ b/src/backend/statistics/dependencies.c
@@ -150,7 +150,7 @@ generate_dependencies_recurse(DependencyGenerator state, int index,
 static void
 generate_dependencies(DependencyGenerator state)
 {
-	AttrNumber *current = (AttrNumber *) palloc0(sizeof(AttrNumber) * state->k);
+	AttrNumber *current = palloc0_array(AttrNumber, state->k);
 
 	generate_dependencies_recurse(state, 0, 0, current);
 
@@ -171,8 +171,8 @@ DependencyGenerator_init(int n, int k)
 	Assert((n >= k) && (k > 0));
 
 	/* allocate the DependencyGenerator state */
-	state = (DependencyGenerator) palloc0(sizeof(DependencyGeneratorData));
-	state->dependencies = (AttrNumber *) palloc(k * sizeof(AttrNumber));
+	state = palloc0_object(DependencyGeneratorData);
+	state->dependencies = palloc_array(AttrNumber, k);
 
 	state->ndependencies = 0;
 	state->current = 0;
@@ -237,7 +237,7 @@ dependency_degree(StatsBuildData *data, int k, AttrNumber *dependency)
 	 * Translate the array of indexes to regular attnums for the dependency
 	 * (we will need this to identify the columns in StatsBuildData).
 	 */
-	attnums_dep = (AttrNumber *) palloc(k * sizeof(AttrNumber));
+	attnums_dep = palloc_array(AttrNumber, k);
 	for (i = 0; i < k; i++)
 		attnums_dep[i] = data->attnums[dependency[i]];
 
@@ -402,8 +402,7 @@ statext_dependencies_build(StatsBuildData *data)
 			/* initialize the list of dependencies */
 			if (dependencies == NULL)
 			{
-				dependencies
-					= (MVDependencies *) palloc0(sizeof(MVDependencies));
+				dependencies = palloc0_object(MVDependencies);
 
 				dependencies->magic = STATS_DEPS_MAGIC;
 				dependencies->type = STATS_DEPS_TYPE_BASIC;
@@ -505,7 +504,7 @@ statext_dependencies_deserialize(bytea *data)
 			 VARSIZE_ANY_EXHDR(data), SizeOfHeader);
 
 	/* read the MVDependencies header */
-	dependencies = (MVDependencies *) palloc0(sizeof(MVDependencies));
+	dependencies = palloc0_object(MVDependencies);
 
 	/* initialize pointer to the data part (skip the varlena header) */
 	tmp = VARDATA_ANY(data);
@@ -959,7 +958,7 @@ clauselist_apply_dependencies(PlannerInfo *root, List *clauses,
 	 * and mark all the corresponding clauses as estimated.
 	 */
 	nattrs = bms_num_members(attnums);
-	attr_sel = (Selectivity *) palloc(sizeof(Selectivity) * nattrs);
+	attr_sel = palloc_array(Selectivity, nattrs);
 
 	attidx = 0;
 	i = -1;
@@ -1306,8 +1305,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
 	if (!has_stats_of_kind(rel->statlist, STATS_EXT_DEPENDENCIES))
 		return 1.0;
 
-	list_attnums = (AttrNumber *) palloc(sizeof(AttrNumber) *
-										 list_length(clauses));
+	list_attnums = palloc_array(AttrNumber, list_length(clauses));
 
 	/*
 	 * We allocate space as if every clause was a unique expression, although
@@ -1315,7 +1313,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
 	 * we'll translate to attnums, and there might be duplicates. But it's
 	 * easier and cheaper to just do one allocation than repalloc later.
 	 */
-	unique_exprs = (Node **) palloc(sizeof(Node *) * list_length(clauses));
+	unique_exprs = palloc_array(Node *, list_length(clauses));
 	unique_exprs_cnt = 0;
 
 	/*
@@ -1468,8 +1466,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
 	 * make it just the right size, but it's likely wasteful anyway thanks to
 	 * moving the freed chunks to freelists etc.
 	 */
-	func_dependencies = (MVDependencies **) palloc(sizeof(MVDependencies *) *
-												   list_length(rel->statlist));
+	func_dependencies = palloc_array(MVDependencies *, list_length(rel->statlist));
 	nfunc_dependencies = 0;
 	total_ndeps = 0;
 
@@ -1692,8 +1689,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
 	 * Work out which dependencies we can apply, starting with the
 	 * widest/strongest ones, and proceeding to smaller/weaker ones.
 	 */
-	dependencies = (MVDependency **) palloc(sizeof(MVDependency *) *
-											total_ndeps);
+	dependencies = palloc_array(MVDependency *, total_ndeps);
 	ndependencies = 0;
 
 	while (true)
diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c
index 3c3d2d315c6..179d15c51ee 100644
--- a/src/backend/statistics/extended_stats.c
+++ b/src/backend/statistics/extended_stats.c
@@ -446,7 +446,7 @@ fetch_statentries_for_relation(Relation pg_statext, Oid relid)
 		Form_pg_statistic_ext staForm;
 		List	   *exprs = NIL;
 
-		entry = palloc0(sizeof(StatExtEntry));
+		entry = palloc0_object(StatExtEntry);
 		staForm = (Form_pg_statistic_ext) GETSTRUCT(htup);
 		entry->statOid = staForm->oid;
 		entry->schema = get_namespace_name(staForm->stxnamespace);
@@ -532,7 +532,7 @@ examine_attribute(Node *expr)
 	/*
 	 * Create the VacAttrStats struct.
 	 */
-	stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
+	stats = palloc0_object(VacAttrStats);
 	stats->attstattarget = -1;
 
 	/*
@@ -613,7 +613,7 @@ examine_expression(Node *expr, int stattarget)
 	/*
 	 * Create the VacAttrStats struct.
 	 */
-	stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
+	stats = palloc0_object(VacAttrStats);
 
 	/*
 	 * We can't have statistics target specified for the expression, so we
@@ -946,7 +946,7 @@ build_attnums_array(Bitmapset *attrs, int nexprs, int *numattrs)
 		*numattrs = num;
 
 	/* build attnums from the bitmapset */
-	attnums = (AttrNumber *) palloc(sizeof(AttrNumber) * num);
+	attnums = palloc_array(AttrNumber, num);
 	i = 0;
 	j = -1;
 	while ((j = bms_next_member(attrs, j)) >= 0)
@@ -1028,7 +1028,7 @@ build_sorted_items(StatsBuildData *data, int *nitems,
 	}
 
 	/* build a local cache of typlen for all attributes */
-	typlen = (int *) palloc(sizeof(int) * data->nattnums);
+	typlen = palloc_array(int, data->nattnums);
 	for (i = 0; i < data->nattnums; i++)
 		typlen[i] = get_typlen(data->stats[i]->attrtypid);
 
@@ -1707,11 +1707,10 @@ statext_mcv_clauselist_selectivity(PlannerInfo *root, List *clauses, int varReli
 	if (!has_stats_of_kind(rel->statlist, STATS_EXT_MCV))
 		return sel;
 
-	list_attnums = (Bitmapset **) palloc(sizeof(Bitmapset *) *
-										 list_length(clauses));
+	list_attnums = palloc_array(Bitmapset *, list_length(clauses));
 
 	/* expressions extracted from complex expressions */
-	list_exprs = (List **) palloc(sizeof(Node *) * list_length(clauses));
+	list_exprs = palloc_array(List *, list_length(clauses));
 
 	/*
 	 * Pre-process the clauses list to extract the attnums and expressions
diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c
index f59fb821543..7c93549cd7f 100644
--- a/src/backend/statistics/mcv.c
+++ b/src/backend/statistics/mcv.c
@@ -270,7 +270,7 @@ statext_mcv_build(StatsBuildData *data, double totalrows, int stattarget)
 										+ sizeof(SortSupportData));
 
 		/* compute frequencies for values in each column */
-		nfreqs = (int *) palloc0(sizeof(int) * numattrs);
+		nfreqs = (int *) palloc0_array(int, numattrs);
 		freqs = build_column_frequencies(groups, ngroups, mss, nfreqs);
 
 		/*
@@ -294,8 +294,8 @@ statext_mcv_build(StatsBuildData *data, double totalrows, int stattarget)
 			/* just point to the proper place in the list */
 			MCVItem    *item = &mcvlist->items[i];
 
-			item->values = (Datum *) palloc(sizeof(Datum) * numattrs);
-			item->isnull = (bool *) palloc(sizeof(bool) * numattrs);
+			item->values = palloc_array(Datum, numattrs);
+			item->isnull = palloc_array(bool, numattrs);
 
 			/* copy values for the group */
 			memcpy(item->values, groups[i].values, sizeof(Datum) * numattrs);
@@ -635,8 +635,8 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
 	char	   *endptr PG_USED_FOR_ASSERTS_ONLY;
 
 	/* values per dimension (and number of non-NULL values) */
-	Datum	  **values = (Datum **) palloc0(sizeof(Datum *) * ndims);
-	int		   *counts = (int *) palloc0(sizeof(int) * ndims);
+	Datum	  **values = (Datum **) palloc0_array(Datum *, ndims);
+	int		   *counts = (int *) palloc0_array(int, ndims);
 
 	/*
 	 * We'll include some rudimentary information about the attribute types
@@ -646,10 +646,10 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
 	 * the statistics gets dropped automatically.  We need to store the info
 	 * about the arrays of deduplicated values anyway.
 	 */
-	info = (DimensionInfo *) palloc0(sizeof(DimensionInfo) * ndims);
+	info = (DimensionInfo *) palloc0_array(DimensionInfo, ndims);
 
 	/* sort support data for all attributes included in the MCV list */
-	ssup = (SortSupport) palloc0(sizeof(SortSupportData) * ndims);
+	ssup = (SortSupport) palloc0_array(SortSupportData, ndims);
 
 	/* collect and deduplicate values for each dimension (attribute) */
 	for (dim = 0; dim < ndims; dim++)
@@ -668,7 +668,7 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
 		info[dim].typbyval = stats[dim]->attrtype->typbyval;
 
 		/* allocate space for values in the attribute and collect them */
-		values[dim] = (Datum *) palloc0(sizeof(Datum) * mcvlist->nitems);
+		values[dim] = (Datum *) palloc0_array(Datum, mcvlist->nitems);
 
 		for (i = 0; i < mcvlist->nitems; i++)
 		{
@@ -1134,11 +1134,11 @@ statext_mcv_deserialize(bytea *data)
 	 * original values (it might go away).
 	 */
 	datalen = 0;				/* space for by-ref data */
-	map = (Datum **) palloc(ndims * sizeof(Datum *));
+	map = palloc_array(Datum *, ndims);
 
 	for (dim = 0; dim < ndims; dim++)
 	{
-		map[dim] = (Datum *) palloc(sizeof(Datum) * info[dim].nvalues);
+		map[dim] = palloc_array(Datum, info[dim].nvalues);
 
 		/* space needed for a copy of data for by-ref types */
 		datalen += info[dim].nbytes_aligned;
@@ -1609,7 +1609,7 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
 	Assert(mcvlist->nitems > 0);
 	Assert(mcvlist->nitems <= STATS_MCVLIST_MAX_ITEMS);
 
-	matches = palloc(sizeof(bool) * mcvlist->nitems);
+	matches = palloc_array(bool, mcvlist->nitems);
 	memset(matches, !is_or, sizeof(bool) * mcvlist->nitems);
 
 	/*
@@ -2134,7 +2134,7 @@ mcv_clause_selectivity_or(PlannerInfo *root, StatisticExtInfo *stat,
 
 	/* build the OR-matches bitmap, if not built already */
 	if (*or_matches == NULL)
-		*or_matches = palloc0(sizeof(bool) * mcv->nitems);
+		*or_matches = palloc0_array(bool, mcv->nitems);
 
 	/* build the match bitmap for the new clause */
 	new_matches = mcv_get_match_bitmap(root, list_make1(clause), stat->keys,
diff --git a/src/backend/statistics/mvdistinct.c b/src/backend/statistics/mvdistinct.c
index fe452f53ae4..58046d2bd62 100644
--- a/src/backend/statistics/mvdistinct.c
+++ b/src/backend/statistics/mvdistinct.c
@@ -110,7 +110,7 @@ statext_ndistinct_build(double totalrows, StatsBuildData *data)
 			MVNDistinctItem *item = &result->items[itemcnt];
 			int			j;
 
-			item->attributes = palloc(sizeof(AttrNumber) * k);
+			item->attributes = palloc_array(AttrNumber, k);
 			item->nattributes = k;
 
 			/* translate the indexes to attnums */
@@ -359,9 +359,9 @@ ndistinct_for_combination(double totalrows, StatsBuildData *data,
 	 * using the specified column combination as dimensions.  We could try to
 	 * sort in place, but it'd probably be more complex and bug-prone.
 	 */
-	items = (SortItem *) palloc(numrows * sizeof(SortItem));
-	values = (Datum *) palloc0(sizeof(Datum) * numrows * k);
-	isnull = (bool *) palloc0(sizeof(bool) * numrows * k);
+	items = palloc_array(SortItem, numrows);
+	values = palloc0_array(Datum, numrows * k);
+	isnull = palloc0_array(bool, numrows * k);
 
 	for (i = 0; i < numrows; i++)
 	{
@@ -508,12 +508,12 @@ generator_init(int n, int k)
 	Assert((n >= k) && (k > 0));
 
 	/* allocate the generator state as a single chunk of memory */
-	state = (CombinationGenerator *) palloc(sizeof(CombinationGenerator));
+	state = palloc_object(CombinationGenerator);
 
 	state->ncombinations = n_choose_k(n, k);
 
 	/* pre-allocate space for all combinations */
-	state->combinations = (int *) palloc(sizeof(int) * k * state->ncombinations);
+	state->combinations = palloc_array(int, k * state->ncombinations);
 
 	state->current = 0;
 	state->k = k;
@@ -606,7 +606,7 @@ generate_combinations_recurse(CombinationGenerator *state,
 static void
 generate_combinations(CombinationGenerator *state)
 {
-	int		   *current = (int *) palloc0(sizeof(int) * state->k);
+	int		   *current = palloc0_array(int, state->k);
 
 	generate_combinations_recurse(state, 0, 0, current);
 
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 327ddb7adc8..b73a8ea5efe 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -4676,7 +4676,7 @@ DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
 	if (nlocators == 0)
 		return;
 
-	rels = palloc(sizeof(SMgrRelation) * nlocators);	/* non-local relations */
+	rels = palloc_array(SMgrRelation, nlocators);	/* non-local relations */
 
 	/* If it's a local relation, it's localbuf.c's problem. */
 	for (i = 0; i < nlocators; i++)
@@ -4705,7 +4705,7 @@ DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
 	 * forks.
 	 */
 	block = (BlockNumber (*)[MAX_FORKNUM + 1])
-		palloc(sizeof(BlockNumber) * n * (MAX_FORKNUM + 1));
+		palloc_array(BlockNumber, n * (MAX_FORKNUM + 1));
 
 	/*
 	 * We can avoid scanning the entire buffer pool if we know the exact size
@@ -4758,7 +4758,7 @@ DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
 	}
 
 	pfree(block);
-	locators = palloc(sizeof(RelFileLocator) * n);	/* non-local relations */
+	locators = palloc_array(RelFileLocator, n);	/* non-local relations */
 	for (i = 0; i < n; i++)
 		locators[i] = rels[i]->smgr_rlocator.locator;
 
@@ -5037,7 +5037,7 @@ FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels)
 		return;
 
 	/* fill-in array for qsort */
-	srels = palloc(sizeof(SMgrSortArray) * nrels);
+	srels = palloc_array(SMgrSortArray, nrels);
 
 	for (i = 0; i < nrels; i++)
 	{
diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c
index 366d70d38a1..4e520065ae0 100644
--- a/src/backend/storage/file/buffile.c
+++ b/src/backend/storage/file/buffile.c
@@ -117,7 +117,7 @@ static File MakeNewFileSetSegment(BufFile *buffile, int segment);
 static BufFile *
 makeBufFileCommon(int nfiles)
 {
-	BufFile    *file = (BufFile *) palloc(sizeof(BufFile));
+	BufFile    *file = palloc_object(BufFile);
 
 	file->numFiles = nfiles;
 	file->isInterXact = false;
@@ -140,7 +140,7 @@ makeBufFile(File firstfile)
 {
 	BufFile    *file = makeBufFileCommon(1);
 
-	file->files = (File *) palloc(sizeof(File));
+	file->files = palloc_object(File);
 	file->files[0] = firstfile;
 	file->readOnly = false;
 	file->fileset = NULL;
@@ -271,7 +271,7 @@ BufFileCreateFileSet(FileSet *fileset, const char *name)
 	file = makeBufFileCommon(1);
 	file->fileset = fileset;
 	file->name = pstrdup(name);
-	file->files = (File *) palloc(sizeof(File));
+	file->files = palloc_object(File);
 	file->files[0] = MakeNewFileSetSegment(file, 0);
 	file->readOnly = false;
 
@@ -297,7 +297,7 @@ BufFileOpenFileSet(FileSet *fileset, const char *name, int mode,
 	File	   *files;
 	int			nfiles = 0;
 
-	files = palloc(sizeof(File) * capacity);
+	files = palloc_array(File, capacity);
 
 	/*
 	 * We don't know how many segments there are, so we'll probe the
@@ -309,7 +309,7 @@ BufFileOpenFileSet(FileSet *fileset, const char *name, int mode,
 		if (nfiles + 1 > capacity)
 		{
 			capacity *= 2;
-			files = repalloc(files, sizeof(File) * capacity);
+			files = repalloc_array(files, File, capacity);
 		}
 		/* Try to load a segment. */
 		FileSetSegmentName(segment_name, name, nfiles);
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 200f72c6e25..f3a1603204e 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -1162,7 +1162,7 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
 	 * Allocate a temporary array to avoid modifying the array passed as
 	 * argument.
 	 */
-	xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
+	xids = palloc_array(TransactionId, running->xcnt + running->subxcnt);
 
 	/*
 	 * Add to the temp array any xids which have not already completed.
@@ -3012,8 +3012,7 @@ GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
 	Assert(type != 0);
 
 	/* allocate what's certainly enough result space */
-	vxids = (VirtualTransactionId *)
-		palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
+	vxids = palloc_array(VirtualTransactionId, arrayP->maxProcs);
 
 	LWLockAcquire(ProcArrayLock, LW_SHARED);
 
@@ -3293,8 +3292,7 @@ GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0,
 	int			index;
 
 	/* allocate what's certainly enough result space */
-	vxids = (VirtualTransactionId *)
-		palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
+	vxids = palloc_array(VirtualTransactionId, arrayP->maxProcs);
 
 	LWLockAcquire(ProcArrayLock, LW_SHARED);
 
diff --git a/src/backend/storage/ipc/shm_mq.c b/src/backend/storage/ipc/shm_mq.c
index 2c79a649f46..9c888d3eb78 100644
--- a/src/backend/storage/ipc/shm_mq.c
+++ b/src/backend/storage/ipc/shm_mq.c
@@ -289,7 +289,7 @@ shm_mq_get_sender(shm_mq *mq)
 shm_mq_handle *
 shm_mq_attach(shm_mq *mq, dsm_segment *seg, BackgroundWorkerHandle *handle)
 {
-	shm_mq_handle *mqh = palloc(sizeof(shm_mq_handle));
+	shm_mq_handle *mqh = palloc_object(shm_mq_handle);
 
 	Assert(mq->mq_receiver == MyProc || mq->mq_sender == MyProc);
 	mqh->mqh_queue = mq;
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index ee3408df301..7b63c7dc90a 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -599,7 +599,7 @@ pg_get_shmem_allocations_numa(PG_FUNCTION_ARGS)
 	InitMaterializedSRF(fcinfo, 0);
 
 	max_nodes = pg_numa_get_max_node();
-	nodes = palloc(sizeof(Size) * (max_nodes + 1));
+	nodes = palloc_array(Size, max_nodes + 1);
 
 	/*
 	 * Shared memory allocations can vary in size and may not align with OS
@@ -624,8 +624,8 @@ pg_get_shmem_allocations_numa(PG_FUNCTION_ARGS)
 	 * them using only fraction of the total pages.
 	 */
 	shm_total_page_count = (ShmemSegHdr->totalsize / os_page_size) + 1;
-	page_ptrs = palloc0(sizeof(void *) * shm_total_page_count);
-	pages_status = palloc(sizeof(int) * shm_total_page_count);
+	page_ptrs = palloc0_array(void *, shm_total_page_count);
+	pages_status = palloc_array(int, shm_total_page_count);
 
 	if (firstNumaTouch)
 		elog(DEBUG1, "NUMA: page-faulting shared memory segments for proper NUMA readouts");
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 9cb78ead105..9015ba3caf7 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -3100,9 +3100,7 @@ GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
 								   (MaxBackends + max_prepared_xacts + 1));
 	}
 	else
-		vxids = (VirtualTransactionId *)
-			palloc0(sizeof(VirtualTransactionId) *
-					(MaxBackends + max_prepared_xacts + 1));
+		vxids = palloc0_array(VirtualTransactionId, (MaxBackends + max_prepared_xacts + 1));
 
 	/* Compute hash code and partition lock, and look up conflicting modes. */
 	hashcode = LockTagHashCode(locktag);
@@ -3801,12 +3799,12 @@ GetLockStatusData(void)
 	int			el;
 	int			i;
 
-	data = (LockData *) palloc(sizeof(LockData));
+	data = palloc_object(LockData);
 
 	/* Guess how much space we'll need. */
 	els = MaxBackends;
 	el = 0;
-	data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * els);
+	data->locks = palloc_array(LockInstanceData, els);
 
 	/*
 	 * First, we iterate through the per-backend fast-path arrays, locking
@@ -4001,7 +3999,7 @@ GetBlockerStatusData(int blocked_pid)
 	PGPROC	   *proc;
 	int			i;
 
-	data = (BlockedProcsData *) palloc(sizeof(BlockedProcsData));
+	data = palloc_object(BlockedProcsData);
 
 	/*
 	 * Guess how much space we'll need, and preallocate.  Most of the time
@@ -4011,9 +4009,9 @@ GetBlockerStatusData(int blocked_pid)
 	 */
 	data->nprocs = data->nlocks = data->npids = 0;
 	data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
-	data->procs = (BlockedProcData *) palloc(sizeof(BlockedProcData) * data->maxprocs);
-	data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * data->maxlocks);
-	data->waiter_pids = (int *) palloc(sizeof(int) * data->maxpids);
+	data->procs = palloc_array(BlockedProcData, data->maxprocs);
+	data->locks = palloc_array(LockInstanceData, data->maxlocks);
+	data->waiter_pids = palloc_array(int, data->maxpids);
 
 	/*
 	 * In order to search the ProcArray for blocked_pid and assume that that
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index bb807d8c9cd..4088107e2e2 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -1451,7 +1451,7 @@ GetPredicateLockStatusData(void)
 	HASH_SEQ_STATUS seqstat;
 	PREDICATELOCK *predlock;
 
-	data = (PredicateLockData *) palloc(sizeof(PredicateLockData));
+	data = palloc_object(PredicateLockData);
 
 	/*
 	 * To ensure consistency, take simultaneous locks on all partition locks
@@ -1464,10 +1464,8 @@ GetPredicateLockStatusData(void)
 	/* Get number of locks and allocate appropriately-sized arrays. */
 	els = hash_get_num_entries(PredicateLockHash);
 	data->nelements = els;
-	data->locktags = (PREDICATELOCKTARGETTAG *)
-		palloc(sizeof(PREDICATELOCKTARGETTAG) * els);
-	data->xacts = (SERIALIZABLEXACT *)
-		palloc(sizeof(SERIALIZABLEXACT) * els);
+	data->locktags = palloc_array(PREDICATELOCKTARGETTAG, els);
+	data->xacts = palloc_array(SERIALIZABLEXACT, els);
 
 
 	/* Scan through PredicateLockHash and copy contents */
diff --git a/src/backend/storage/smgr/bulk_write.c b/src/backend/storage/smgr/bulk_write.c
index b958be15716..d43c30da48e 100644
--- a/src/backend/storage/smgr/bulk_write.c
+++ b/src/backend/storage/smgr/bulk_write.c
@@ -101,7 +101,7 @@ smgr_bulk_start_smgr(SMgrRelation smgr, ForkNumber forknum, bool use_wal)
 {
 	BulkWriteState *state;
 
-	state = palloc(sizeof(BulkWriteState));
+	state = palloc_object(BulkWriteState);
 	state->smgr = smgr;
 	state->forknum = forknum;
 	state->use_wal = use_wal;
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index e3f335a8340..71bcdeb6601 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -1599,7 +1599,7 @@ DropRelationFiles(RelFileLocator *delrels, int ndelrels, bool isRedo)
 	SMgrRelation *srels;
 	int			i;
 
-	srels = palloc(sizeof(SMgrRelation) * ndelrels);
+	srels = palloc_array(SMgrRelation, ndelrels);
 	for (i = 0; i < ndelrels; i++)
 	{
 		SMgrRelation srel = smgropen(delrels[i], INVALID_PROC_NUMBER);
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index bce37a36d51..f9066ab8c49 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -561,7 +561,7 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
 	 * create an array which contains all relations to be dropped, and close
 	 * each relation's forks at the smgr level while at it
 	 */
-	rlocators = palloc(sizeof(RelFileLocatorBackend) * nrels);
+	rlocators = palloc_array(RelFileLocatorBackend, nrels);
 	for (i = 0; i < nrels; i++)
 	{
 		RelFileLocatorBackend rlocator = rels[i]->smgr_rlocator;
diff --git a/src/backend/storage/sync/sync.c b/src/backend/storage/sync/sync.c
index fc16db90133..9d4c5eae5f6 100644
--- a/src/backend/storage/sync/sync.c
+++ b/src/backend/storage/sync/sync.c
@@ -531,7 +531,7 @@ RememberSyncRequest(const FileTag *ftag, SyncRequestType type)
 		MemoryContext oldcxt = MemoryContextSwitchTo(pendingOpsCxt);
 		PendingUnlinkEntry *entry;
 
-		entry = palloc(sizeof(PendingUnlinkEntry));
+		entry = palloc_object(PendingUnlinkEntry);
 		entry->tag = *ftag;
 		entry->cycle_ctr = checkpoint_cycle_ctr;
 		entry->canceled = false;
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index fde78c55160..6dd64726f06 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -74,7 +74,7 @@ CreateQueryDesc(PlannedStmt *plannedstmt,
 				QueryEnvironment *queryEnv,
 				int instrument_options)
 {
-	QueryDesc  *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
+	QueryDesc  *qd = palloc_object(QueryDesc);
 
 	qd->operation = plannedstmt->commandType;	/* operation */
 	qd->plannedstmt = plannedstmt;	/* plan */
diff --git a/src/backend/tsearch/dict.c b/src/backend/tsearch/dict.c
index eb968858683..d0725108b80 100644
--- a/src/backend/tsearch/dict.c
+++ b/src/backend/tsearch/dict.c
@@ -61,7 +61,7 @@ ts_lexize(PG_FUNCTION_ARGS)
 	ptr = res;
 	while (ptr->lexeme)
 		ptr++;
-	da = (Datum *) palloc(sizeof(Datum) * (ptr - res));
+	da = (Datum *) palloc_array(Datum, ptr - res); 
 	ptr = res;
 	while (ptr->lexeme)
 	{
diff --git a/src/backend/tsearch/dict_ispell.c b/src/backend/tsearch/dict_ispell.c
index debfbf956cc..14e5da486e0 100644
--- a/src/backend/tsearch/dict_ispell.c
+++ b/src/backend/tsearch/dict_ispell.c
@@ -37,7 +37,7 @@ dispell_init(PG_FUNCTION_ARGS)
 				stoploaded = false;
 	ListCell   *l;
 
-	d = (DictISpell *) palloc0(sizeof(DictISpell));
+	d = palloc0_object(DictISpell);
 
 	NIStartBuild(&(d->obj));
 
diff --git a/src/backend/tsearch/dict_simple.c b/src/backend/tsearch/dict_simple.c
index 2c972fc0538..f6639ac7c97 100644
--- a/src/backend/tsearch/dict_simple.c
+++ b/src/backend/tsearch/dict_simple.c
@@ -31,7 +31,7 @@ Datum
 dsimple_init(PG_FUNCTION_ARGS)
 {
 	List	   *dictoptions = (List *) PG_GETARG_POINTER(0);
-	DictSimple *d = (DictSimple *) palloc0(sizeof(DictSimple));
+	DictSimple *d = palloc0_object(DictSimple);
 	bool		stoploaded = false,
 				acceptloaded = false;
 	ListCell   *l;
@@ -87,13 +87,13 @@ dsimple_lexize(PG_FUNCTION_ARGS)
 	{
 		/* reject as stopword */
 		pfree(txt);
-		res = palloc0(sizeof(TSLexeme) * 2);
+		res = palloc0_array(TSLexeme, 2);
 		PG_RETURN_POINTER(res);
 	}
 	else if (d->accept)
 	{
 		/* accept */
-		res = palloc0(sizeof(TSLexeme) * 2);
+		res = palloc0_array(TSLexeme, 2);
 		res[0].lexeme = txt;
 		PG_RETURN_POINTER(res);
 	}
diff --git a/src/backend/tsearch/dict_synonym.c b/src/backend/tsearch/dict_synonym.c
index c2773eb01ad..e076660b5ec 100644
--- a/src/backend/tsearch/dict_synonym.c
+++ b/src/backend/tsearch/dict_synonym.c
@@ -134,7 +134,7 @@ dsynonym_init(PG_FUNCTION_ARGS)
 				 errmsg("could not open synonym file \"%s\": %m",
 						filename)));
 
-	d = (DictSyn *) palloc0(sizeof(DictSyn));
+	d = palloc0_object(DictSyn);
 
 	while ((line = tsearch_readline(&trst)) != NULL)
 	{
@@ -169,12 +169,12 @@ dsynonym_init(PG_FUNCTION_ARGS)
 			if (d->len == 0)
 			{
 				d->len = 64;
-				d->syn = (Syn *) palloc(sizeof(Syn) * d->len);
+				d->syn = palloc_array(Syn, d->len);
 			}
 			else
 			{
 				d->len *= 2;
-				d->syn = (Syn *) repalloc(d->syn, sizeof(Syn) * d->len);
+				d->syn = repalloc_array(d->syn, Syn, d->len);
 			}
 		}
 
@@ -236,7 +236,7 @@ dsynonym_lexize(PG_FUNCTION_ARGS)
 	if (!found)
 		PG_RETURN_POINTER(NULL);
 
-	res = palloc0(sizeof(TSLexeme) * 2);
+	res = palloc0_array(TSLexeme, 2);
 	res[0].lexeme = pnstrdup(found->out, found->outlen);
 	res[0].flags = found->flags;
 
diff --git a/src/backend/tsearch/dict_thesaurus.c b/src/backend/tsearch/dict_thesaurus.c
index 1e6bbde1ca7..6a3d3369858 100644
--- a/src/backend/tsearch/dict_thesaurus.c
+++ b/src/backend/tsearch/dict_thesaurus.c
@@ -78,12 +78,12 @@ newLexeme(DictThesaurus *d, char *b, char *e, uint32 idsubst, uint16 posinsubst)
 		if (d->ntwrds == 0)
 		{
 			d->ntwrds = 16;
-			d->wrds = (TheLexeme *) palloc(sizeof(TheLexeme) * d->ntwrds);
+			d->wrds = palloc_array(TheLexeme, d->ntwrds);
 		}
 		else
 		{
 			d->ntwrds *= 2;
-			d->wrds = (TheLexeme *) repalloc(d->wrds, sizeof(TheLexeme) * d->ntwrds);
+			d->wrds = repalloc_array(d->wrds, TheLexeme, d->ntwrds);
 		}
 	}
 
@@ -95,7 +95,7 @@ newLexeme(DictThesaurus *d, char *b, char *e, uint32 idsubst, uint16 posinsubst)
 	memcpy(ptr->lexeme, b, e - b);
 	ptr->lexeme[e - b] = '\0';
 
-	ptr->entries = (LexemeInfo *) palloc(sizeof(LexemeInfo));
+	ptr->entries = palloc_object(LexemeInfo);
 
 	ptr->entries->nextentry = NULL;
 	ptr->entries->idsubst = idsubst;
@@ -118,12 +118,12 @@ addWrd(DictThesaurus *d, char *b, char *e, uint32 idsubst, uint16 nwrd, uint16 p
 			if (d->nsubst == 0)
 			{
 				d->nsubst = 16;
-				d->subst = (TheSubstitute *) palloc(sizeof(TheSubstitute) * d->nsubst);
+				d->subst = palloc_array(TheSubstitute, d->nsubst);
 			}
 			else
 			{
 				d->nsubst *= 2;
-				d->subst = (TheSubstitute *) repalloc(d->subst, sizeof(TheSubstitute) * d->nsubst);
+				d->subst = repalloc_array(d->subst, TheSubstitute, d->nsubst);
 			}
 		}
 	}
@@ -137,12 +137,12 @@ addWrd(DictThesaurus *d, char *b, char *e, uint32 idsubst, uint16 nwrd, uint16 p
 		if (ntres == 0)
 		{
 			ntres = 2;
-			ptr->res = (TSLexeme *) palloc(sizeof(TSLexeme) * ntres);
+			ptr->res = palloc_array(TSLexeme, ntres);
 		}
 		else
 		{
 			ntres *= 2;
-			ptr->res = (TSLexeme *) repalloc(ptr->res, sizeof(TSLexeme) * ntres);
+			ptr->res = repalloc_array(ptr->res, TSLexeme, ntres);
 		}
 	}
 
@@ -309,7 +309,7 @@ addCompiledLexeme(TheLexeme *newwrds, int *nnw, int *tnm, TSLexeme *lexeme, Lexe
 		newwrds = (TheLexeme *) repalloc(newwrds, sizeof(TheLexeme) * *tnm);
 	}
 
-	newwrds[*nnw].entries = (LexemeInfo *) palloc(sizeof(LexemeInfo));
+	newwrds[*nnw].entries = palloc_object(LexemeInfo);
 
 	if (lexeme && lexeme->lexeme)
 	{
@@ -394,7 +394,7 @@ compileTheLexeme(DictThesaurus *d)
 	int			i,
 				nnw = 0,
 				tnm = 16;
-	TheLexeme  *newwrds = (TheLexeme *) palloc(sizeof(TheLexeme) * tnm),
+	TheLexeme  *newwrds = palloc_array(TheLexeme, tnm),
 			   *ptrwrds;
 
 	for (i = 0; i < d->nwrds; i++)
@@ -511,7 +511,7 @@ compileTheSubstitute(DictThesaurus *d)
 				   *inptr;
 		int			n = 2;
 
-		outptr = d->subst[i].res = (TSLexeme *) palloc(sizeof(TSLexeme) * n);
+		outptr = d->subst[i].res = palloc_array(TSLexeme, n);
 		outptr->lexeme = NULL;
 		inptr = rem;
 
@@ -603,7 +603,7 @@ thesaurus_init(PG_FUNCTION_ARGS)
 	List	   *namelist;
 	ListCell   *l;
 
-	d = (DictThesaurus *) palloc0(sizeof(DictThesaurus));
+	d = palloc0_object(DictThesaurus);
 
 	foreach(l, dictoptions)
 	{
@@ -756,7 +756,7 @@ copyTSLexeme(TheSubstitute *ts)
 	TSLexeme   *res;
 	uint16		i;
 
-	res = (TSLexeme *) palloc(sizeof(TSLexeme) * (ts->reslen + 1));
+	res = palloc_array(TSLexeme, ts->reslen + 1);
 	for (i = 0; i < ts->reslen; i++)
 	{
 		res[i] = ts->res[i];
@@ -834,7 +834,7 @@ thesaurus_lexize(PG_FUNCTION_ARGS)
 				ptr++;
 			}
 
-			infos = (LexemeInfo **) palloc(sizeof(LexemeInfo *) * nlex);
+			infos = palloc_array(LexemeInfo *, nlex);
 			for (i = 0; i < nlex; i++)
 				if ((infos[i] = findTheLexeme(d, basevar[i].lexeme)) == NULL)
 					break;
diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c
index 146801885d7..79c333e6945 100644
--- a/src/backend/tsearch/spell.c
+++ b/src/backend/tsearch/spell.c
@@ -691,7 +691,7 @@ NIAddAffix(IspellDict *Conf, const char *flag, char flagflags, const char *mask,
 		else
 		{
 			Conf->maffixes = 16;
-			Conf->Affix = (AFFIX *) palloc(Conf->maffixes * sizeof(AFFIX));
+			Conf->Affix = palloc_array(AFFIX, Conf->maffixes);
 		}
 	}
 
@@ -737,7 +737,7 @@ NIAddAffix(IspellDict *Conf, const char *flag, char flagflags, const char *mask,
 		 * allocated in the dictionary's memory context, and will be freed
 		 * automatically when it is destroyed.
 		 */
-		Affix->reg.pregex = palloc(sizeof(regex_t));
+		Affix->reg.pregex = palloc_object(regex_t);
 		err = pg_regcomp(Affix->reg.pregex, wmask, wmasklen,
 						 REG_ADVANCED | REG_NOSUB,
 						 DEFAULT_COLLATION_OID);
@@ -1327,7 +1327,7 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename)
 				/* Also reserve place for empty flag set */
 				naffix++;
 
-				Conf->AffixData = (const char **) palloc0(naffix * sizeof(char *));
+				Conf->AffixData = (const char **) palloc0_array(char *, naffix);
 				Conf->lenAffixData = Conf->nAffixData = naffix;
 
 				/* Add empty flag set into AffixData */
@@ -1794,7 +1794,7 @@ NISortDictionary(IspellDict *Conf)
 		 * dictionary. Replace textual flag-field of Conf->Spell entries with
 		 * indexes into Conf->AffixData array.
 		 */
-		Conf->AffixData = (const char **) palloc0(naffix * sizeof(const char *));
+		Conf->AffixData = (const char **) palloc0_array(const char *, naffix);
 
 		curaffix = -1;
 		for (i = 0; i < Conf->nspell; i++)
@@ -1991,7 +1991,7 @@ NISortAffixes(IspellDict *Conf)
 	/* Store compound affixes in the Conf->CompoundAffix array */
 	if (Conf->naffixes > 1)
 		qsort(Conf->Affix, Conf->naffixes, sizeof(AFFIX), cmpaffix);
-	Conf->CompoundAffix = ptr = (CMPDAffix *) palloc(sizeof(CMPDAffix) * Conf->naffixes);
+	Conf->CompoundAffix = ptr = palloc_array(CMPDAffix, Conf->naffixes);
 	ptr->affix = NULL;
 
 	for (i = 0; i < Conf->naffixes; i++)
@@ -2147,7 +2147,7 @@ CheckAffix(const char *word, size_t len, AFFIX *Affix, int flagflags, char *neww
 
 		/* Convert data string to wide characters */
 		newword_len = strlen(newword);
-		data = (pg_wchar *) palloc((newword_len + 1) * sizeof(pg_wchar));
+		data = palloc_array(pg_wchar, newword_len + 1);
 		data_len = pg_mb2wchar_with_len(newword, data, newword_len);
 
 		if (pg_regexec(Affix->reg.pregex, data, data_len,
@@ -2197,7 +2197,7 @@ NormalizeSubWord(IspellDict *Conf, const char *word, int flag)
 
 	if (wrdlen > MAXNORMLEN)
 		return NULL;
-	cur = forms = (char **) palloc(MAX_NORM * sizeof(char *));
+	cur = forms = palloc_array(char *, MAX_NORM);
 	*cur = NULL;
 
 
@@ -2340,7 +2340,7 @@ CheckCompoundAffixes(CMPDAffix **ptr, const char *word, int len, bool CheckInPla
 static SplitVar *
 CopyVar(SplitVar *s, int makedup)
 {
-	SplitVar   *v = (SplitVar *) palloc(sizeof(SplitVar));
+	SplitVar   *v = palloc_object(SplitVar);
 
 	v->next = NULL;
 	if (s)
@@ -2348,7 +2348,7 @@ CopyVar(SplitVar *s, int makedup)
 		int			i;
 
 		v->lenstem = s->lenstem;
-		v->stem = (char **) palloc(sizeof(char *) * v->lenstem);
+		v->stem = palloc_array(char *, v->lenstem);
 		v->nstem = s->nstem;
 		for (i = 0; i < s->nstem; i++)
 			v->stem[i] = (makedup) ? pstrdup(s->stem[i]) : s->stem[i];
@@ -2356,7 +2356,7 @@ CopyVar(SplitVar *s, int makedup)
 	else
 	{
 		v->lenstem = 16;
-		v->stem = (char **) palloc(sizeof(char *) * v->lenstem);
+		v->stem = palloc_array(char *, v->lenstem);
 		v->nstem = 0;
 	}
 	return v;
@@ -2529,7 +2529,7 @@ static void
 addNorm(TSLexeme **lres, TSLexeme **lcur, char *word, int flags, uint16 NVariant)
 {
 	if (*lres == NULL)
-		*lcur = *lres = (TSLexeme *) palloc(MAX_NORM * sizeof(TSLexeme));
+		*lcur = *lres = palloc_array(TSLexeme, MAX_NORM);
 
 	if (*lcur - *lres < MAX_NORM - 1)
 	{
diff --git a/src/backend/tsearch/to_tsany.c b/src/backend/tsearch/to_tsany.c
index 4dfcc2cd3bd..b6efe108424 100644
--- a/src/backend/tsearch/to_tsany.c
+++ b/src/backend/tsearch/to_tsany.c
@@ -84,7 +84,7 @@ uniqueWORD(ParsedWord *a, int32 l)
 	{
 		tmppos = LIMITPOS(a->pos.pos);
 		a->alen = 2;
-		a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen);
+		a->pos.apos = palloc_array(uint16, a->alen);
 		a->pos.apos[0] = 1;
 		a->pos.apos[1] = tmppos;
 		return l;
@@ -103,7 +103,7 @@ uniqueWORD(ParsedWord *a, int32 l)
 	 */
 	tmppos = LIMITPOS(a->pos.pos);
 	a->alen = 2;
-	a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen);
+	a->pos.apos = palloc_array(uint16, a->alen);
 	a->pos.apos[0] = 1;
 	a->pos.apos[1] = tmppos;
 
@@ -123,7 +123,7 @@ uniqueWORD(ParsedWord *a, int32 l)
 			res->word = ptr->word;
 			tmppos = LIMITPOS(ptr->pos.pos);
 			res->alen = 2;
-			res->pos.apos = (uint16 *) palloc(sizeof(uint16) * res->alen);
+			res->pos.apos = palloc_array(uint16, res->alen);
 			res->pos.apos[0] = 1;
 			res->pos.apos[1] = tmppos;
 		}
@@ -141,7 +141,7 @@ uniqueWORD(ParsedWord *a, int32 l)
 				if (res->pos.apos[0] + 1 >= res->alen)
 				{
 					res->alen *= 2;
-					res->pos.apos = (uint16 *) repalloc(res->pos.apos, sizeof(uint16) * res->alen);
+					res->pos.apos = repalloc_array(res->pos.apos, uint16, res->alen);
 				}
 				if (res->pos.apos[0] == 0 || res->pos.apos[res->pos.apos[0]] != LIMITPOS(ptr->pos.pos))
 				{
@@ -255,7 +255,7 @@ to_tsvector_byid(PG_FUNCTION_ARGS)
 		prs.lenwords = MaxAllocSize / sizeof(ParsedWord);
 	prs.curwords = 0;
 	prs.pos = 0;
-	prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);
+	prs.words = palloc_array(ParsedWord, prs.lenwords);
 
 	parsetext(cfgId, &prs, VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
 
@@ -453,7 +453,7 @@ add_to_tsvector(void *_state, char *elem_value, int elem_len)
 		 * (parsetext() will realloc it bigger as needed.)
 		 */
 		prs->lenwords = 16;
-		prs->words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs->lenwords);
+		prs->words = palloc_array(ParsedWord, prs->lenwords);
 		prs->curwords = 0;
 		prs->pos = 0;
 	}
@@ -503,7 +503,7 @@ pushval_morph(Datum opaque, TSQueryParserState state, char *strval, int lenval,
 	prs.lenwords = 4;
 	prs.curwords = 0;
 	prs.pos = 0;
-	prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);
+	prs.words = palloc_array(ParsedWord, prs.lenwords);
 
 	parsetext(data->cfg_id, &prs, strval, lenval);
 
diff --git a/src/backend/tsearch/ts_parse.c b/src/backend/tsearch/ts_parse.c
index cba421892bf..6eebff6c467 100644
--- a/src/backend/tsearch/ts_parse.c
+++ b/src/backend/tsearch/ts_parse.c
@@ -99,7 +99,7 @@ LPLRemoveHead(ListParsedLex *list)
 static void
 LexizeAddLemm(LexizeData *ld, int type, char *lemm, int lenlemm)
 {
-	ParsedLex  *newpl = (ParsedLex *) palloc(sizeof(ParsedLex));
+	ParsedLex  *newpl = palloc_object(ParsedLex);
 
 	newpl->type = type;
 	newpl->lemm = lemm;
diff --git a/src/backend/tsearch/ts_selfuncs.c b/src/backend/tsearch/ts_selfuncs.c
index fb367ad74d2..63a6ecd3e2a 100644
--- a/src/backend/tsearch/ts_selfuncs.c
+++ b/src/backend/tsearch/ts_selfuncs.c
@@ -226,7 +226,7 @@ mcelem_tsquery_selec(TSQuery query, const Datum *mcelem, int nmcelem,
 	/*
 	 * Transpose the data into a single array so we can use bsearch().
 	 */
-	lookup = (TextFreq *) palloc(sizeof(TextFreq) * nmcelem);
+	lookup = palloc_array(TextFreq, nmcelem);
 	for (i = 0; i < nmcelem; i++)
 	{
 		/*
diff --git a/src/backend/tsearch/ts_typanalyze.c b/src/backend/tsearch/ts_typanalyze.c
index 93aab00a3ca..9b8b0995ab7 100644
--- a/src/backend/tsearch/ts_typanalyze.c
+++ b/src/backend/tsearch/ts_typanalyze.c
@@ -320,7 +320,7 @@ compute_tsvector_stats(VacAttrStats *stats,
 		cutoff_freq = 9 * lexeme_no / bucket_width;
 
 		i = hash_get_num_entries(lexemes_tab);	/* surely enough space */
-		sort_table = (TrackItem **) palloc(sizeof(TrackItem *) * i);
+		sort_table = palloc_array(TrackItem *, i);
 
 		hash_seq_init(&scan_status, lexemes_tab);
 		track_len = 0;
@@ -412,8 +412,8 @@ compute_tsvector_stats(VacAttrStats *stats,
 			 * create that for a tsvector column, since null elements aren't
 			 * possible.)
 			 */
-			mcelem_values = (Datum *) palloc(num_mcelem * sizeof(Datum));
-			mcelem_freqs = (float4 *) palloc((num_mcelem + 2) * sizeof(float4));
+			mcelem_values = palloc_array(Datum, num_mcelem);
+			mcelem_freqs = palloc_array(float4, num_mcelem + 2);
 
 			/*
 			 * See comments above about use of nonnull_cnt as the divisor for
diff --git a/src/backend/tsearch/ts_utils.c b/src/backend/tsearch/ts_utils.c
index 0b4a5786644..647e4649644 100644
--- a/src/backend/tsearch/ts_utils.c
+++ b/src/backend/tsearch/ts_utils.c
@@ -105,12 +105,12 @@ readstoplist(const char *fname, StopList *s, char *(*wordop) (const char *, size
 				if (reallen == 0)
 				{
 					reallen = 64;
-					stop = (char **) palloc(sizeof(char *) * reallen);
+					stop = palloc_array(char *, reallen);
 				}
 				else
 				{
 					reallen *= 2;
-					stop = (char **) repalloc(stop, sizeof(char *) * reallen);
+					stop = repalloc_array(stop, char *, reallen);
 				}
 			}
 
diff --git a/src/backend/tsearch/wparser.c b/src/backend/tsearch/wparser.c
index 55171aa8da1..9e53f57324f 100644
--- a/src/backend/tsearch/wparser.c
+++ b/src/backend/tsearch/wparser.c
@@ -58,7 +58,7 @@ tt_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
 
 	oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-	st = (TSTokenTypeStorage *) palloc(sizeof(TSTokenTypeStorage));
+	st = palloc_object(TSTokenTypeStorage);
 	st->cur = 0;
 	/* lextype takes one dummy argument */
 	st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
@@ -173,10 +173,10 @@ prs_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
 
 	oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-	st = (PrsStorage *) palloc(sizeof(PrsStorage));
+	st = palloc_object(PrsStorage);
 	st->cur = 0;
 	st->len = 16;
-	st->list = (LexemeEntry *) palloc(sizeof(LexemeEntry) * st->len);
+	st->list = palloc_array(LexemeEntry, st->len);
 
 	prsdata = DatumGetPointer(FunctionCall2(&prs->prsstart,
 											PointerGetDatum(VARDATA_ANY(txt)),
@@ -307,7 +307,7 @@ ts_headline_byid_opt(PG_FUNCTION_ARGS)
 
 	memset(&prs, 0, sizeof(HeadlineParsedText));
 	prs.lenwords = 32;
-	prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
+	prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
 
 	hlparsetext(cfg->cfgId, &prs, query,
 				VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
@@ -373,11 +373,11 @@ ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
 	Jsonb	   *out;
 	JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
 	HeadlineParsedText prs;
-	HeadlineJsonState *state = palloc0(sizeof(HeadlineJsonState));
+	HeadlineJsonState *state = palloc0_object(HeadlineJsonState);
 
 	memset(&prs, 0, sizeof(HeadlineParsedText));
 	prs.lenwords = 32;
-	prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
+	prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
 
 	state->prs = &prs;
 	state->cfg = lookup_ts_config_cache(tsconfig);
@@ -450,11 +450,11 @@ ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
 	JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
 
 	HeadlineParsedText prs;
-	HeadlineJsonState *state = palloc0(sizeof(HeadlineJsonState));
+	HeadlineJsonState *state = palloc0_object(HeadlineJsonState);
 
 	memset(&prs, 0, sizeof(HeadlineParsedText));
 	prs.lenwords = 32;
-	prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
+	prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
 
 	state->prs = &prs;
 	state->cfg = lookup_ts_config_cache(tsconfig);
diff --git a/src/backend/tsearch/wparser_def.c b/src/backend/tsearch/wparser_def.c
index 251a2ae6563..9fbeab47545 100644
--- a/src/backend/tsearch/wparser_def.c
+++ b/src/backend/tsearch/wparser_def.c
@@ -269,7 +269,7 @@ static bool TParserGet(TParser *prs);
 static TParserPosition *
 newTParserPosition(TParserPosition *prev)
 {
-	TParserPosition *res = (TParserPosition *) palloc(sizeof(TParserPosition));
+	TParserPosition *res = palloc_object(TParserPosition);
 
 	if (prev)
 		memcpy(res, prev, sizeof(TParserPosition));
@@ -286,12 +286,12 @@ newTParserPosition(TParserPosition *prev)
 static TParser *
 TParserInit(char *str, int len)
 {
-	TParser    *prs = (TParser *) palloc0(sizeof(TParser));
+	TParser    *prs = palloc0_object(TParser);
 
 	prs->charmaxlen = pg_database_encoding_max_length();
 	prs->str = str;
 	prs->lenstr = len;
-	prs->pgwstr = (pg_wchar *) palloc(sizeof(pg_wchar) * (prs->lenstr + 1));
+	prs->pgwstr = palloc_array(pg_wchar, prs->lenstr + 1);
 	pg_mb2wchar_with_len(prs->str, prs->pgwstr, prs->lenstr);
 
 	prs->state = newTParserPosition(NULL);
@@ -318,7 +318,7 @@ TParserInit(char *str, int len)
 static TParser *
 TParserCopyInit(const TParser *orig)
 {
-	TParser    *prs = (TParser *) palloc0(sizeof(TParser));
+	TParser    *prs = palloc0_object(TParser);
 
 	prs->charmaxlen = orig->charmaxlen;
 	prs->str = orig->str + orig->state->posbyte;
@@ -1832,7 +1832,7 @@ TParserGet(TParser *prs)
 Datum
 prsd_lextype(PG_FUNCTION_ARGS)
 {
-	LexDescr   *descr = (LexDescr *) palloc(sizeof(LexDescr) * (LASTNUM + 1));
+	LexDescr   *descr = palloc_array(LexDescr, LASTNUM + 1);
 	int			i;
 
 	for (i = 1; i <= LASTNUM; i++)
@@ -1949,7 +1949,7 @@ checkcondition_HL(void *opaque, QueryOperand *val, ExecPhraseData *data)
 
 			if (!data->pos)
 			{
-				data->pos = palloc(sizeof(WordEntryPos) * checkval->len);
+				data->pos = palloc_array(WordEntryPos, checkval->len);
 				data->allocated = true;
 				data->npos = 1;
 				data->pos[0] = checkval->words[i].pos;
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index 1de477cbeeb..b90754f8578 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -514,7 +514,7 @@ find_tabstat_entry(Oid rel_id)
 	}
 
 	tabentry = (PgStat_TableStatus *) entry_ref->pending;
-	tablestatus = palloc(sizeof(PgStat_TableStatus));
+	tablestatus = palloc_object(PgStat_TableStatus);
 	*tablestatus = *tabentry;
 
 	/*
diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c
index d9b8f34a355..e81b4f96a24 100644
--- a/src/backend/utils/activity/wait_event.c
+++ b/src/backend/utils/activity/wait_event.c
@@ -317,7 +317,7 @@ GetWaitEventCustomNames(uint32 classId, int *nwaitevents)
 	els = hash_get_num_entries(WaitEventCustomHashByName);
 
 	/* Allocate enough space for all entries */
-	waiteventnames = palloc(els * sizeof(char *));
+	waiteventnames = palloc_array(char *, els);
 
 	/* Now scan the hash table to copy the data */
 	hash_seq_init(&hash_seq, WaitEventCustomHashByName);
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index fbcd64a2609..05d48412f82 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -618,7 +618,7 @@ aclitemin(PG_FUNCTION_ARGS)
 	Node	   *escontext = fcinfo->context;
 	AclItem    *aip;
 
-	aip = (AclItem *) palloc(sizeof(AclItem));
+	aip = palloc_object(AclItem);
 
 	s = aclparse(s, aip, escontext);
 	if (s == NULL)
@@ -1661,7 +1661,7 @@ makeaclitem(PG_FUNCTION_ARGS)
 
 	priv = convert_any_priv_string(privtext, any_priv_map);
 
-	result = (AclItem *) palloc(sizeof(AclItem));
+	result = palloc_object(AclItem);
 
 	result->ai_grantee = grantee;
 	result->ai_grantor = grantor;
@@ -1821,7 +1821,7 @@ aclexplode(PG_FUNCTION_ARGS)
 		funcctx->tuple_desc = BlessTupleDesc(tupdesc);
 
 		/* allocate memory for user context */
-		idx = (int *) palloc(sizeof(int[2]));
+		idx = palloc_array(int, 2);
 		idx[0] = 0;				/* ACL array item index */
 		idx[1] = -1;			/* privilege type counter */
 		funcctx->user_fctx = idx;
diff --git a/src/backend/utils/adt/array_selfuncs.c b/src/backend/utils/adt/array_selfuncs.c
index 4dab35b0057..cd201461c17 100644
--- a/src/backend/utils/adt/array_selfuncs.c
+++ b/src/backend/utils/adt/array_selfuncs.c
@@ -759,7 +759,7 @@ mcelem_array_contained_selec(const Datum *mcelem, int nmcelem,
 	 * elem_selec is array of estimated frequencies for elements in the
 	 * constant.
 	 */
-	elem_selec = (float *) palloc(sizeof(float) * nitems);
+	elem_selec = palloc_array(float, nitems);
 
 	/* Scan mcelem and array in parallel. */
 	mcelem_index = 0;
@@ -936,7 +936,7 @@ calc_hist(const float4 *hist, int nhist, int n)
 				next_interval;
 	float		frac;
 
-	hist_part = (float *) palloc((n + 1) * sizeof(float));
+	hist_part = palloc_array(float, n + 1);
 
 	/*
 	 * frac is a probability contribution for each interval between histogram
@@ -1028,8 +1028,8 @@ calc_distr(const float *p, int n, int m, float rest)
 	 * Since we return only the last row of the matrix and need only the
 	 * current and previous row for calculations, allocate two rows.
 	 */
-	row = (float *) palloc((m + 1) * sizeof(float));
-	prev_row = (float *) palloc((m + 1) * sizeof(float));
+	row = palloc_array(float, m + 1);
+	prev_row = palloc_array(float, m + 1);
 
 	/* M[0,0] = 1 */
 	row[0] = 1.0f;
diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c
index 560b27f3ca7..61aedd31ff1 100644
--- a/src/backend/utils/adt/array_typanalyze.c
+++ b/src/backend/utils/adt/array_typanalyze.c
@@ -132,7 +132,7 @@ array_typanalyze(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(true);
 
 	/* Store our findings for use by compute_array_stats() */
-	extra_data = (ArrayAnalyzeExtraData *) palloc(sizeof(ArrayAnalyzeExtraData));
+	extra_data = palloc_object(ArrayAnalyzeExtraData);
 	extra_data->type_id = typentry->type_id;
 	extra_data->eq_opr = typentry->eq_opr;
 	extra_data->coll_id = stats->attrcollid;	/* collation we should use */
@@ -469,7 +469,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 		cutoff_freq = 9 * element_no / bucket_width;
 
 		i = hash_get_num_entries(elements_tab); /* surely enough space */
-		sort_table = (TrackItem **) palloc(sizeof(TrackItem *) * i);
+		sort_table = palloc_array(TrackItem *, i);
 
 		hash_seq_init(&scan_status, elements_tab);
 		track_len = 0;
@@ -606,8 +606,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 			 * Create an array of DECountItem pointers, and sort them into
 			 * increasing count order.
 			 */
-			sorted_count_items = (DECountItem **)
-				palloc(sizeof(DECountItem *) * count_items_count);
+			sorted_count_items = palloc_array(DECountItem *, count_items_count);
 			hash_seq_init(&scan_status, count_tab);
 			j = 0;
 			while ((count_item = (DECountItem *) hash_seq_search(&scan_status)) != NULL)
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index 8eb342e3382..c01bf466121 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -433,8 +433,8 @@ array_cat(PG_FUNCTION_ARGS)
 		 * themselves) of the input argument arrays
 		 */
 		ndims = ndims1;
-		dims = (int *) palloc(ndims * sizeof(int));
-		lbs = (int *) palloc(ndims * sizeof(int));
+		dims = palloc_array(int, ndims);
+		lbs = palloc_array(int, ndims);
 
 		dims[0] = dims1[0] + dims2[0];
 		lbs[0] = lbs1[0];
@@ -459,8 +459,8 @@ array_cat(PG_FUNCTION_ARGS)
 		 * the first argument inserted at the front of the outer dimension
 		 */
 		ndims = ndims2;
-		dims = (int *) palloc(ndims * sizeof(int));
-		lbs = (int *) palloc(ndims * sizeof(int));
+		dims = palloc_array(int, ndims);
+		lbs = palloc_array(int, ndims);
 		memcpy(dims, dims2, ndims * sizeof(int));
 		memcpy(lbs, lbs2, ndims * sizeof(int));
 
@@ -487,8 +487,8 @@ array_cat(PG_FUNCTION_ARGS)
 		 * second argument appended to the end of the outer dimension
 		 */
 		ndims = ndims1;
-		dims = (int *) palloc(ndims * sizeof(int));
-		lbs = (int *) palloc(ndims * sizeof(int));
+		dims = palloc_array(int, ndims);
+		lbs = palloc_array(int, ndims);
 		memcpy(dims, dims1, ndims * sizeof(int));
 		memcpy(lbs, lbs1, ndims * sizeof(int));
 
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index a464349ee33..4095d449f32 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -3582,7 +3582,7 @@ construct_empty_array(Oid elmtype)
 {
 	ArrayType  *result;
 
-	result = (ArrayType *) palloc0(sizeof(ArrayType));
+	result = (ArrayType *) palloc0_object(ArrayType);
 	SET_VARSIZE(result, sizeof(ArrayType));
 	result->ndim = 0;
 	result->dataoffset = 0;
@@ -3647,7 +3647,7 @@ deconstruct_array(const ArrayType *array,
 	nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
 	*elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
 	if (nullsp)
-		*nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
+		*nullsp = nulls = (bool *) palloc0_array(bool, nelems);
 	else
 		nulls = NULL;
 	*nelemsp = nelems;
@@ -4209,7 +4209,7 @@ hash_array(PG_FUNCTION_ARGS)
 			 * modify typentry, since that points directly into the type
 			 * cache.
 			 */
-			record_typentry = palloc0(sizeof(*record_typentry));
+			record_typentry = palloc0_object(TypeCacheEntry);
 			record_typentry->type_id = element_type;
 
 			/* fill in what we need below */
@@ -4597,7 +4597,7 @@ arraycontained(PG_FUNCTION_ARGS)
 ArrayIterator
 array_create_iterator(ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
 {
-	ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
+	ArrayIterator iterator = palloc0_object(ArrayIteratorData);
 
 	/*
 	 * Sanity-check inputs --- caller should have got this right already
@@ -5944,7 +5944,7 @@ generate_subscripts(PG_FUNCTION_ARGS)
 		 * switch to memory context appropriate for multiple function calls
 		 */
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
-		fctx = (generate_subscripts_fctx *) palloc(sizeof(generate_subscripts_fctx));
+		fctx = palloc_object(generate_subscripts_fctx);
 
 		lb = AARR_LBOUND(v);
 		dimv = AARR_DIMS(v);
@@ -6291,7 +6291,7 @@ array_unnest(PG_FUNCTION_ARGS)
 		arr = PG_GETARG_ANY_ARRAY_P(0);
 
 		/* allocate memory for user context */
-		fctx = (array_unnest_fctx *) palloc(sizeof(array_unnest_fctx));
+		fctx = palloc_object(array_unnest_fctx);
 
 		/* initialize state */
 		array_iter_setup(&fctx->iter, arr);
diff --git a/src/backend/utils/adt/arraysubs.c b/src/backend/utils/adt/arraysubs.c
index 2940fb8e8d7..71ca181fba8 100644
--- a/src/backend/utils/adt/arraysubs.c
+++ b/src/backend/utils/adt/arraysubs.c
@@ -497,7 +497,7 @@ array_exec_setup(const SubscriptingRef *sbsref,
 	/*
 	 * Allocate type-specific workspace.
 	 */
-	workspace = (ArraySubWorkspace *) palloc(sizeof(ArraySubWorkspace));
+	workspace = palloc_object(ArraySubWorkspace);
 	sbsrefstate->workspace = workspace;
 
 	/*
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 344f58b92f7..3d747fc856e 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -357,7 +357,7 @@ GetSQLCurrentTime(int32 typmod)
 
 	GetCurrentTimeUsec(tm, &fsec, &tz);
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 	tm2timetz(tm, fsec, tz, result);
 	AdjustTimeForTypmod(&(result->time), typmod);
 	return result;
@@ -2138,7 +2138,7 @@ time_interval(PG_FUNCTION_ARGS)
 	TimeADT		time = PG_GETARG_TIMEADT(0);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	result->time = time;
 	result->day = 0;
@@ -2183,7 +2183,7 @@ time_mi_time(PG_FUNCTION_ARGS)
 	TimeADT		time2 = PG_GETARG_TIMEADT(1);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	result->month = 0;
 	result->day = 0;
@@ -2450,7 +2450,7 @@ timetz_in(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 	}
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 	tm2timetz(tm, fsec, tz, result);
 	AdjustTimeForTypmod(&(result->time), typmod);
 
@@ -2489,7 +2489,7 @@ timetz_recv(PG_FUNCTION_ARGS)
 	int32		typmod = PG_GETARG_INT32(2);
 	TimeTzADT  *result;
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = pq_getmsgint64(buf);
 
@@ -2575,7 +2575,7 @@ timetz_scale(PG_FUNCTION_ARGS)
 	int32		typmod = PG_GETARG_INT32(1);
 	TimeTzADT  *result;
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = time->time;
 	result->zone = time->zone;
@@ -2751,7 +2751,7 @@ timetz_pl_interval(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("cannot add infinite interval to time")));
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = time->time + span->time;
 	result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
@@ -2778,7 +2778,7 @@ timetz_mi_interval(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("cannot subtract infinite interval from time")));
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = time->time - span->time;
 	result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
@@ -2985,7 +2985,7 @@ time_timetz(PG_FUNCTION_ARGS)
 	time2tm(time, tm, &fsec);
 	tz = DetermineTimeZoneOffset(tm, session_timezone);
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = time;
 	result->zone = tz;
@@ -3015,7 +3015,7 @@ timestamptz_timetz(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("timestamp out of range")));
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	tm2timetz(tm, fsec, tz, result);
 
@@ -3248,7 +3248,7 @@ timetz_zone(PG_FUNCTION_ARGS)
 					 errmsg("timestamp out of range")));
 	}
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
 	/* C99 modulo has the wrong sign convention for negative input */
@@ -3289,7 +3289,7 @@ timetz_izone(PG_FUNCTION_ARGS)
 
 	tz = -(zone->time / USECS_PER_SEC);
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
 	/* C99 modulo has the wrong sign convention for negative input */
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 680fee2a844..e3a099eaa67 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -5152,7 +5152,7 @@ pg_timezone_abbrevs_zone(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		pindex = (int *) palloc(sizeof(int));
+		pindex = palloc_object(int);
 		*pindex = 0;
 		funcctx->user_fctx = pindex;
 
@@ -5187,7 +5187,7 @@ pg_timezone_abbrevs_zone(PG_FUNCTION_ARGS)
 		/* Convert offset (in seconds) to an interval; can't overflow */
 		MemSet(&itm_in, 0, sizeof(struct pg_itm_in));
 		itm_in.tm_usec = (int64) gmtoff * USECS_PER_SEC;
-		resInterval = (Interval *) palloc(sizeof(Interval));
+		resInterval = palloc_object(Interval);
 		(void) itmin2interval(&itm_in, resInterval);
 		values[1] = IntervalPGetDatum(resInterval);
 
@@ -5239,7 +5239,7 @@ pg_timezone_abbrevs_abbrevs(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		pindex = (int *) palloc(sizeof(int));
+		pindex = palloc_object(int);
 		*pindex = 0;
 		funcctx->user_fctx = pindex;
 
@@ -5310,7 +5310,7 @@ pg_timezone_abbrevs_abbrevs(PG_FUNCTION_ARGS)
 	/* Convert offset (in seconds) to an interval; can't overflow */
 	MemSet(&itm_in, 0, sizeof(struct pg_itm_in));
 	itm_in.tm_usec = (int64) gmtoffset * USECS_PER_SEC;
-	resInterval = (Interval *) palloc(sizeof(Interval));
+	resInterval = palloc_object(Interval);
 	(void) itmin2interval(&itm_in, resInterval);
 	values[1] = IntervalPGetDatum(resInterval);
 
@@ -5378,7 +5378,7 @@ pg_timezone_names(PG_FUNCTION_ARGS)
 		/* Convert tzoff to an interval; can't overflow */
 		MemSet(&itm_in, 0, sizeof(struct pg_itm_in));
 		itm_in.tm_usec = (int64) -tzoff * USECS_PER_SEC;
-		resInterval = (Interval *) palloc(sizeof(Interval));
+		resInterval = palloc_object(Interval);
 		(void) itmin2interval(&itm_in, resInterval);
 		values[2] = IntervalPGetDatum(resInterval);
 
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 5bfeda2ffde..a9fa209e345 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -4263,7 +4263,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 	{
 		if (flags & DCH_ZONED)
 		{
-			TimeTzADT  *result = palloc(sizeof(TimeTzADT));
+			TimeTzADT  *result = palloc_object(TimeTzADT);
 
 			if (ftz.has_tz)
 			{
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 377a1b3f3ad..2537d00ff87 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -423,7 +423,7 @@ box_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	Node	   *escontext = fcinfo->context;
-	BOX		   *box = (BOX *) palloc(sizeof(BOX));
+	BOX		   *box = palloc_object(BOX);
 	bool		isopen;
 	float8		x,
 				y;
@@ -470,7 +470,7 @@ box_recv(PG_FUNCTION_ARGS)
 	float8		x,
 				y;
 
-	box = (BOX *) palloc(sizeof(BOX));
+	box = palloc_object(BOX);
 
 	box->high.x = pq_getmsgfloat8(buf);
 	box->high.y = pq_getmsgfloat8(buf);
@@ -849,7 +849,7 @@ Datum
 box_center(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
-	Point	   *result = (Point *) palloc(sizeof(Point));
+	Point	   *result = palloc_object(Point);
 
 	box_cn(result, box);
 
@@ -914,7 +914,7 @@ box_intersect(PG_FUNCTION_ARGS)
 	if (!box_ov(box1, box2))
 		PG_RETURN_NULL();
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	result->high.x = float8_min(box1->high.x, box2->high.x);
 	result->low.x = float8_max(box1->low.x, box2->low.x);
@@ -933,7 +933,7 @@ Datum
 box_diagonal(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
-	LSEG	   *result = (LSEG *) palloc(sizeof(LSEG));
+	LSEG	   *result = palloc_object(LSEG);
 
 	statlseg_construct(result, &box->high, &box->low);
 
@@ -980,7 +980,7 @@ line_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	Node	   *escontext = fcinfo->context;
-	LINE	   *line = (LINE *) palloc(sizeof(LINE));
+	LINE	   *line = palloc_object(LINE);
 	LSEG		lseg;
 	bool		isopen;
 	char	   *s;
@@ -1040,7 +1040,7 @@ line_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	LINE	   *line;
 
-	line = (LINE *) palloc(sizeof(LINE));
+	line = palloc_object(LINE);
 
 	line->A = pq_getmsgfloat8(buf);
 	line->B = pq_getmsgfloat8(buf);
@@ -1116,7 +1116,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
-	LINE	   *result = (LINE *) palloc(sizeof(LINE));
+	LINE	   *result = palloc_object(LINE);
 
 	if (point_eq_point(pt1, pt2))
 		ereport(ERROR,
@@ -1289,7 +1289,7 @@ line_interpt(PG_FUNCTION_ARGS)
 	LINE	   *l2 = PG_GETARG_LINE_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (!line_interpt_line(result, l1, l2))
 		PG_RETURN_NULL();
@@ -1831,7 +1831,7 @@ Datum
 point_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
-	Point	   *point = (Point *) palloc(sizeof(Point));
+	Point	   *point = palloc_object(Point);
 
 	/* Ignore failure from pair_decode, since our return value won't matter */
 	pair_decode(str, &point->x, &point->y, NULL, "point", str, fcinfo->context);
@@ -1855,7 +1855,7 @@ point_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	Point	   *point;
 
-	point = (Point *) palloc(sizeof(Point));
+	point = palloc_object(Point);
 	point->x = pq_getmsgfloat8(buf);
 	point->y = pq_getmsgfloat8(buf);
 	PG_RETURN_POINT_P(point);
@@ -2066,7 +2066,7 @@ lseg_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	Node	   *escontext = fcinfo->context;
-	LSEG	   *lseg = (LSEG *) palloc(sizeof(LSEG));
+	LSEG	   *lseg = palloc_object(LSEG);
 	bool		isopen;
 
 	if (!path_decode(str, true, 2, &lseg->p[0], &isopen, NULL, "lseg", str,
@@ -2094,7 +2094,7 @@ lseg_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	LSEG	   *lseg;
 
-	lseg = (LSEG *) palloc(sizeof(LSEG));
+	lseg = palloc_object(LSEG);
 
 	lseg->p[0].x = pq_getmsgfloat8(buf);
 	lseg->p[0].y = pq_getmsgfloat8(buf);
@@ -2130,7 +2130,7 @@ lseg_construct(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
-	LSEG	   *result = (LSEG *) palloc(sizeof(LSEG));
+	LSEG	   *result = palloc_object(LSEG);
 
 	statlseg_construct(result, pt1, pt2);
 
@@ -2318,7 +2318,7 @@ lseg_center(PG_FUNCTION_ARGS)
 	LSEG	   *lseg = PG_GETARG_LSEG_P(0);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	result->x = float8_div(float8_pl(lseg->p[0].x, lseg->p[1].x), 2.0);
 	result->y = float8_div(float8_pl(lseg->p[0].y, lseg->p[1].y), 2.0);
@@ -2364,7 +2364,7 @@ lseg_interpt(PG_FUNCTION_ARGS)
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (!lseg_interpt_lseg(result, l1, l2))
 		PG_RETURN_NULL();
@@ -2753,7 +2753,7 @@ close_pl(PG_FUNCTION_ARGS)
 	LINE	   *line = PG_GETARG_LINE_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(line_closept_point(result, line, pt)))
 		PG_RETURN_NULL();
@@ -2794,7 +2794,7 @@ close_ps(PG_FUNCTION_ARGS)
 	LSEG	   *lseg = PG_GETARG_LSEG_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(lseg_closept_point(result, lseg, pt)))
 		PG_RETURN_NULL();
@@ -2859,7 +2859,7 @@ close_lseg(PG_FUNCTION_ARGS)
 	if (lseg_sl(l1) == lseg_sl(l2))
 		PG_RETURN_NULL();
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(lseg_closept_lseg(result, l2, l1)))
 		PG_RETURN_NULL();
@@ -2936,7 +2936,7 @@ close_pb(PG_FUNCTION_ARGS)
 	BOX		   *box = PG_GETARG_BOX_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(box_closept_point(result, box, pt)))
 		PG_RETURN_NULL();
@@ -2994,7 +2994,7 @@ close_ls(PG_FUNCTION_ARGS)
 	if (lseg_sl(lseg) == line_sl(line))
 		PG_RETURN_NULL();
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(lseg_closept_line(result, lseg, line)))
 		PG_RETURN_NULL();
@@ -3066,7 +3066,7 @@ close_sb(PG_FUNCTION_ARGS)
 	BOX		   *box = PG_GETARG_BOX_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(box_closept_lseg(result, box, lseg)))
 		PG_RETURN_NULL();
@@ -4099,7 +4099,7 @@ construct_point(PG_FUNCTION_ARGS)
 	float8		y = PG_GETARG_FLOAT8(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	point_construct(result, x, y);
 
@@ -4122,7 +4122,7 @@ point_add(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	point_add_point(result, p1, p2);
 
@@ -4145,7 +4145,7 @@ point_sub(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	point_sub_point(result, p1, p2);
 
@@ -4170,7 +4170,7 @@ point_mul(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	point_mul_point(result, p1, p2);
 
@@ -4199,7 +4199,7 @@ point_div(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	point_div_point(result, p1, p2);
 
@@ -4220,7 +4220,7 @@ points_box(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 	BOX		   *result;
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	box_construct(result, p1, p2);
 
@@ -4234,7 +4234,7 @@ box_add(PG_FUNCTION_ARGS)
 	Point	   *p = PG_GETARG_POINT_P(1);
 	BOX		   *result;
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	point_add_point(&result->high, &box->high, p);
 	point_add_point(&result->low, &box->low, p);
@@ -4249,7 +4249,7 @@ box_sub(PG_FUNCTION_ARGS)
 	Point	   *p = PG_GETARG_POINT_P(1);
 	BOX		   *result;
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	point_sub_point(&result->high, &box->high, p);
 	point_sub_point(&result->low, &box->low, p);
@@ -4266,7 +4266,7 @@ box_mul(PG_FUNCTION_ARGS)
 	Point		high,
 				low;
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	point_mul_point(&high, &box->high, p);
 	point_mul_point(&low, &box->low, p);
@@ -4285,7 +4285,7 @@ box_div(PG_FUNCTION_ARGS)
 	Point		high,
 				low;
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	point_div_point(&high, &box->high, p);
 	point_div_point(&low, &box->low, p);
@@ -4304,7 +4304,7 @@ point_box(PG_FUNCTION_ARGS)
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	BOX		   *box;
 
-	box = (BOX *) palloc(sizeof(BOX));
+	box = palloc_object(BOX);
 
 	box->high.x = pt->x;
 	box->low.x = pt->x;
@@ -4324,7 +4324,7 @@ boxes_bound_box(PG_FUNCTION_ARGS)
 			   *box2 = PG_GETARG_BOX_P(1),
 			   *container;
 
-	container = (BOX *) palloc(sizeof(BOX));
+	container = palloc_object(BOX);
 
 	container->high.x = float8_max(box1->high.x, box2->high.x);
 	container->low.x = float8_min(box1->low.x, box2->low.x);
@@ -4506,7 +4506,7 @@ poly_center(PG_FUNCTION_ARGS)
 	Point	   *result;
 	CIRCLE		circle;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	poly_to_circle(&circle, poly);
 	*result = circle.center;
@@ -4521,7 +4521,7 @@ poly_box(PG_FUNCTION_ARGS)
 	POLYGON    *poly = PG_GETARG_POLYGON_P(0);
 	BOX		   *box;
 
-	box = (BOX *) palloc(sizeof(BOX));
+	box = palloc_object(BOX);
 	*box = poly->boundbox;
 
 	PG_RETURN_BOX_P(box);
@@ -4612,7 +4612,7 @@ circle_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	Node	   *escontext = fcinfo->context;
-	CIRCLE	   *circle = (CIRCLE *) palloc(sizeof(CIRCLE));
+	CIRCLE	   *circle = palloc_object(CIRCLE);
 	char	   *s,
 			   *cp;
 	int			depth = 0;
@@ -4705,7 +4705,7 @@ circle_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	CIRCLE	   *circle;
 
-	circle = (CIRCLE *) palloc(sizeof(CIRCLE));
+	circle = palloc_object(CIRCLE);
 
 	circle->center.x = pq_getmsgfloat8(buf);
 	circle->center.y = pq_getmsgfloat8(buf);
@@ -4968,7 +4968,7 @@ circle_add_pt(PG_FUNCTION_ARGS)
 	Point	   *point = PG_GETARG_POINT_P(1);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	point_add_point(&result->center, &circle->center, point);
 	result->radius = circle->radius;
@@ -4983,7 +4983,7 @@ circle_sub_pt(PG_FUNCTION_ARGS)
 	Point	   *point = PG_GETARG_POINT_P(1);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	point_sub_point(&result->center, &circle->center, point);
 	result->radius = circle->radius;
@@ -5002,7 +5002,7 @@ circle_mul_pt(PG_FUNCTION_ARGS)
 	Point	   *point = PG_GETARG_POINT_P(1);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	point_mul_point(&result->center, &circle->center, point);
 	result->radius = float8_mul(circle->radius, HYPOT(point->x, point->y));
@@ -5017,7 +5017,7 @@ circle_div_pt(PG_FUNCTION_ARGS)
 	Point	   *point = PG_GETARG_POINT_P(1);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	point_div_point(&result->center, &circle->center, point);
 	result->radius = float8_div(circle->radius, HYPOT(point->x, point->y));
@@ -5145,7 +5145,7 @@ circle_center(PG_FUNCTION_ARGS)
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 	result->x = circle->center.x;
 	result->y = circle->center.y;
 
@@ -5173,7 +5173,7 @@ cr_circle(PG_FUNCTION_ARGS)
 	float8		radius = PG_GETARG_FLOAT8(1);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	result->center.x = center->x;
 	result->center.y = center->y;
@@ -5189,7 +5189,7 @@ circle_box(PG_FUNCTION_ARGS)
 	BOX		   *box;
 	float8		delta;
 
-	box = (BOX *) palloc(sizeof(BOX));
+	box = palloc_object(BOX);
 
 	delta = float8_div(circle->radius, sqrt(2.0));
 
@@ -5210,7 +5210,7 @@ box_circle(PG_FUNCTION_ARGS)
 	BOX		   *box = PG_GETARG_BOX_P(0);
 	CIRCLE	   *circle;
 
-	circle = (CIRCLE *) palloc(sizeof(CIRCLE));
+	circle = palloc_object(CIRCLE);
 
 	circle->center.x = float8_div(float8_pl(box->high.x, box->low.x), 2.0);
 	circle->center.y = float8_div(float8_pl(box->high.y, box->low.y), 2.0);
@@ -5309,7 +5309,7 @@ poly_circle(PG_FUNCTION_ARGS)
 	POLYGON    *poly = PG_GETARG_POLYGON_P(0);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	poly_to_circle(result, poly);
 
diff --git a/src/backend/utils/adt/geo_spgist.c b/src/backend/utils/adt/geo_spgist.c
index fec33e95372..e71e6848d98 100644
--- a/src/backend/utils/adt/geo_spgist.c
+++ b/src/backend/utils/adt/geo_spgist.c
@@ -156,7 +156,7 @@ getQuadrant(BOX *centroid, BOX *inBox)
 static RangeBox *
 getRangeBox(BOX *box)
 {
-	RangeBox   *range_box = (RangeBox *) palloc(sizeof(RangeBox));
+	RangeBox   *range_box = palloc_object(RangeBox);
 
 	range_box->left.low = box->low.x;
 	range_box->left.high = box->high.x;
@@ -176,7 +176,7 @@ getRangeBox(BOX *box)
 static RectBox *
 initRectBox(void)
 {
-	RectBox    *rect_box = (RectBox *) palloc(sizeof(RectBox));
+	RectBox    *rect_box = palloc_object(RectBox);
 	float8		infinity = get_float8_infinity();
 
 	rect_box->range_box_x.left.low = -infinity;
@@ -204,7 +204,7 @@ initRectBox(void)
 static RectBox *
 nextRectBox(RectBox *rect_box, RangeBox *centroid, uint8 quadrant)
 {
-	RectBox    *next_rect_box = (RectBox *) palloc(sizeof(RectBox));
+	RectBox    *next_rect_box = palloc_object(RectBox);
 
 	memcpy(next_rect_box, rect_box, sizeof(RectBox));
 
@@ -445,10 +445,10 @@ spg_box_quad_picksplit(PG_FUNCTION_ARGS)
 	BOX		   *centroid;
 	int			median,
 				i;
-	float8	   *lowXs = palloc(sizeof(float8) * in->nTuples);
-	float8	   *highXs = palloc(sizeof(float8) * in->nTuples);
-	float8	   *lowYs = palloc(sizeof(float8) * in->nTuples);
-	float8	   *highYs = palloc(sizeof(float8) * in->nTuples);
+	float8	   *lowXs = palloc_array(float8, in->nTuples);
+	float8	   *highXs = palloc_array(float8, in->nTuples);
+	float8	   *lowYs = palloc_array(float8, in->nTuples);
+	float8	   *highYs = palloc_array(float8, in->nTuples);
 
 	/* Calculate median of all 4D coordinates */
 	for (i = 0; i < in->nTuples; i++)
@@ -468,7 +468,7 @@ spg_box_quad_picksplit(PG_FUNCTION_ARGS)
 
 	median = in->nTuples / 2;
 
-	centroid = palloc(sizeof(BOX));
+	centroid = palloc_object(BOX);
 
 	centroid->low.x = lowXs[median];
 	centroid->high.x = highXs[median];
@@ -482,8 +482,8 @@ spg_box_quad_picksplit(PG_FUNCTION_ARGS)
 	out->nNodes = 16;
 	out->nodeLabels = NULL;		/* We don't need node labels. */
 
-	out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	/*
 	 * Assign ranges to corresponding nodes according to quadrants relative to
@@ -574,13 +574,13 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
 	{
 		/* Report that all nodes should be visited */
 		out->nNodes = in->nNodes;
-		out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
+		out->nodeNumbers = palloc_array(int, in->nNodes);
 		for (i = 0; i < in->nNodes; i++)
 			out->nodeNumbers[i] = i;
 
 		if (in->norderbys > 0 && in->nNodes > 0)
 		{
-			double	   *distances = palloc(sizeof(double) * in->norderbys);
+			double	   *distances = palloc_array(double, in->norderbys);
 			int			j;
 
 			for (j = 0; j < in->norderbys; j++)
@@ -590,12 +590,12 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
 				distances[j] = pointToRectBoxDistance(pt, rect_box);
 			}
 
-			out->distances = (double **) palloc(sizeof(double *) * in->nNodes);
+			out->distances = palloc_array(double *, in->nNodes);
 			out->distances[0] = distances;
 
 			for (i = 1; i < in->nNodes; i++)
 			{
-				out->distances[i] = palloc(sizeof(double) * in->norderbys);
+				out->distances[i] = palloc_array(double, in->norderbys);
 				memcpy(out->distances[i], distances,
 					   sizeof(double) * in->norderbys);
 			}
@@ -609,7 +609,7 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
 	 * following operations.
 	 */
 	centroid = getRangeBox(DatumGetBoxP(in->prefixDatum));
-	queries = (RangeBox **) palloc(in->nkeys * sizeof(RangeBox *));
+	queries = palloc_array(RangeBox *, in->nkeys);
 	for (i = 0; i < in->nkeys; i++)
 	{
 		BOX		   *box = spg_box_quad_get_scankey_bbox(&in->scankeys[i], NULL);
@@ -619,10 +619,10 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
 
 	/* Allocate enough memory for nodes */
 	out->nNodes = 0;
-	out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
-	out->traversalValues = (void **) palloc(sizeof(void *) * in->nNodes);
+	out->nodeNumbers = palloc_array(int, in->nNodes);
+	out->traversalValues = palloc_array(void *, in->nNodes);
 	if (in->norderbys > 0)
-		out->distances = (double **) palloc(sizeof(double *) * in->nNodes);
+		out->distances = palloc_array(double *, in->nNodes);
 
 	/*
 	 * We switch memory context, because we want to allocate memory for new
@@ -703,7 +703,7 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
 
 			if (in->norderbys > 0)
 			{
-				double	   *distances = palloc(sizeof(double) * in->norderbys);
+				double	   *distances = palloc_array(double, in->norderbys);
 				int			j;
 
 				out->distances[out->nNodes] = distances;
@@ -878,7 +878,7 @@ spg_poly_quad_compress(PG_FUNCTION_ARGS)
 	POLYGON    *polygon = PG_GETARG_POLYGON_P(0);
 	BOX		   *box;
 
-	box = (BOX *) palloc(sizeof(BOX));
+	box = palloc_object(BOX);
 	*box = polygon->boundbox;
 
 	PG_RETURN_BOX_P(box);
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index b5781989a64..60411ee024d 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -1537,7 +1537,7 @@ generate_series_step_int4(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
+		fctx = palloc_object(generate_series_fctx);
 
 		/*
 		 * Use fctx to keep state from call to call. Seed current with the
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index bdea490202a..18b7e9e8b6b 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -1364,7 +1364,7 @@ generate_series_step_int8(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
+		fctx = palloc_object(generate_series_fctx);
 
 		/*
 		 * Use fctx to keep state from call to call. Seed current with the
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 06dd62f0008..73cacf33e61 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -807,7 +807,7 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
 		 * use the right context to enlarge the object if necessary.
 		 */
 		oldcontext = MemoryContextSwitchTo(aggcontext);
-		state = (JsonAggState *) palloc(sizeof(JsonAggState));
+		state = palloc_object(JsonAggState);
 		state->str = makeStringInfo();
 		MemoryContextSwitchTo(oldcontext);
 
@@ -1029,7 +1029,7 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
 		 * sure they use the right context to enlarge the object if necessary.
 		 */
 		oldcontext = MemoryContextSwitchTo(aggcontext);
-		state = (JsonAggState *) palloc(sizeof(JsonAggState));
+		state = palloc_object(JsonAggState);
 		state->str = makeStringInfo();
 		if (unique_keys)
 			json_unique_builder_init(&state->unique_check);
@@ -1762,7 +1762,7 @@ json_unique_object_start(void *_state)
 		return JSON_SUCCESS;
 
 	/* push object entry to stack */
-	entry = palloc(sizeof(*entry));
+	entry = palloc_object(JsonUniqueStackEntry);
 	entry->object_id = state->id_counter++;
 	entry->parent = state->stack;
 	state->stack = entry;
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index 9399cdb491a..1cc650e717b 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -1478,7 +1478,7 @@ clone_parse_state(JsonbParseState *state)
 	if (state == NULL)
 		return NULL;
 
-	result = palloc(sizeof(JsonbParseState));
+	result = palloc_object(JsonbParseState);
 	icursor = state;
 	ocursor = result;
 	for (;;)
@@ -1490,7 +1490,7 @@ clone_parse_state(JsonbParseState *state)
 		icursor = icursor->next;
 		if (icursor == NULL)
 			break;
-		ocursor->next = palloc(sizeof(JsonbParseState));
+		ocursor->next = palloc_object(JsonbParseState);
 		ocursor = ocursor->next;
 	}
 	ocursor->next = NULL;
@@ -1531,8 +1531,8 @@ jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
 					 errmsg("could not determine input data type")));
 
 		oldcontext = MemoryContextSwitchTo(aggcontext);
-		state = palloc(sizeof(JsonbAggState));
-		result = palloc0(sizeof(JsonbInState));
+		state = palloc_object(JsonbAggState);
+		result = palloc0_object(JsonbInState);
 		state->res = result;
 		result->res = pushJsonbValue(&result->parseState,
 									 WJB_BEGIN_ARRAY, NULL);
@@ -1701,8 +1701,8 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
 		Oid			arg_type;
 
 		oldcontext = MemoryContextSwitchTo(aggcontext);
-		state = palloc(sizeof(JsonbAggState));
-		result = palloc0(sizeof(JsonbInState));
+		state = palloc_object(JsonbAggState);
+		result = palloc0_object(JsonbInState);
 		state->res = result;
 		result->res = pushJsonbValue(&result->parseState,
 									 WJB_BEGIN_OBJECT, NULL);
diff --git a/src/backend/utils/adt/jsonb_gin.c b/src/backend/utils/adt/jsonb_gin.c
index 9b56248cf0b..2190092b14f 100644
--- a/src/backend/utils/adt/jsonb_gin.c
+++ b/src/backend/utils/adt/jsonb_gin.c
@@ -163,7 +163,7 @@ static void
 init_gin_entries(GinEntries *entries, int preallocated)
 {
 	entries->allocated = preallocated;
-	entries->buf = preallocated ? palloc(sizeof(Datum) * preallocated) : NULL;
+	entries->buf = preallocated ? palloc_array(Datum, preallocated) : NULL;
 	entries->count = 0;
 }
 
@@ -178,13 +178,14 @@ add_gin_entry(GinEntries *entries, Datum entry)
 		if (entries->allocated)
 		{
 			entries->allocated *= 2;
-			entries->buf = repalloc(entries->buf,
-									sizeof(Datum) * entries->allocated);
+			entries->buf = repalloc_array(entries->buf,
+										 Datum,
+										 entries->allocated);
 		}
 		else
 		{
 			entries->allocated = 8;
-			entries->buf = palloc(sizeof(Datum) * entries->allocated);
+			entries->buf = palloc_array(Datum, entries->allocated);
 		}
 	}
 
@@ -307,7 +308,7 @@ jsonb_ops__add_path_item(JsonPathGinPath *path, JsonPathItem *jsp)
 			return false;
 	}
 
-	pentry = palloc(sizeof(*pentry));
+	pentry = palloc_object(JsonPathGinPathItem);
 
 	pentry->type = jsp->type;
 	pentry->keyName = keyName;
@@ -785,7 +786,7 @@ extract_jsp_query(JsonPath *jp, StrategyNumber strat, bool pathOps,
 	if (!*nentries)
 		return NULL;
 
-	*extra_data = palloc0(sizeof(**extra_data) * entries.count);
+	*extra_data = palloc0_array(Pointer, entries.count);
 	**extra_data = (Pointer) node;
 
 	return entries.buf;
@@ -869,7 +870,7 @@ gin_extract_jsonb_query(PG_FUNCTION_ARGS)
 		text	   *query = PG_GETARG_TEXT_PP(0);
 
 		*nentries = 1;
-		entries = (Datum *) palloc(sizeof(Datum));
+		entries = palloc_object(Datum);
 		entries[0] = make_text_key(JGINFLAG_KEY,
 								   VARDATA_ANY(query),
 								   VARSIZE_ANY_EXHDR(query));
@@ -887,7 +888,7 @@ gin_extract_jsonb_query(PG_FUNCTION_ARGS)
 
 		deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
 
-		entries = (Datum *) palloc(sizeof(Datum) * key_count);
+		entries = palloc_array(Datum, key_count);
 
 		for (i = 0, j = 0; i < key_count; i++)
 		{
@@ -1126,7 +1127,7 @@ gin_extract_jsonb_path(PG_FUNCTION_ARGS)
 			case WJB_BEGIN_OBJECT:
 				/* Push a stack level for this object */
 				parent = stack;
-				stack = (PathHashStack *) palloc(sizeof(PathHashStack));
+				stack = palloc_object(PathHashStack);
 
 				/*
 				 * We pass forward hashes from outer nesting levels so that
diff --git a/src/backend/utils/adt/jsonb_util.c b/src/backend/utils/adt/jsonb_util.c
index 82b807d067a..714b07a5555 100644
--- a/src/backend/utils/adt/jsonb_util.c
+++ b/src/backend/utils/adt/jsonb_util.c
@@ -356,7 +356,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
 
 	if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
 	{
-		JsonbValue *result = palloc(sizeof(JsonbValue));
+		JsonbValue *result = palloc_object(JsonbValue);
 		char	   *base_addr = (char *) (children + count);
 		uint32		offset = 0;
 		int			i;
@@ -439,7 +439,7 @@ getKeyJsonValueFromContainer(JsonbContainer *container,
 			int			index = stopMiddle + count;
 
 			if (!res)
-				res = palloc(sizeof(JsonbValue));
+				res = palloc_object(JsonbValue);
 
 			fillJsonbValue(container, index, baseAddr,
 						   getJsonbOffset(container, index),
@@ -481,7 +481,7 @@ getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
 	if (i >= nelements)
 		return NULL;
 
-	result = palloc(sizeof(JsonbValue));
+	result = palloc_object(JsonbValue);
 
 	fillJsonbValue(container, i, base_addr,
 				   getJsonbOffset(container, i),
@@ -663,8 +663,8 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
 			{
 				(*pstate)->size = 4;
 			}
-			(*pstate)->contVal.val.array.elems = palloc(sizeof(JsonbValue) *
-														(*pstate)->size);
+			(*pstate)->contVal.val.array.elems = palloc_array(JsonbValue,
+															(*pstate)->size);
 			break;
 		case WJB_BEGIN_OBJECT:
 			Assert(!scalarVal);
@@ -673,8 +673,8 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
 			(*pstate)->contVal.type = jbvObject;
 			(*pstate)->contVal.val.object.nPairs = 0;
 			(*pstate)->size = 4;
-			(*pstate)->contVal.val.object.pairs = palloc(sizeof(JsonbPair) *
-														 (*pstate)->size);
+			(*pstate)->contVal.val.object.pairs = palloc_array(JsonbPair,
+																 (*pstate)->size);
 			break;
 		case WJB_KEY:
 			Assert(scalarVal->type == jbvString);
@@ -731,7 +731,7 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
 static JsonbParseState *
 pushState(JsonbParseState **pstate)
 {
-	JsonbParseState *ns = palloc(sizeof(JsonbParseState));
+	JsonbParseState *ns = palloc_object(JsonbParseState);
 
 	ns->next = *pstate;
 	ns->unique_keys = false;
@@ -1010,7 +1010,7 @@ iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent)
 {
 	JsonbIterator *it;
 
-	it = palloc0(sizeof(JsonbIterator));
+	it = palloc0_object(JsonbIterator);
 	it->container = container;
 	it->parent = parent;
 	it->nElems = JsonContainerSize(container);
@@ -1256,7 +1256,7 @@ JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
 					uint32		j = 0;
 
 					/* Make room for all possible values */
-					lhsConts = palloc(sizeof(JsonbValue) * nLhsElems);
+					lhsConts = palloc_array(JsonbValue, nLhsElems);
 
 					for (i = 0; i < nLhsElems; i++)
 					{
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index 8898f0f90a1..3e122dab934 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -593,12 +593,12 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
 		funcctx = SRF_FIRSTCALL_INIT();
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-		state = palloc(sizeof(OkeysState));
+		state = palloc_object(OkeysState);
 
 		state->result_size = JB_ROOT_COUNT(jb);
 		state->result_count = 0;
 		state->sent_count = 0;
-		state->result = palloc(state->result_size * sizeof(char *));
+		state->result = palloc_array(char *, state->result_size);
 
 		it = JsonbIteratorInit(&jb->root);
 
@@ -744,14 +744,14 @@ json_object_keys(PG_FUNCTION_ARGS)
 		funcctx = SRF_FIRSTCALL_INIT();
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-		state = palloc(sizeof(OkeysState));
-		sem = palloc0(sizeof(JsonSemAction));
+		state = palloc_object(OkeysState);
+		sem = palloc0_object(JsonSemAction);
 
 		state->lex = makeJsonLexContext(&lex, json, true);
 		state->result_size = 256;
 		state->result_count = 0;
 		state->sent_count = 0;
-		state->result = palloc(256 * sizeof(char *));
+		state->result = palloc_array(char *, 256);
 
 		sem->semstate = state;
 		sem->array_start = okeys_array_start;
@@ -1045,8 +1045,8 @@ get_path_all(FunctionCallInfo fcinfo, bool as_text)
 
 	deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
 
-	tpath = palloc(npath * sizeof(char *));
-	ipath = palloc(npath * sizeof(int));
+	tpath = palloc_array(char *, npath);
+	ipath = palloc_array(int, npath);
 
 	for (i = 0; i < npath; i++)
 	{
@@ -1106,8 +1106,8 @@ get_worker(text *json,
 		   int npath,
 		   bool normalize_results)
 {
-	JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
-	GetState   *state = palloc0(sizeof(GetState));
+	JsonSemAction *sem = palloc0_object(JsonSemAction);
+	GetState   *state = palloc0_object(GetState);
 
 	Assert(npath >= 0);
 
@@ -1118,8 +1118,8 @@ get_worker(text *json,
 	state->npath = npath;
 	state->path_names = tpath;
 	state->path_indexes = ipath;
-	state->pathok = palloc0(sizeof(bool) * npath);
-	state->array_cur_index = palloc(sizeof(int) * npath);
+	state->pathok = palloc0_array(bool, npath);
+	state->array_cur_index = palloc_array(int, npath);
 
 	if (npath > 0)
 		state->pathok[0] = true;
@@ -1682,7 +1682,7 @@ jsonb_set_element(Jsonb *jb, const Datum *path, int path_len,
 	JsonbValue *res;
 	JsonbParseState *state = NULL;
 	JsonbIterator *it;
-	bool	   *path_nulls = palloc0(path_len * sizeof(bool));
+	bool	   *path_nulls = palloc0_array(bool, path_len);
 
 	if (newval->type == jbvArray && newval->val.array.rawScalar)
 		*newval = newval->val.array.elems[0];
@@ -1727,7 +1727,7 @@ push_path(JsonbParseState **st, int level, const Datum *path_elems,
 	 * it contains only information about path slice from level to the end,
 	 * the access index must be normalized by level.
 	 */
-	enum jbvType *tpath = palloc0((path_len - level) * sizeof(enum jbvType));
+	enum jbvType *tpath = palloc0_array(enum jbvType, path_len - level);
 	JsonbValue	newkey;
 
 	/*
@@ -1856,14 +1856,14 @@ json_array_length(PG_FUNCTION_ARGS)
 	JsonLexContext lex;
 	JsonSemAction *sem;
 
-	state = palloc0(sizeof(AlenState));
+	state = palloc0_object(AlenState);
 	state->lex = makeJsonLexContext(&lex, json, false);
 	/* palloc0 does this for us */
 #if 0
 	state->count = 0;
 #endif
 
-	sem = palloc0(sizeof(JsonSemAction));
+	sem = palloc0_object(JsonSemAction);
 	sem->semstate = state;
 	sem->object_start = alen_object_start;
 	sem->scalar = alen_scalar;
@@ -2063,8 +2063,8 @@ each_worker(FunctionCallInfo fcinfo, bool as_text)
 	ReturnSetInfo *rsi;
 	EachState  *state;
 
-	state = palloc0(sizeof(EachState));
-	sem = palloc0(sizeof(JsonSemAction));
+	state = palloc0_object(EachState);
+	sem = palloc0_object(JsonSemAction);
 
 	rsi = (ReturnSetInfo *) fcinfo->resultinfo;
 
@@ -2316,8 +2316,8 @@ elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 	/* elements only needs escaped strings when as_text */
 	makeJsonLexContext(&lex, json, as_text);
 
-	state = palloc0(sizeof(ElementsState));
-	sem = palloc0(sizeof(JsonSemAction));
+	state = palloc0_object(ElementsState);
+	sem = palloc0_object(JsonSemAction);
 
 	InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC | MAT_SRF_BLESS);
 	rsi = (ReturnSetInfo *) fcinfo->resultinfo;
@@ -2572,8 +2572,8 @@ populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
 	}
 
 	ctx->ndims = ndims;
-	ctx->dims = palloc(sizeof(int) * ndims);
-	ctx->sizes = palloc0(sizeof(int) * ndims);
+	ctx->dims = palloc_array(int, ndims);
+	ctx->sizes = palloc0_array(int, ndims);
 
 	for (i = 0; i < ndims; i++)
 		ctx->dims[i] = -1;		/* dimensions are unknown yet */
@@ -2958,7 +2958,7 @@ populate_array(ArrayIOData *aio,
 
 	Assert(ctx.ndims > 0);
 
-	lbs = palloc(sizeof(int) * ctx.ndims);
+	lbs = palloc_array(int, ctx.ndims);
 
 	for (i = 0; i < ctx.ndims; i++)
 		lbs[i] = 1;
@@ -3824,8 +3824,8 @@ get_json_object_as_hash(const char *json, int len, const char *funcname,
 					  &ctl,
 					  HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
 
-	state = palloc0(sizeof(JHashState));
-	sem = palloc0(sizeof(JsonSemAction));
+	state = palloc0_object(JHashState);
+	sem = palloc0_object(JsonSemAction);
 
 	state->function_name = funcname;
 	state->hash = tab;
@@ -4122,7 +4122,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
 	 */
 	update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
 
-	state = palloc0(sizeof(PopulateRecordsetState));
+	state = palloc0_object(PopulateRecordsetState);
 
 	/* make tuplestore in a sufficiently long-lived memory context */
 	old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
@@ -4141,7 +4141,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
 		JsonLexContext lex;
 		JsonSemAction *sem;
 
-		sem = palloc0(sizeof(JsonSemAction));
+		sem = palloc0_object(JsonSemAction);
 
 		makeJsonLexContext(&lex, json, true);
 
@@ -4511,8 +4511,8 @@ json_strip_nulls(PG_FUNCTION_ARGS)
 	JsonLexContext lex;
 	JsonSemAction *sem;
 
-	state = palloc0(sizeof(StripnullState));
-	sem = palloc0(sizeof(JsonSemAction));
+	state = palloc0_object(StripnullState);
+	sem = palloc0_object(JsonSemAction);
 	initStringInfo(&strbuf);
 
 	state->lex = makeJsonLexContext(&lex, json, true);
@@ -5736,8 +5736,8 @@ iterate_json_values(text *json, uint32 flags, void *action_state,
 					JsonIterateStringValuesAction action)
 {
 	JsonLexContext lex;
-	JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
-	IterateJsonStringValuesState *state = palloc0(sizeof(IterateJsonStringValuesState));
+	JsonSemAction *sem = palloc0_object(JsonSemAction);
+	IterateJsonStringValuesState *state = palloc0_object(IterateJsonStringValuesState);
 
 	state->lex = makeJsonLexContext(&lex, json, true);
 	state->action = action;
@@ -5857,8 +5857,8 @@ transform_json_string_values(text *json, void *action_state,
 							 JsonTransformStringValuesAction transform_action)
 {
 	JsonLexContext lex;
-	JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
-	TransformJsonStringValuesState *state = palloc0(sizeof(TransformJsonStringValuesState));
+	JsonSemAction *sem = palloc0_object(JsonSemAction);
+	TransformJsonStringValuesState *state = palloc0_object(TransformJsonStringValuesState);
 	StringInfoData strbuf;
 
 	initStringInfo(&strbuf);
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 8156695e97e..7aa5194be7a 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -775,7 +775,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 					break;
 				}
 
-				v = hasNext ? &vbuf : palloc(sizeof(*v));
+				v = hasNext ? &vbuf : palloc_object(JsonbValue);
 
 				baseObject = cxt->baseObject;
 				getJsonPathItem(cxt, jsp, v);
@@ -1088,7 +1088,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 
 		case jpiType:
 			{
-				JsonbValue *jbv = palloc(sizeof(*jbv));
+				JsonbValue *jbv = palloc_object(JsonbValue);
 
 				jbv->type = jbvString;
 				jbv->val.string.val = pstrdup(JsonbTypeName(jb));
@@ -1118,7 +1118,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 					size = 1;
 				}
 
-				jb = palloc(sizeof(*jb));
+				jb = palloc_object(JsonbValue);
 
 				jb->type = jbvNumeric;
 				jb->val.numeric = int64_to_numeric(size);
@@ -1249,7 +1249,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 
 				last = cxt->innermostArraySize - 1;
 
-				lastjbv = hasNext ? &tmpjbv : palloc(sizeof(*lastjbv));
+				lastjbv = hasNext ? &tmpjbv : palloc_object(JsonbValue);
 
 				lastjbv->type = jbvNumeric;
 				lastjbv->val.numeric = int64_to_numeric(last);
@@ -2162,7 +2162,7 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
 	if (!jspGetNext(jsp, &elem) && !found)
 		return jperOk;
 
-	lval = palloc(sizeof(*lval));
+	lval = palloc_object(JsonbValue);
 	lval->type = jbvNumeric;
 	lval->val.numeric = res;
 
@@ -2317,7 +2317,7 @@ executeNumericItemMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 	if (!jspGetNext(jsp, &next) && !found)
 		return jperOk;
 
-	jb = palloc(sizeof(*jb));
+	jb = palloc_object(JsonbValue);
 	jb->type = jbvNumeric;
 	jb->val.numeric = DatumGetNumeric(datum);
 
@@ -2783,7 +2783,7 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 	if (!hasNext && !found)
 		return res;
 
-	jb = hasNext ? &jbvbuf : palloc(sizeof(*jb));
+	jb = hasNext ? &jbvbuf : palloc_object(JsonbValue);
 
 	jb->type = jbvDatetime;
 	jb->val.datetime.value = value;
@@ -3018,7 +3018,7 @@ GetJsonPathVar(void *cxt, char *varName, int varNameLen,
 		return NULL;
 	}
 
-	result = palloc(sizeof(JsonbValue));
+	result = palloc_object(JsonbValue);
 	if (var->isnull)
 	{
 		*baseObjectId = 0;
@@ -3445,7 +3445,7 @@ compareNumeric(Numeric a, Numeric b)
 static JsonbValue *
 copyJsonbValue(JsonbValue *src)
 {
-	JsonbValue *dst = palloc(sizeof(*dst));
+	JsonbValue *dst = palloc_object(JsonbValue);
 
 	*dst = *src;
 
@@ -4119,7 +4119,7 @@ JsonTableInitOpaque(TableFuncScanState *state, int natts)
 	JsonExpr   *je = castNode(JsonExpr, tf->docexpr);
 	List	   *args = NIL;
 
-	cxt = palloc0(sizeof(JsonTableExecContext));
+	cxt = palloc0_object(JsonTableExecContext);
 	cxt->magic = JSON_TABLE_EXEC_CONTEXT_MAGIC;
 
 	/*
@@ -4138,7 +4138,7 @@ JsonTableInitOpaque(TableFuncScanState *state, int natts)
 		{
 			ExprState  *state = lfirst_node(ExprState, exprlc);
 			String	   *name = lfirst_node(String, namelc);
-			JsonPathVariable *var = palloc(sizeof(*var));
+			JsonPathVariable *var = palloc_object(JsonPathVariable);
 
 			var->name = pstrdup(name->sval);
 			var->namelen = strlen(var->name);
@@ -4156,8 +4156,7 @@ JsonTableInitOpaque(TableFuncScanState *state, int natts)
 		}
 	}
 
-	cxt->colplanstates = palloc(sizeof(JsonTablePlanState *) *
-								list_length(tf->colvalexprs));
+	cxt->colplanstates = palloc_array(JsonTablePlanState *, list_length(tf->colvalexprs));
 
 	/*
 	 * Initialize plan for the root path and, recursively, also any child
@@ -4195,7 +4194,7 @@ JsonTableInitPlan(JsonTableExecContext *cxt, JsonTablePlan *plan,
 				  JsonTablePlanState *parentstate,
 				  List *args, MemoryContext mcxt)
 {
-	JsonTablePlanState *planstate = palloc0(sizeof(*planstate));
+	JsonTablePlanState *planstate = palloc0_object(JsonTablePlanState);
 
 	planstate->plan = plan;
 	planstate->parent = parentstate;
diff --git a/src/backend/utils/adt/jsonpath_gram.y b/src/backend/utils/adt/jsonpath_gram.y
index 499745a8fef..411a8baf380 100644
--- a/src/backend/utils/adt/jsonpath_gram.y
+++ b/src/backend/utils/adt/jsonpath_gram.y
@@ -120,7 +120,7 @@ static bool makeItemLikeRegex(JsonPathParseItem *expr,
 
 result:
 	mode expr_or_predicate			{
-										*result = palloc(sizeof(JsonPathParseResult));
+										*result = palloc_object(JsonPathParseResult);
 										(*result)->expr = $2;
 										(*result)->lax = $1;
 										(void) yynerrs;
@@ -384,7 +384,7 @@ method:
 static JsonPathParseItem *
 makeItemType(JsonPathItemType type)
 {
-	JsonPathParseItem *v = palloc(sizeof(*v));
+	JsonPathParseItem *v = palloc_object(JsonPathParseItem);
 
 	CHECK_FOR_INTERRUPTS();
 
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index df938812dd3..bf38d68aa03 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -152,7 +152,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
 		 * Collect all the locking information that we will format and send
 		 * out as a result set.
 		 */
-		mystatus = (PG_Lock_Status *) palloc(sizeof(PG_Lock_Status));
+		mystatus = palloc_object(PG_Lock_Status);
 		funcctx->user_fctx = mystatus;
 
 		mystatus->lockData = GetLockStatusData();
diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c
index bb38ef2f5e4..35234e700ff 100644
--- a/src/backend/utils/adt/mac.c
+++ b/src/backend/utils/adt/mac.c
@@ -101,7 +101,7 @@ macaddr_in(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("invalid octet value in \"macaddr\" value: \"%s\"", str)));
 
-	result = (macaddr *) palloc(sizeof(macaddr));
+	result = palloc_object(macaddr);
 
 	result->a = a;
 	result->b = b;
@@ -142,7 +142,7 @@ macaddr_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	macaddr    *addr;
 
-	addr = (macaddr *) palloc(sizeof(macaddr));
+	addr = palloc_object(macaddr);
 
 	addr->a = pq_getmsgbyte(buf);
 	addr->b = pq_getmsgbyte(buf);
@@ -289,7 +289,7 @@ macaddr_not(PG_FUNCTION_ARGS)
 	macaddr    *addr = PG_GETARG_MACADDR_P(0);
 	macaddr    *result;
 
-	result = (macaddr *) palloc(sizeof(macaddr));
+	result = palloc_object(macaddr);
 	result->a = ~addr->a;
 	result->b = ~addr->b;
 	result->c = ~addr->c;
@@ -306,7 +306,7 @@ macaddr_and(PG_FUNCTION_ARGS)
 	macaddr    *addr2 = PG_GETARG_MACADDR_P(1);
 	macaddr    *result;
 
-	result = (macaddr *) palloc(sizeof(macaddr));
+	result = palloc_object(macaddr);
 	result->a = addr1->a & addr2->a;
 	result->b = addr1->b & addr2->b;
 	result->c = addr1->c & addr2->c;
@@ -323,7 +323,7 @@ macaddr_or(PG_FUNCTION_ARGS)
 	macaddr    *addr2 = PG_GETARG_MACADDR_P(1);
 	macaddr    *result;
 
-	result = (macaddr *) palloc(sizeof(macaddr));
+	result = palloc_object(macaddr);
 	result->a = addr1->a | addr2->a;
 	result->b = addr1->b | addr2->b;
 	result->c = addr1->c | addr2->c;
@@ -343,7 +343,7 @@ macaddr_trunc(PG_FUNCTION_ARGS)
 	macaddr    *addr = PG_GETARG_MACADDR_P(0);
 	macaddr    *result;
 
-	result = (macaddr *) palloc(sizeof(macaddr));
+	result = palloc_object(macaddr);
 
 	result->a = addr->a;
 	result->b = addr->b;
@@ -374,7 +374,7 @@ macaddr_sortsupport(PG_FUNCTION_ARGS)
 
 		oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
 
-		uss = palloc(sizeof(macaddr_sortsupport_state));
+		uss = palloc_object(macaddr_sortsupport_state);
 		uss->input_count = 0;
 		uss->estimating = true;
 		initHyperLogLog(&uss->abbr_card, 10);
diff --git a/src/backend/utils/adt/mac8.c b/src/backend/utils/adt/mac8.c
index 08e41ba4eea..ea715a7a0d4 100644
--- a/src/backend/utils/adt/mac8.c
+++ b/src/backend/utils/adt/mac8.c
@@ -207,7 +207,7 @@ macaddr8_in(PG_FUNCTION_ARGS)
 	else if (count != 8)
 		goto fail;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 
 	result->a = a;
 	result->b = b;
@@ -256,7 +256,7 @@ macaddr8_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	macaddr8   *addr;
 
-	addr = (macaddr8 *) palloc0(sizeof(macaddr8));
+	addr = palloc0_object(macaddr8);
 
 	addr->a = pq_getmsgbyte(buf);
 	addr->b = pq_getmsgbyte(buf);
@@ -417,7 +417,7 @@ macaddr8_not(PG_FUNCTION_ARGS)
 	macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 	result->a = ~addr->a;
 	result->b = ~addr->b;
 	result->c = ~addr->c;
@@ -437,7 +437,7 @@ macaddr8_and(PG_FUNCTION_ARGS)
 	macaddr8   *addr2 = PG_GETARG_MACADDR8_P(1);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 	result->a = addr1->a & addr2->a;
 	result->b = addr1->b & addr2->b;
 	result->c = addr1->c & addr2->c;
@@ -457,7 +457,7 @@ macaddr8_or(PG_FUNCTION_ARGS)
 	macaddr8   *addr2 = PG_GETARG_MACADDR8_P(1);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 	result->a = addr1->a | addr2->a;
 	result->b = addr1->b | addr2->b;
 	result->c = addr1->c | addr2->c;
@@ -479,7 +479,7 @@ macaddr8_trunc(PG_FUNCTION_ARGS)
 	macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 
 	result->a = addr->a;
 	result->b = addr->b;
@@ -502,7 +502,7 @@ macaddr8_set7bit(PG_FUNCTION_ARGS)
 	macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 
 	result->a = addr->a | 0x02;
 	result->b = addr->b;
@@ -526,7 +526,7 @@ macaddrtomacaddr8(PG_FUNCTION_ARGS)
 	macaddr    *addr6 = PG_GETARG_MACADDR_P(0);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 
 	result->a = addr6->a;
 	result->b = addr6->b;
@@ -547,7 +547,7 @@ macaddr8tomacaddr(PG_FUNCTION_ARGS)
 	macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
 	macaddr    *result;
 
-	result = (macaddr *) palloc0(sizeof(macaddr));
+	result = palloc0_object(macaddr);
 
 	if ((addr->d != 0xFF) || (addr->e != 0xFE))
 		ereport(ERROR,
diff --git a/src/backend/utils/adt/mcxtfuncs.c b/src/backend/utils/adt/mcxtfuncs.c
index fe6dce9cba3..46dfb3dd133 100644
--- a/src/backend/utils/adt/mcxtfuncs.c
+++ b/src/backend/utils/adt/mcxtfuncs.c
@@ -52,7 +52,7 @@ int_list_to_array(const List *list)
 	ArrayType  *result_array;
 
 	length = list_length(list);
-	datum_array = (Datum *) palloc(length * sizeof(Datum));
+	datum_array = palloc_array(Datum, length);
 
 	foreach_int(i, list)
 		datum_array[foreach_current_index(i)] = Int32GetDatum(i);
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index a365c432d34..c32f24fbf97 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -487,7 +487,7 @@ pg_get_catalog_foreign_keys(PG_FUNCTION_ARGS)
 		 * array_in, and it wouldn't be very efficient if we could.  Fill an
 		 * FmgrInfo to use for the call.
 		 */
-		arrayinp = (FmgrInfo *) palloc(sizeof(FmgrInfo));
+		arrayinp = palloc_object(FmgrInfo);
 		fmgr_info(F_ARRAY_IN, arrayinp);
 		funcctx->user_fctx = arrayinp;
 
diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c
index 5273b97f7fe..a34efea5c61 100644
--- a/src/backend/utils/adt/multirangetypes.c
+++ b/src/backend/utils/adt/multirangetypes.c
@@ -125,7 +125,7 @@ multirange_in(PG_FUNCTION_ARGS)
 	int32		range_count = 0;
 	int32		range_capacity = 8;
 	RangeType  *range;
-	RangeType **ranges = palloc(range_capacity * sizeof(RangeType *));
+	RangeType **ranges = palloc_array(RangeType *, range_capacity);
 	MultirangeIOData *cache;
 	MultirangeType *ret;
 	MultirangeParseState parse_state;
@@ -348,7 +348,7 @@ multirange_recv(PG_FUNCTION_ARGS)
 	cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_receive);
 
 	range_count = pq_getmsgint(buf, 4);
-	ranges = palloc(range_count * sizeof(RangeType *));
+	ranges = palloc_array(RangeType *, range_count);
 
 	initStringInfo(&tmpbuf);
 	for (int i = 0; i < range_count; i++)
@@ -836,7 +836,7 @@ multirange_deserialize(TypeCacheEntry *rangetyp,
 	{
 		int			i;
 
-		*ranges = palloc(*range_count * sizeof(RangeType *));
+		*ranges = palloc_array(RangeType *, *range_count);
 		for (i = 0; i < *range_count; i++)
 			(*ranges)[i] = multirange_get_range(rangetyp, multirange, i);
 	}
@@ -2818,7 +2818,7 @@ multirange_unnest(PG_FUNCTION_ARGS)
 		mr = PG_GETARG_MULTIRANGE_P(0);
 
 		/* allocate memory for user context */
-		fctx = (multirange_unnest_fctx *) palloc(sizeof(multirange_unnest_fctx));
+		fctx = palloc_object(multirange_unnest_fctx);
 
 		/* initialize state */
 		fctx->mr = mr;
diff --git a/src/backend/utils/adt/multirangetypes_selfuncs.c b/src/backend/utils/adt/multirangetypes_selfuncs.c
index 21f0205d803..fc5a4354fce 100644
--- a/src/backend/utils/adt/multirangetypes_selfuncs.c
+++ b/src/backend/utils/adt/multirangetypes_selfuncs.c
@@ -496,8 +496,8 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
 	 * bounds.
 	 */
 	nhist = hslot.nvalues;
-	hist_lower = (RangeBound *) palloc(sizeof(RangeBound) * nhist);
-	hist_upper = (RangeBound *) palloc(sizeof(RangeBound) * nhist);
+	hist_lower = palloc_array(RangeBound, nhist);
+	hist_upper = palloc_array(RangeBound, nhist);
 	for (i = 0; i < nhist; i++)
 	{
 		bool		empty;
diff --git a/src/backend/utils/adt/multixactfuncs.c b/src/backend/utils/adt/multixactfuncs.c
index e74ea938348..a428e140bc4 100644
--- a/src/backend/utils/adt/multixactfuncs.c
+++ b/src/backend/utils/adt/multixactfuncs.c
@@ -50,7 +50,7 @@ pg_get_multixact_members(PG_FUNCTION_ARGS)
 		funccxt = SRF_FIRSTCALL_INIT();
 		oldcxt = MemoryContextSwitchTo(funccxt->multi_call_memory_ctx);
 
-		multi = palloc(sizeof(mxact));
+		multi = palloc_object(mxact);
 		/* no need to allow for old values here */
 		multi->nmembers = GetMultiXactIdMembers(mxid, &multi->members, false,
 												false);
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index 3cb0ab6829a..3a2002097dd 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -75,7 +75,7 @@ network_in(char *src, bool is_cidr, Node *escontext)
 	int			bits;
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = (inet *) palloc0_object(inet);
 
 	/*
 	 * First, check to see if this is an IPv6 or IPv4 address.  IPv6 addresses
@@ -196,7 +196,7 @@ network_recv(StringInfo buf, bool is_cidr)
 				i;
 
 	/* make sure any unused bits in a CIDR value are zeroed */
-	addr = (inet *) palloc0(sizeof(inet));
+	addr = palloc0_object(inet);
 
 	ip_family(addr) = pq_getmsgbyte(buf);
 	if (ip_family(addr) != PGSQL_AF_INET &&
@@ -363,7 +363,7 @@ cidr_set_masklen(PG_FUNCTION_ARGS)
 inet *
 cidr_set_masklen_internal(const inet *src, int bits)
 {
-	inet	   *dst = (inet *) palloc0(sizeof(inet));
+	inet	   *dst = palloc0_object(inet);
 
 	ip_family(dst) = ip_family(src);
 	ip_bits(dst) = bits;
@@ -444,7 +444,7 @@ network_sortsupport(PG_FUNCTION_ARGS)
 
 		oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
 
-		uss = palloc(sizeof(network_sortsupport_state));
+		uss = palloc_object(network_sortsupport_state);
 		uss->input_count = 0;
 		uss->estimating = true;
 		initHyperLogLog(&uss->abbr_card, 10);
@@ -1227,7 +1227,7 @@ network_broadcast(PG_FUNCTION_ARGS)
 			   *b;
 
 	/* make sure any unused bits are zeroed */
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	maxbytes = ip_addrsize(ip);
 	bits = ip_bits(ip);
@@ -1271,7 +1271,7 @@ network_network(PG_FUNCTION_ARGS)
 			   *b;
 
 	/* make sure any unused bits are zeroed */
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	bits = ip_bits(ip);
 	a = ip_addr(ip);
@@ -1314,7 +1314,7 @@ network_netmask(PG_FUNCTION_ARGS)
 	unsigned char *b;
 
 	/* make sure any unused bits are zeroed */
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	bits = ip_bits(ip);
 	b = ip_addr(dst);
@@ -1357,7 +1357,7 @@ network_hostmask(PG_FUNCTION_ARGS)
 	unsigned char *b;
 
 	/* make sure any unused bits are zeroed */
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	maxbytes = ip_addrsize(ip);
 	bits = ip_maxbits(ip) - ip_bits(ip);
@@ -1792,7 +1792,7 @@ inetnot(PG_FUNCTION_ARGS)
 	inet	   *ip = PG_GETARG_INET_PP(0);
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	{
 		int			nb = ip_addrsize(ip);
@@ -1818,7 +1818,7 @@ inetand(PG_FUNCTION_ARGS)
 	inet	   *ip2 = PG_GETARG_INET_PP(1);
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	if (ip_family(ip) != ip_family(ip2))
 		ereport(ERROR,
@@ -1850,7 +1850,7 @@ inetor(PG_FUNCTION_ARGS)
 	inet	   *ip2 = PG_GETARG_INET_PP(1);
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	if (ip_family(ip) != ip_family(ip2))
 		ereport(ERROR,
@@ -1880,7 +1880,7 @@ internal_inetpl(inet *ip, int64 addend)
 {
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	{
 		int			nb = ip_addrsize(ip);
diff --git a/src/backend/utils/adt/network_gist.c b/src/backend/utils/adt/network_gist.c
index a08c4953789..30145f5985a 100644
--- a/src/backend/utils/adt/network_gist.c
+++ b/src/backend/utils/adt/network_gist.c
@@ -475,7 +475,7 @@ build_inet_union_key(int family, int minbits, int commonbits,
 	GistInetKey *result;
 
 	/* Make sure any unused bits are zeroed. */
-	result = (GistInetKey *) palloc0(sizeof(GistInetKey));
+	result = palloc0_object(GistInetKey);
 
 	gk_ip_family(result) = family;
 	gk_ip_minbits(result) = minbits;
@@ -546,13 +546,13 @@ inet_gist_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)
 	{
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		if (DatumGetPointer(entry->key) != NULL)
 		{
 			inet	   *in = DatumGetInetPP(entry->key);
 			GistInetKey *r;
 
-			r = (GistInetKey *) palloc0(sizeof(GistInetKey));
+			r = palloc0_object(GistInetKey);
 
 			gk_ip_family(r) = ip_family(in);
 			gk_ip_minbits(r) = ip_bits(in);
@@ -594,14 +594,14 @@ inet_gist_fetch(PG_FUNCTION_ARGS)
 	GISTENTRY  *retval;
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	ip_family(dst) = gk_ip_family(key);
 	ip_bits(dst) = gk_ip_minbits(key);
 	memcpy(ip_addr(dst), gk_ip_addr(key), ip_addrsize(dst));
 	SET_INET_VARSIZE(dst);
 
-	retval = palloc(sizeof(GISTENTRY));
+	retval = palloc_object(GISTENTRY);
 	gistentryinit(*retval, InetPGetDatum(dst), entry->rel, entry->page,
 				  entry->offset, false);
 
diff --git a/src/backend/utils/adt/network_spgist.c b/src/backend/utils/adt/network_spgist.c
index a84747d9275..2f1e58e9b5c 100644
--- a/src/backend/utils/adt/network_spgist.c
+++ b/src/backend/utils/adt/network_spgist.c
@@ -196,8 +196,8 @@ inet_spg_picksplit(PG_FUNCTION_ARGS)
 
 	/* Don't need labels; allocate output arrays */
 	out->nodeLabels = NULL;
-	out->mapTuplesToNodes = (int *) palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = (Datum *) palloc(sizeof(Datum) * in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples); 
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	if (differentFamilies)
 	{
@@ -301,7 +301,7 @@ inet_spg_inner_consistent(PG_FUNCTION_ARGS)
 
 	if (which)
 	{
-		out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
+		out->nodeNumbers = palloc_array(int, in->nNodes);
 
 		for (i = 0; i < in->nNodes; i++)
 		{
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 2501007d981..6e8102a0459 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -1759,8 +1759,7 @@ generate_series_step_numeric(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		fctx = (generate_series_numeric_fctx *)
-			palloc(sizeof(generate_series_numeric_fctx));
+		fctx = palloc_object(generate_series_numeric_fctx);
 
 		/*
 		 * Use fctx to keep state from call to call. Seed current with the
@@ -2117,7 +2116,7 @@ numeric_sortsupport(PG_FUNCTION_ARGS)
 		NumericSortSupport *nss;
 		MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
 
-		nss = palloc(sizeof(NumericSortSupport));
+		nss = palloc_object(NumericSortSupport);
 
 		/*
 		 * palloc a buffer for handling unaligned packed values in addition to
@@ -4754,7 +4753,7 @@ makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
 
 	old_context = MemoryContextSwitchTo(agg_context);
 
-	state = (NumericAggState *) palloc0(sizeof(NumericAggState));
+	state = palloc0_object(NumericAggState);
 	state->calcSumX2 = calcSumX2;
 	state->agg_context = agg_context;
 
@@ -4772,7 +4771,7 @@ makeNumericAggStateCurrentContext(bool calcSumX2)
 {
 	NumericAggState *state;
 
-	state = (NumericAggState *) palloc0(sizeof(NumericAggState));
+	state = palloc0_object(NumericAggState);
 	state->calcSumX2 = calcSumX2;
 	state->agg_context = CurrentMemoryContext;
 
@@ -5418,7 +5417,7 @@ makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
 
 	old_context = MemoryContextSwitchTo(agg_context);
 
-	state = (Int128AggState *) palloc0(sizeof(Int128AggState));
+	state = palloc0_object(Int128AggState);
 	state->calcSumX2 = calcSumX2;
 
 	MemoryContextSwitchTo(old_context);
@@ -5435,7 +5434,7 @@ makeInt128AggStateCurrentContext(bool calcSumX2)
 {
 	Int128AggState *state;
 
-	state = (Int128AggState *) palloc0(sizeof(Int128AggState));
+	state = palloc0_object(Int128AggState);
 	state->calcSumX2 = calcSumX2;
 
 	return state;
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index 2121cc05f28..ac3963fc3e0 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -153,7 +153,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
 		qcontext = fcinfo->flinfo->fn_mcxt;
 		oldcontext = MemoryContextSwitchTo(qcontext);
 
-		qstate = (OSAPerQueryState *) palloc0(sizeof(OSAPerQueryState));
+		qstate = palloc0_object(OSAPerQueryState);
 		qstate->aggref = aggref;
 		qstate->qcontext = qcontext;
 
@@ -278,7 +278,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
 	/* Now build the stuff we need in group-lifespan context */
 	oldcontext = MemoryContextSwitchTo(gcontext);
 
-	osastate = (OSAPerGroupState *) palloc(sizeof(OSAPerGroupState));
+	osastate = palloc_object(OSAPerGroupState);
 	osastate->qstate = qstate;
 	osastate->gcontext = gcontext;
 
diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c
index 716f005066a..63b30ee572b 100644
--- a/src/backend/utils/adt/pg_locale_libc.c
+++ b/src/backend/utils/adt/pg_locale_libc.c
@@ -485,7 +485,7 @@ strlower_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 				 errmsg("out of memory")));
 
 	/* Output workspace cannot have more codes than input bytes */
-	workspace = (wchar_t *) palloc((srclen + 1) * sizeof(wchar_t));
+	workspace = palloc_array(wchar_t, srclen + 1);
 
 	char2wchar(workspace, srclen + 1, src, srclen, loc);
 
@@ -590,7 +590,7 @@ strtitle_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 				 errmsg("out of memory")));
 
 	/* Output workspace cannot have more codes than input bytes */
-	workspace = (wchar_t *) palloc((srclen + 1) * sizeof(wchar_t));
+	workspace = palloc_array(wchar_t, srclen + 1);
 
 	char2wchar(workspace, srclen + 1, src, srclen, loc);
 
@@ -683,7 +683,7 @@ strupper_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 				 errmsg("out of memory")));
 
 	/* Output workspace cannot have more codes than input bytes */
-	workspace = (wchar_t *) palloc((srclen + 1) * sizeof(wchar_t));
+	workspace = palloc_array(wchar_t, srclen + 1);
 
 	char2wchar(workspace, srclen + 1, src, srclen, loc);
 
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index 065a8000cf2..e31ebd0a2de 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -1258,7 +1258,7 @@ range_minus_multi(PG_FUNCTION_ARGS)
 			elog(ERROR, "range types do not match");
 
 		/* allocate memory for user context */
-		fctx = (struct range_minus_multi_fctx *) palloc(sizeof(struct range_minus_multi_fctx));
+		fctx = palloc_object(struct range_minus_multi_fctx);
 
 		/*
 		 * Initialize state. We can't store the range typcache in fn_extra
diff --git a/src/backend/utils/adt/rangetypes_gist.c b/src/backend/utils/adt/rangetypes_gist.c
index a60ee985e74..33c705e6a87 100644
--- a/src/backend/utils/adt/rangetypes_gist.c
+++ b/src/backend/utils/adt/rangetypes_gist.c
@@ -251,7 +251,7 @@ multirange_gist_compress(PG_FUNCTION_ARGS)
 		MultirangeType *mr = DatumGetMultirangeTypeP(entry->key);
 		RangeType  *r;
 		TypeCacheEntry *typcache;
-		GISTENTRY  *retval = palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
 		r = multirange_get_union_range(typcache->rngtype, mr);
@@ -1240,8 +1240,7 @@ range_gist_single_sorting_split(TypeCacheEntry *typcache,
 
 	maxoff = entryvec->n - 1;
 
-	sortItems = (SingleBoundSortItem *)
-		palloc(maxoff * sizeof(SingleBoundSortItem));
+	sortItems = palloc_array(SingleBoundSortItem, maxoff);
 
 	/*
 	 * Prepare auxiliary array and sort the values.
@@ -1343,8 +1342,8 @@ range_gist_double_sorting_split(TypeCacheEntry *typcache,
 	context.first = true;
 
 	/* Allocate arrays for sorted range bounds */
-	by_lower = (NonEmptyRange *) palloc(nentries * sizeof(NonEmptyRange));
-	by_upper = (NonEmptyRange *) palloc(nentries * sizeof(NonEmptyRange));
+	by_lower = palloc_array(NonEmptyRange, nentries);
+	by_upper = palloc_array(NonEmptyRange, nentries);
 
 	/* Fill arrays of bounds */
 	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
@@ -1499,8 +1498,8 @@ range_gist_double_sorting_split(TypeCacheEntry *typcache,
 	 */
 
 	/* Allocate vectors for results */
-	v->spl_left = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
-	v->spl_right = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
+	v->spl_left = palloc_array(OffsetNumber, nentries);
+	v->spl_right = palloc_array(OffsetNumber, nentries);
 	v->spl_nleft = 0;
 	v->spl_nright = 0;
 
@@ -1509,7 +1508,7 @@ range_gist_double_sorting_split(TypeCacheEntry *typcache,
 	 * either group without affecting overlap along selected axis.
 	 */
 	common_entries_count = 0;
-	common_entries = (CommonEntry *) palloc(nentries * sizeof(CommonEntry));
+	common_entries = palloc_array(CommonEntry, nentries);
 
 	/*
 	 * Distribute entries which can be distributed unambiguously, and collect
diff --git a/src/backend/utils/adt/rangetypes_selfuncs.c b/src/backend/utils/adt/rangetypes_selfuncs.c
index d85252cafb2..27d736a40e5 100644
--- a/src/backend/utils/adt/rangetypes_selfuncs.c
+++ b/src/backend/utils/adt/rangetypes_selfuncs.c
@@ -412,8 +412,8 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
 	 * bounds.
 	 */
 	nhist = hslot.nvalues;
-	hist_lower = (RangeBound *) palloc(sizeof(RangeBound) * nhist);
-	hist_upper = (RangeBound *) palloc(sizeof(RangeBound) * nhist);
+	hist_lower = palloc_array(RangeBound, nhist);
+	hist_upper = palloc_array(RangeBound, nhist);
 	for (i = 0; i < nhist; i++)
 	{
 		range_deserialize(typcache, DatumGetRangeTypeP(hslot.values[i]),
diff --git a/src/backend/utils/adt/rangetypes_spgist.c b/src/backend/utils/adt/rangetypes_spgist.c
index be519654880..14e5d6065f8 100644
--- a/src/backend/utils/adt/rangetypes_spgist.c
+++ b/src/backend/utils/adt/rangetypes_spgist.c
@@ -216,8 +216,8 @@ spg_range_quad_picksplit(PG_FUNCTION_ARGS)
 								  RangeTypeGetOid(DatumGetRangeTypeP(in->datums[0])));
 
 	/* Allocate memory for bounds */
-	lowerBounds = palloc(sizeof(RangeBound) * in->nTuples);
-	upperBounds = palloc(sizeof(RangeBound) * in->nTuples);
+	lowerBounds = palloc_array(RangeBound, in->nTuples);
+	upperBounds = palloc_array(RangeBound, in->nTuples);
 	j = 0;
 
 	/* Deserialize bounds of ranges, count non-empty ranges */
@@ -243,8 +243,8 @@ spg_range_quad_picksplit(PG_FUNCTION_ARGS)
 		out->prefixDatum = PointerGetDatum(NULL);
 		out->nodeLabels = NULL;
 
-		out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
-		out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
+		out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+		out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 		/* Place all ranges into node 0 */
 		for (i = 0; i < in->nTuples; i++)
@@ -273,8 +273,8 @@ spg_range_quad_picksplit(PG_FUNCTION_ARGS)
 	out->nNodes = (in->level == 0) ? 5 : 4;
 	out->nodeLabels = NULL;		/* we don't need node labels */
 
-	out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	/*
 	 * Assign ranges to corresponding nodes according to quadrants relative to
@@ -316,7 +316,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
 	{
 		/* Report that all nodes should be visited */
 		out->nNodes = in->nNodes;
-		out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
+		out->nodeNumbers = palloc_array(int, in->nNodes);
 		for (i = 0; i < in->nNodes; i++)
 			out->nodeNumbers[i] = i;
 		PG_RETURN_VOID();
@@ -732,9 +732,9 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
 	}
 
 	/* We must descend into the quadrant(s) identified by 'which' */
-	out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
+	out->nodeNumbers = palloc_array(int, in->nNodes);
 	if (needPrevious)
-		out->traversalValues = (void **) palloc(sizeof(void *) * in->nNodes);
+		out->traversalValues = palloc_array(void *, in->nNodes);
 	out->nNodes = 0;
 
 	/*
diff --git a/src/backend/utils/adt/rangetypes_typanalyze.c b/src/backend/utils/adt/rangetypes_typanalyze.c
index 36e885af2dd..45ea6cbc780 100644
--- a/src/backend/utils/adt/rangetypes_typanalyze.c
+++ b/src/backend/utils/adt/rangetypes_typanalyze.c
@@ -151,9 +151,9 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 	has_subdiff = OidIsValid(typcache->rng_subdiff_finfo.fn_oid);
 
 	/* Allocate memory to hold range bounds and lengths of the sample ranges. */
-	lowers = (RangeBound *) palloc(sizeof(RangeBound) * samplerows);
-	uppers = (RangeBound *) palloc(sizeof(RangeBound) * samplerows);
-	lengths = (float8 *) palloc(sizeof(float8) * samplerows);
+	lowers = palloc_array(RangeBound, samplerows);
+	uppers = palloc_array(RangeBound, samplerows);
+	lengths = palloc_array(float8, samplerows);
 
 	/* Loop over the sample ranges. */
 	for (range_no = 0; range_no < samplerows; range_no++)
@@ -401,7 +401,7 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 		stats->statypalign[slot_idx] = 'd';
 
 		/* Store the fraction of empty ranges */
-		emptyfrac = (float4 *) palloc(sizeof(float4));
+		emptyfrac = palloc_object(float4);
 		*emptyfrac = ((double) empty_cnt) / ((double) non_null_cnt);
 		stats->stanumbers[slot_idx] = emptyfrac;
 		stats->numnumbers[slot_idx] = 1;
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
index b0cdef9b19f..6542e8c1df0 100644
--- a/src/backend/utils/adt/regexp.c
+++ b/src/backend/utils/adt/regexp.c
@@ -189,7 +189,7 @@ RE_compile_and_cache(text *text_re, int cflags, Oid collation)
 	 */
 
 	/* Convert pattern string to wide characters */
-	pattern = (pg_wchar *) palloc((text_re_len + 1) * sizeof(pg_wchar));
+	pattern = palloc_array(pg_wchar, text_re_len + 1);
 	pattern_len = pg_mb2wchar_with_len(text_re_val,
 									   pattern,
 									   text_re_len);
@@ -329,7 +329,7 @@ RE_execute(regex_t *re, char *dat, int dat_len,
 	bool		match;
 
 	/* Convert data string to wide characters */
-	data = (pg_wchar *) palloc((dat_len + 1) * sizeof(pg_wchar));
+	data = palloc_array(pg_wchar, dat_len + 1);
 	data_len = pg_mb2wchar_with_len(dat, data, dat_len);
 
 	/* Perform RE match and return result */
@@ -1389,8 +1389,8 @@ regexp_match(PG_FUNCTION_ARGS)
 	Assert(matchctx->nmatches == 1);
 
 	/* Create workspace that build_regexp_match_result needs */
-	matchctx->elems = (Datum *) palloc(sizeof(Datum) * matchctx->npatterns);
-	matchctx->nulls = (bool *) palloc(sizeof(bool) * matchctx->npatterns);
+	matchctx->elems = palloc_array(Datum, matchctx->npatterns);
+	matchctx->nulls = palloc_array(bool, matchctx->npatterns);
 
 	PG_RETURN_DATUM(PointerGetDatum(build_regexp_match_result(matchctx)));
 }
@@ -1432,8 +1432,8 @@ regexp_matches(PG_FUNCTION_ARGS)
 										true, false, false);
 
 		/* Pre-create workspace that build_regexp_match_result needs */
-		matchctx->elems = (Datum *) palloc(sizeof(Datum) * matchctx->npatterns);
-		matchctx->nulls = (bool *) palloc(sizeof(bool) * matchctx->npatterns);
+		matchctx->elems = palloc_array(Datum, matchctx->npatterns);
+		matchctx->nulls = palloc_array(bool, matchctx->npatterns);
 
 		MemoryContextSwitchTo(oldcontext);
 		funcctx->user_fctx = matchctx;
@@ -1489,7 +1489,7 @@ setup_regexp_matches(text *orig_str, text *pattern, pg_re_flags *re_flags,
 					 bool ignore_degenerate,
 					 bool fetching_unmatched)
 {
-	regexp_matches_ctx *matchctx = palloc0(sizeof(regexp_matches_ctx));
+	regexp_matches_ctx *matchctx = palloc0_object(regexp_matches_ctx);
 	int			eml = pg_database_encoding_max_length();
 	int			orig_len;
 	pg_wchar   *wide_str;
@@ -1509,7 +1509,7 @@ setup_regexp_matches(text *orig_str, text *pattern, pg_re_flags *re_flags,
 
 	/* convert string to pg_wchar form for matching */
 	orig_len = VARSIZE_ANY_EXHDR(orig_str);
-	wide_str = (pg_wchar *) palloc(sizeof(pg_wchar) * (orig_len + 1));
+	wide_str = palloc_array(pg_wchar, orig_len + 1);
 	wide_len = pg_mb2wchar_with_len(VARDATA_ANY(orig_str), wide_str, orig_len);
 
 	/* set up the compiled pattern */
@@ -1532,7 +1532,7 @@ setup_regexp_matches(text *orig_str, text *pattern, pg_re_flags *re_flags,
 	}
 
 	/* temporary output space for RE package */
-	pmatch = palloc(sizeof(regmatch_t) * pmatch_len);
+	pmatch = palloc_array(regmatch_t, pmatch_len);
 
 	/*
 	 * the real output space (grown dynamically if needed)
@@ -1541,7 +1541,7 @@ setup_regexp_matches(text *orig_str, text *pattern, pg_re_flags *re_flags,
 	 * than at 2^27
 	 */
 	array_len = re_flags->glob ? 255 : 31;
-	matchctx->match_locs = (int *) palloc(sizeof(int) * array_len);
+	matchctx->match_locs = palloc_array(int, array_len);
 	array_idx = 0;
 
 	/* search for the pattern, perhaps repeatedly */
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index 9e5449f17d7..80f59a810fd 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -140,8 +140,8 @@ record_in(PG_FUNCTION_ARGS)
 		my_extra->ncolumns = ncolumns;
 	}
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	/*
 	 * Scan the string.  We use "buf" to accumulate the de-quoted data for
@@ -383,8 +383,8 @@ record_out(PG_FUNCTION_ARGS)
 		my_extra->ncolumns = ncolumns;
 	}
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	/* Break down the tuple into fields */
 	heap_deform_tuple(&tuple, tupdesc, values, nulls);
@@ -539,8 +539,8 @@ record_recv(PG_FUNCTION_ARGS)
 		my_extra->ncolumns = ncolumns;
 	}
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	/* Fetch number of columns user thinks it has */
 	usercols = pq_getmsgint(buf, 4);
@@ -741,8 +741,8 @@ record_send(PG_FUNCTION_ARGS)
 		my_extra->ncolumns = ncolumns;
 	}
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	/* Break down the tuple into fields */
 	heap_deform_tuple(&tuple, tupdesc, values, nulls);
@@ -1863,8 +1863,8 @@ hash_record(PG_FUNCTION_ARGS)
 	}
 
 	/* Break down the tuple into fields */
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 	heap_deform_tuple(&tuple, tupdesc, values, nulls);
 
 	for (int i = 0; i < ncolumns; i++)
@@ -1984,8 +1984,8 @@ hash_record_extended(PG_FUNCTION_ARGS)
 	}
 
 	/* Break down the tuple into fields */
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 	heap_deform_tuple(&tuple, tupdesc, values, nulls);
 
 	for (int i = 0; i < ncolumns; i++)
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 556ab057e5a..dd66357f5f8 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3713,7 +3713,7 @@ deparse_context_for(const char *aliasname, Oid relid)
 	deparse_namespace *dpns;
 	RangeTblEntry *rte;
 
-	dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
+	dpns = palloc0_object(deparse_namespace);
 
 	/* Build a minimal RTE for the rel */
 	rte = makeNode(RangeTblEntry);
@@ -3757,7 +3757,7 @@ deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
 {
 	deparse_namespace *dpns;
 
-	dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
+	dpns = palloc0_object(deparse_namespace);
 
 	/* Initialize fields that stay the same across the whole plan tree */
 	dpns->rtable = pstmt->rtable;
@@ -4051,7 +4051,7 @@ set_deparse_for_query(deparse_namespace *dpns, Query *query,
 	dpns->rtable_columns = NIL;
 	while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
 		dpns->rtable_columns = lappend(dpns->rtable_columns,
-									   palloc0(sizeof(deparse_columns)));
+									   palloc0_object(deparse_columns));
 
 	/* If it's a utility query, it won't have a jointree */
 	if (query->jointree)
@@ -4107,7 +4107,7 @@ set_simple_column_names(deparse_namespace *dpns)
 	dpns->rtable_columns = NIL;
 	while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
 		dpns->rtable_columns = lappend(dpns->rtable_columns,
-									   palloc0(sizeof(deparse_columns)));
+									   palloc0_object(deparse_columns));
 
 	/* Assign unique column aliases within each non-join RTE */
 	forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 540aa9628d7..c760b19db55 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -3683,7 +3683,7 @@ add_unique_group_var(PlannerInfo *root, List *varinfos,
 		}
 	}
 
-	varinfo = (GroupVarInfo *) palloc(sizeof(GroupVarInfo));
+	varinfo = palloc_object(GroupVarInfo);
 
 	varinfo->var = var;
 	varinfo->rel = vardata->rel;
@@ -4264,7 +4264,7 @@ estimate_multivariate_bucketsize(PlannerInfo *root, RelOptInfo *inner,
 				 * estimate_multivariate_ndistinct(), which doesn't care about
 				 * ndistinct and isdefault fields.  Thus, skip these fields.
 				 */
-				varinfo = (GroupVarInfo *) palloc0(sizeof(GroupVarInfo));
+				varinfo = palloc0_object(GroupVarInfo);
 				varinfo->var = expr;
 				varinfo->rel = root->simple_rel_array[relid];
 				varinfos = lappend(varinfos, varinfo);
diff --git a/src/backend/utils/adt/skipsupport.c b/src/backend/utils/adt/skipsupport.c
index 2bd35d2d272..2fcf5782ec8 100644
--- a/src/backend/utils/adt/skipsupport.c
+++ b/src/backend/utils/adt/skipsupport.c
@@ -38,7 +38,7 @@ PrepareSkipSupportFromOpclass(Oid opfamily, Oid opcintype, bool reverse)
 	if (!OidIsValid(skipSupportFunction))
 		return NULL;
 
-	sksup = palloc(sizeof(SkipSupportData));
+	sksup = palloc_object(SkipSupportData);
 	OidFunctionCall1(skipSupportFunction, PointerGetDatum(sksup));
 
 	if (reverse)
diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c
index 0cfb0bd3735..435d40fee3e 100644
--- a/src/backend/utils/adt/tid.c
+++ b/src/backend/utils/adt/tid.c
@@ -104,7 +104,7 @@ tidin(PG_FUNCTION_ARGS)
 						"tid", str)));
 	offsetNumber = (OffsetNumber) cvt;
 
-	result = (ItemPointer) palloc(sizeof(ItemPointerData));
+	result = (ItemPointer) palloc_object(ItemPointerData);
 
 	ItemPointerSet(result, blockNumber, offsetNumber);
 
@@ -146,7 +146,7 @@ tidrecv(PG_FUNCTION_ARGS)
 	blockNumber = pq_getmsgint(buf, sizeof(blockNumber));
 	offsetNumber = pq_getmsgint(buf, sizeof(offsetNumber));
 
-	result = (ItemPointer) palloc(sizeof(ItemPointerData));
+	result = (ItemPointer) palloc_object(ItemPointerData);
 
 	ItemPointerSet(result, blockNumber, offsetNumber);
 
@@ -300,7 +300,7 @@ currtid_internal(Relation rel, const ItemPointerData *tid)
 	Snapshot	snapshot;
 	TableScanDesc scan;
 
-	result = (ItemPointer) palloc(sizeof(ItemPointerData));
+	result = (ItemPointer) palloc_object(ItemPointerData);
 
 	aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
 								  ACL_SELECT);
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 156a4830ffd..ce5fa5e9ae7 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -937,7 +937,7 @@ interval_in(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 	}
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	switch (dtype)
 	{
@@ -1004,7 +1004,7 @@ interval_recv(PG_FUNCTION_ARGS)
 	int32		typmod = PG_GETARG_INT32(2);
 	Interval   *interval;
 
-	interval = (Interval *) palloc(sizeof(Interval));
+	interval = palloc_object(Interval);
 
 	interval->time = pq_getmsgint64(buf);
 	interval->day = pq_getmsgint(buf, sizeof(interval->day));
@@ -1331,7 +1331,7 @@ interval_scale(PG_FUNCTION_ARGS)
 	int32		typmod = PG_GETARG_INT32(1);
 	Interval   *result;
 
-	result = palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 	*result = *interval;
 
 	AdjustIntervalForTypmod(result, typmod, NULL);
@@ -1545,7 +1545,7 @@ make_interval(PG_FUNCTION_ARGS)
 	if (isinf(secs) || isnan(secs))
 		goto out_of_range;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/* years and months -> months */
 	if (pg_mul_s32_overflow(years, MONTHS_PER_YEAR, &result->month) ||
@@ -2827,7 +2827,7 @@ timestamp_mi(PG_FUNCTION_ARGS)
 	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle infinities.
@@ -2922,7 +2922,7 @@ interval_justify_interval(PG_FUNCTION_ARGS)
 	TimeOffset	wholeday;
 	int32		wholemonth;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 	result->month = span->month;
 	result->day = span->day;
 	result->time = span->time;
@@ -3001,7 +3001,7 @@ interval_justify_hours(PG_FUNCTION_ARGS)
 	Interval   *result;
 	TimeOffset	wholeday;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 	result->month = span->month;
 	result->day = span->day;
 	result->time = span->time;
@@ -3043,7 +3043,7 @@ interval_justify_days(PG_FUNCTION_ARGS)
 	Interval   *result;
 	int32		wholemonth;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 	result->month = span->month;
 	result->day = span->day;
 	result->time = span->time;
@@ -3445,7 +3445,7 @@ interval_um(PG_FUNCTION_ARGS)
 	Interval   *interval = PG_GETARG_INTERVAL_P(0);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 	interval_um_internal(interval, result);
 
 	PG_RETURN_INTERVAL_P(result);
@@ -3503,7 +3503,7 @@ interval_pl(PG_FUNCTION_ARGS)
 	Interval   *span2 = PG_GETARG_INTERVAL_P(1);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle infinities.
@@ -3559,7 +3559,7 @@ interval_mi(PG_FUNCTION_ARGS)
 	Interval   *span2 = PG_GETARG_INTERVAL_P(1);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle infinities.
@@ -3613,7 +3613,7 @@ interval_mul(PG_FUNCTION_ARGS)
 				orig_day = span->day;
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle NaN and infinities.
@@ -3743,7 +3743,7 @@ interval_div(PG_FUNCTION_ARGS)
 				orig_day = span->day;
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	if (factor == 0.0)
 		ereport(ERROR,
@@ -3972,7 +3972,7 @@ makeIntervalAggState(FunctionCallInfo fcinfo)
 
 	old_context = MemoryContextSwitchTo(agg_context);
 
-	state = (IntervalAggState *) palloc0(sizeof(IntervalAggState));
+	state = palloc0_object(IntervalAggState);
 
 	MemoryContextSwitchTo(old_context);
 
@@ -4159,7 +4159,7 @@ interval_avg_deserialize(PG_FUNCTION_ARGS)
 	initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
 						   VARSIZE_ANY_EXHDR(sstate));
 
-	result = (IntervalAggState *) palloc0(sizeof(IntervalAggState));
+	result = palloc0_object(IntervalAggState);
 
 	/* N */
 	result->N = pq_getmsgint64(&buf);
@@ -4226,7 +4226,7 @@ interval_avg(PG_FUNCTION_ARGS)
 					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 					 errmsg("interval out of range")));
 
-		result = (Interval *) palloc(sizeof(Interval));
+		result = palloc_object(Interval);
 		if (state->pInfcount > 0)
 			INTERVAL_NOEND(result);
 		else
@@ -4263,7 +4263,7 @@ interval_sum(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("interval out of range")));
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	if (state->pInfcount > 0)
 		INTERVAL_NOEND(result);
@@ -4296,7 +4296,7 @@ timestamp_age(PG_FUNCTION_ARGS)
 	struct pg_tm tt2,
 			   *tm2 = &tt2;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle infinities.
@@ -4444,7 +4444,7 @@ timestamptz_age(PG_FUNCTION_ARGS)
 	int			tz1;
 	int			tz2;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle infinities.
@@ -5117,7 +5117,7 @@ interval_trunc(PG_FUNCTION_ARGS)
 	struct pg_itm tt,
 			   *tm = &tt;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
 											VARSIZE_ANY_EXHDR(units),
@@ -6720,8 +6720,7 @@ generate_series_timestamp(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		fctx = (generate_series_timestamp_fctx *)
-			palloc(sizeof(generate_series_timestamp_fctx));
+		fctx = palloc_object(generate_series_timestamp_fctx);
 
 		/*
 		 * Use fctx to keep state from call to call. Seed current with the
@@ -6805,8 +6804,7 @@ generate_series_timestamptz_internal(FunctionCallInfo fcinfo)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		fctx = (generate_series_timestamptz_fctx *)
-			palloc(sizeof(generate_series_timestamptz_fctx));
+		fctx = palloc_object(generate_series_timestamptz_fctx);
 
 		/*
 		 * Use fctx to keep state from call to call. Seed current with the
diff --git a/src/backend/utils/adt/tsginidx.c b/src/backend/utils/adt/tsginidx.c
index 2712fd89df0..24a1cbe89ed 100644
--- a/src/backend/utils/adt/tsginidx.c
+++ b/src/backend/utils/adt/tsginidx.c
@@ -73,7 +73,7 @@ gin_extract_tsvector(PG_FUNCTION_ARGS)
 		int			i;
 		WordEntry  *we = ARRPTR(vector);
 
-		entries = (Datum *) palloc(sizeof(Datum) * vector->size);
+		entries = palloc_array(Datum, vector->size);
 
 		for (i = 0; i < vector->size; i++)
 		{
@@ -133,16 +133,16 @@ gin_extract_tsquery(PG_FUNCTION_ARGS)
 		}
 		*nentries = j;
 
-		entries = (Datum *) palloc(sizeof(Datum) * j);
-		partialmatch = *ptr_partialmatch = (bool *) palloc(sizeof(bool) * j);
+		entries = palloc_array(Datum, j);
+		partialmatch = *ptr_partialmatch = palloc_array(bool, j);
 
 		/*
 		 * Make map to convert item's number to corresponding operand's (the
 		 * same, entry's) number. Entry's number is used in check array in
 		 * consistent method. We use the same map for each entry.
 		 */
-		*extra_data = (Pointer *) palloc(sizeof(Pointer) * j);
-		map_item_operand = (int *) palloc0(sizeof(int) * query->size);
+		*extra_data = palloc_array(Pointer, j);
+		map_item_operand = palloc0_array(int, query->size);
 
 		/* Now rescan the VAL items and fill in the arrays */
 		j = 0;
diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c
index 935187b37c7..01e43f86214 100644
--- a/src/backend/utils/adt/tsgistidx.c
+++ b/src/backend/utils/adt/tsgistidx.c
@@ -212,7 +212,7 @@ gtsvector_compress(PG_FUNCTION_ARGS)
 			res = ressign;
 		}
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -231,7 +231,7 @@ gtsvector_compress(PG_FUNCTION_ARGS)
 		}
 
 		res = gtsvector_alloc(SIGNKEY | ALLISTRUE, siglen, sign);
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -251,7 +251,7 @@ gtsvector_decompress(PG_FUNCTION_ARGS)
 
 	if (key != (SignTSVector *) DatumGetPointer(entry->key))
 	{
-		GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
@@ -641,7 +641,7 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
 	v->spl_left = (OffsetNumber *) palloc(nbytes);
 	v->spl_right = (OffsetNumber *) palloc(nbytes);
 
-	cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2));
+	cache = palloc_array(CACHESIGN, maxoff + 2);
 	cache_sign = palloc(siglen * (maxoff + 2));
 
 	for (j = 0; j < maxoff + 2; j++)
@@ -688,7 +688,7 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
 	maxoff = OffsetNumberNext(maxoff);
 	fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff), siglen);
 	/* sort before ... */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c
index 717de8073d5..a0c990fdfa0 100644
--- a/src/backend/utils/adt/tsquery.c
+++ b/src/backend/utils/adt/tsquery.c
@@ -534,7 +534,7 @@ pushOperator(TSQueryParserState state, int8 oper, int16 distance)
 
 	Assert(oper == OP_NOT || oper == OP_AND || oper == OP_OR || oper == OP_PHRASE);
 
-	tmp = (QueryOperator *) palloc0(sizeof(QueryOperator));
+	tmp = palloc0_object(QueryOperator);
 	tmp->type = QI_OPR;
 	tmp->oper = oper;
 	tmp->distance = (oper == OP_PHRASE) ? distance : 0;
@@ -559,7 +559,7 @@ pushValue_internal(TSQueryParserState state, pg_crc32 valcrc, int distance, int
 				 errmsg("operand is too long in tsquery: \"%s\"",
 						state->buffer)));
 
-	tmp = (QueryOperand *) palloc0(sizeof(QueryOperand));
+	tmp = palloc0_object(QueryOperand);
 	tmp->type = QI_VAL;
 	tmp->weight = weight;
 	tmp->prefix = prefix;
@@ -617,7 +617,7 @@ pushStop(TSQueryParserState state)
 {
 	QueryOperand *tmp;
 
-	tmp = (QueryOperand *) palloc0(sizeof(QueryOperand));
+	tmp = palloc0_object(QueryOperand);
 	tmp->type = QI_VALSTOP;
 
 	state->polstr = lcons(tmp, state->polstr);
@@ -1101,7 +1101,7 @@ infix(INFIX *in, int parentPriority, bool rightPhraseOp)
 		nrm.curpol = in->curpol;
 		nrm.op = in->op;
 		nrm.buflen = 16;
-		nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+		nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 
 		/* get right operand */
 		infix(&nrm, priority, (op == OP_PHRASE));
@@ -1157,7 +1157,7 @@ tsqueryout(PG_FUNCTION_ARGS)
 	}
 	nrm.curpol = GETQUERY(query);
 	nrm.buflen = 32;
-	nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+	nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 	*(nrm.cur) = '\0';
 	nrm.op = GETOPERAND(query);
 	infix(&nrm, -1 /* lowest priority */ , false);
@@ -1385,7 +1385,7 @@ tsquerytree(PG_FUNCTION_ARGS)
 	{
 		nrm.curpol = q;
 		nrm.buflen = 32;
-		nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+		nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 		*(nrm.cur) = '\0';
 		nrm.op = GETOPERAND(query);
 		infix(&nrm, -1, false);
diff --git a/src/backend/utils/adt/tsquery_cleanup.c b/src/backend/utils/adt/tsquery_cleanup.c
index 590d7c7989c..45de2da900c 100644
--- a/src/backend/utils/adt/tsquery_cleanup.c
+++ b/src/backend/utils/adt/tsquery_cleanup.c
@@ -32,7 +32,7 @@ typedef struct NODE
 static NODE *
 maketree(QueryItem *in)
 {
-	NODE	   *node = (NODE *) palloc(sizeof(NODE));
+	NODE	   *node = palloc_object(NODE);
 
 	/* since this function recurses, it could be driven to stack overflow. */
 	check_stack_depth();
diff --git a/src/backend/utils/adt/tsquery_gist.c b/src/backend/utils/adt/tsquery_gist.c
index f7f94c1c760..55fc93ebef5 100644
--- a/src/backend/utils/adt/tsquery_gist.c
+++ b/src/backend/utils/adt/tsquery_gist.c
@@ -33,7 +33,7 @@ gtsquery_compress(PG_FUNCTION_ARGS)
 	{
 		TSQuerySign sign;
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		sign = makeTSQuerySign(DatumGetTSQuery(entry->key));
 
 		gistentryinit(*retval, TSQuerySignGetDatum(sign),
@@ -213,7 +213,7 @@ gtsquery_picksplit(PG_FUNCTION_ARGS)
 	datum_r = GETENTRY(entryvec, seed_2);
 
 	maxoff = OffsetNumberNext(maxoff);
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/src/backend/utils/adt/tsquery_op.c b/src/backend/utils/adt/tsquery_op.c
index bb77e923062..84bf070dff2 100644
--- a/src/backend/utils/adt/tsquery_op.c
+++ b/src/backend/utils/adt/tsquery_op.c
@@ -32,17 +32,17 @@ tsquery_numnode(PG_FUNCTION_ARGS)
 static QTNode *
 join_tsqueries(TSQuery a, TSQuery b, int8 operator, uint16 distance)
 {
-	QTNode	   *res = (QTNode *) palloc0(sizeof(QTNode));
+	QTNode	   *res = palloc0_object(QTNode);
 
 	res->flags |= QTN_NEEDFREE;
 
-	res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
+	res->valnode = palloc0_object(QueryItem);
 	res->valnode->type = QI_OPR;
 	res->valnode->qoperator.oper = operator;
 	if (operator == OP_PHRASE)
 		res->valnode->qoperator.distance = distance;
 
-	res->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
+	res->child = palloc0_array(QTNode *, 2);
 	res->child[0] = QT2QTN(GETQUERY(b), GETOPERAND(b));
 	res->child[1] = QT2QTN(GETQUERY(a), GETOPERAND(a));
 	res->nchild = 2;
@@ -165,15 +165,15 @@ tsquery_not(PG_FUNCTION_ARGS)
 	if (a->size == 0)
 		PG_RETURN_POINTER(a);
 
-	res = (QTNode *) palloc0(sizeof(QTNode));
+	res = palloc0_object(QTNode);
 
 	res->flags |= QTN_NEEDFREE;
 
-	res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
+	res->valnode = palloc0_object(QueryItem);
 	res->valnode->type = QI_OPR;
 	res->valnode->qoperator.oper = OP_NOT;
 
-	res->child = (QTNode **) palloc0(sizeof(QTNode *));
+	res->child = palloc0_object(QTNode *);
 	res->child[0] = QT2QTN(GETQUERY(a), GETOPERAND(a));
 	res->nchild = 1;
 
@@ -272,7 +272,7 @@ collectTSQueryValues(TSQuery a, int *nvalues_p)
 	int			nvalues = 0;
 	int			i;
 
-	values = (char **) palloc(sizeof(char *) * a->size);
+	values = palloc_array(char *, a->size);
 
 	for (i = 0; i < a->size; i++)
 	{
diff --git a/src/backend/utils/adt/tsquery_util.c b/src/backend/utils/adt/tsquery_util.c
index 1c24b041aa2..2ccfc9d3303 100644
--- a/src/backend/utils/adt/tsquery_util.c
+++ b/src/backend/utils/adt/tsquery_util.c
@@ -24,7 +24,7 @@
 QTNode *
 QT2QTN(QueryItem *in, char *operand)
 {
-	QTNode	   *node = (QTNode *) palloc0(sizeof(QTNode));
+	QTNode	   *node = palloc0_object(QTNode);
 
 	/* since this function recurses, it could be driven to stack overflow. */
 	check_stack_depth();
@@ -33,7 +33,7 @@ QT2QTN(QueryItem *in, char *operand)
 
 	if (in->type == QI_OPR)
 	{
-		node->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
+		node->child = palloc0_array(QTNode *, 2);
 		node->child[0] = QT2QTN(in + 1, operand);
 		node->sign = node->child[0]->sign;
 		if (in->qoperator.oper == OP_NOT)
@@ -226,7 +226,7 @@ QTNTernary(QTNode *in)
 			int			oldnchild = in->nchild;
 
 			in->nchild += cc->nchild - 1;
-			in->child = (QTNode **) repalloc(in->child, in->nchild * sizeof(QTNode *));
+			in->child = repalloc_array(in->child, QTNode *, in->nchild);
 
 			if (i + 1 != oldnchild)
 				memmove(in->child + i + cc->nchild, in->child + i + 1,
@@ -262,10 +262,10 @@ QTNBinary(QTNode *in)
 
 	while (in->nchild > 2)
 	{
-		QTNode	   *nn = (QTNode *) palloc0(sizeof(QTNode));
+		QTNode	   *nn = palloc0_object(QTNode);
 
-		nn->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
-		nn->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
+		nn->valnode = palloc0_object(QueryItem);
+		nn->child = palloc0_array(QTNode *, 2);
 
 		nn->nchild = 2;
 		nn->flags = QTN_NEEDFREE;
@@ -400,10 +400,10 @@ QTNCopy(QTNode *in)
 	/* since this function recurses, it could be driven to stack overflow. */
 	check_stack_depth();
 
-	out = (QTNode *) palloc(sizeof(QTNode));
+	out = palloc_object(QTNode);
 
 	*out = *in;
-	out->valnode = (QueryItem *) palloc(sizeof(QueryItem));
+	out->valnode = palloc_object(QueryItem);
 	*(out->valnode) = *(in->valnode);
 	out->flags |= QTN_NEEDFREE;
 
@@ -418,7 +418,7 @@ QTNCopy(QTNode *in)
 	{
 		int			i;
 
-		out->child = (QTNode **) palloc(sizeof(QTNode *) * in->nchild);
+		out->child = palloc_array(QTNode *, in->nchild);
 
 		for (i = 0; i < in->nchild; i++)
 			out->child[i] = QTNCopy(in->child[i]);
diff --git a/src/backend/utils/adt/tsrank.c b/src/backend/utils/adt/tsrank.c
index e863aa58653..4a341848647 100644
--- a/src/backend/utils/adt/tsrank.c
+++ b/src/backend/utils/adt/tsrank.c
@@ -160,7 +160,7 @@ SortAndUniqItems(TSQuery q, int *size)
 			  **ptr,
 			  **prevptr;
 
-	ptr = res = (QueryOperand **) palloc(sizeof(QueryOperand *) * *size);
+	ptr = res = palloc_array(QueryOperand *, *size);
 
 	/* Collect all operands from the tree to res */
 	while ((*size)--)
@@ -225,7 +225,7 @@ calc_rank_and(const float *w, TSVector t, TSQuery q)
 		pfree(item);
 		return calc_rank_or(w, t, q);
 	}
-	pos = (WordEntryPosVector **) palloc0(sizeof(WordEntryPosVector *) * q->size);
+	pos = palloc0_array(WordEntryPosVector *, q->size);
 
 	/* A dummy WordEntryPos array to use when haspos is false */
 	posnull.npos = 1;
@@ -743,7 +743,7 @@ get_docrep(TSVector txt, QueryRepresentation *qr, int *doclen)
 				cur = 0;
 	DocRepresentation *doc;
 
-	doc = (DocRepresentation *) palloc(sizeof(DocRepresentation) * len);
+	doc = palloc_array(DocRepresentation, len);
 
 	/*
 	 * Iterate through query to make DocRepresentation for words and it's
@@ -815,7 +815,7 @@ get_docrep(TSVector txt, QueryRepresentation *qr, int *doclen)
 		 * Join QueryItem per WordEntry and its position
 		 */
 		storage.pos = doc->pos;
-		storage.data.query.items = palloc(sizeof(QueryItem *) * qr->query->size);
+		storage.data.query.items = palloc_array(QueryItem *, qr->query->size);
 		storage.data.query.items[0] = doc->data.map.item;
 		storage.data.query.nitem = 1;
 
@@ -832,7 +832,7 @@ get_docrep(TSVector txt, QueryRepresentation *qr, int *doclen)
 				*wptr = storage;
 				wptr++;
 				storage.pos = rptr->pos;
-				storage.data.query.items = palloc(sizeof(QueryItem *) * qr->query->size);
+				storage.data.query.items = palloc_array(QueryItem *, qr->query->size);
 				storage.data.query.items[0] = rptr->data.map.item;
 				storage.data.query.nitem = 1;
 			}
@@ -878,8 +878,7 @@ calc_rank_cd(const float4 *arrdata, TSVector txt, TSQuery query, int method)
 	}
 
 	qr.query = query;
-	qr.operandData = (QueryRepresentationOperand *)
-		palloc0(sizeof(QueryRepresentationOperand) * query->size);
+	qr.operandData = palloc0_array(QueryRepresentationOperand, query->size);
 
 	doc = get_docrep(txt, &qr, &doclen);
 	if (!doc)
diff --git a/src/backend/utils/adt/tsvector.c b/src/backend/utils/adt/tsvector.c
index 1fa2e3729bf..39be10f45a4 100644
--- a/src/backend/utils/adt/tsvector.c
+++ b/src/backend/utils/adt/tsvector.c
@@ -202,8 +202,8 @@ tsvectorin(PG_FUNCTION_ARGS)
 	state = init_tsvector_parser(buf, 0, escontext);
 
 	arrlen = 64;
-	arr = (WordEntryIN *) palloc(sizeof(WordEntryIN) * arrlen);
-	cur = tmpbuf = (char *) palloc(buflen);
+	arr = palloc_array(WordEntryIN, arrlen); 
+	cur = tmpbuf = palloc_array(char, buflen);
 
 	while (gettoken_tsvector(state, &token, &toklen, &pos, &poslen, NULL))
 	{
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index c752cbe5463..b809089ac5d 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -1212,7 +1212,7 @@ checkclass_str(CHKVAL *chkval, WordEntry *entry, QueryOperand *val,
 			/*
 			 * Filter position information by weights
 			 */
-			dptr = data->pos = palloc(sizeof(WordEntryPos) * posvec->npos);
+			dptr = data->pos = palloc_array(WordEntryPos, posvec->npos);
 			data->allocated = true;
 
 			/* Is there a position with a matching weight? */
@@ -1391,12 +1391,12 @@ checkcondition_str(void *checkval, QueryOperand *val, ExecPhraseData *data)
 						if (totalpos == 0)
 						{
 							totalpos = 256;
-							allpos = palloc(sizeof(WordEntryPos) * totalpos);
+							allpos = palloc_array(WordEntryPos, totalpos);
 						}
 						else
 						{
 							totalpos *= 2;
-							allpos = repalloc(allpos, sizeof(WordEntryPos) * totalpos);
+							allpos = repalloc_array(allpos, WordEntryPos, totalpos);
 						}
 					}
 
@@ -2456,7 +2456,7 @@ ts_setup_firstcall(FunctionCallInfo fcinfo, FuncCallContext *funcctx,
 
 	oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-	stat->stack = palloc0(sizeof(StatEntry *) * (stat->maxdepth + 1));
+	stat->stack = palloc0_array(StatEntry *, stat->maxdepth + 1);
 	stat->stackpos = 0;
 
 	node = stat->root;
@@ -2839,7 +2839,7 @@ tsvector_update_trigger(PG_FUNCTION_ARGS, bool config_column)
 	prs.lenwords = 32;
 	prs.curwords = 0;
 	prs.pos = 0;
-	prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);
+	prs.words = palloc_array(ParsedWord, prs.lenwords);
 
 	/* find all words in indexable column(s) */
 	for (i = 2; i < trigger->tgnargs; i++)
diff --git a/src/backend/utils/adt/tsvector_parser.c b/src/backend/utils/adt/tsvector_parser.c
index e1620d3ed1f..395c3403b9a 100644
--- a/src/backend/utils/adt/tsvector_parser.c
+++ b/src/backend/utils/adt/tsvector_parser.c
@@ -58,7 +58,7 @@ init_tsvector_parser(char *input, int flags, Node *escontext)
 {
 	TSVectorParseState state;
 
-	state = (TSVectorParseState) palloc(sizeof(struct TSVectorParseStateData));
+	state = palloc_object(struct TSVectorParseStateData);
 	state->prsbuf = input;
 	state->bufstart = input;
 	state->len = 32;
@@ -322,13 +322,13 @@ gettoken_tsvector(TSVectorParseState state,
 				if (posalen == 0)
 				{
 					posalen = 4;
-					pos = (WordEntryPos *) palloc(sizeof(WordEntryPos) * posalen);
+					pos = palloc_array(WordEntryPos, posalen); 
 					npos = 0;
 				}
 				else if (npos + 1 >= posalen)
 				{
 					posalen *= 2;
-					pos = (WordEntryPos *) repalloc(pos, sizeof(WordEntryPos) * posalen);
+					pos = repalloc_array(pos, WordEntryPos, posalen);
 				}
 				npos++;
 				WEP_SETPOS(pos[npos - 1], LIMITPOS(atoi(state->prsbuf)));
diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c
index e5f27ff892b..493aac32799 100644
--- a/src/backend/utils/adt/uuid.c
+++ b/src/backend/utils/adt/uuid.c
@@ -80,7 +80,7 @@ uuid_in(PG_FUNCTION_ARGS)
 	char	   *uuid_str = PG_GETARG_CSTRING(0);
 	pg_uuid_t  *uuid;
 
-	uuid = (pg_uuid_t *) palloc(sizeof(*uuid));
+	uuid = palloc_object(pg_uuid_t);
 	string_to_uuid(uuid_str, uuid, fcinfo->context);
 	PG_RETURN_UUID_P(uuid);
 }
@@ -288,7 +288,7 @@ uuid_sortsupport(PG_FUNCTION_ARGS)
 
 		oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
 
-		uss = palloc(sizeof(uuid_sortsupport_state));
+		uss = palloc_object(uuid_sortsupport_state);
 		uss->input_count = 0;
 		uss->estimating = true;
 		initHyperLogLog(&uss->abbr_card, 10);
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 3894457ab40..c26d57ea2ec 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -1692,7 +1692,7 @@ varstr_sortsupport(SortSupport ssup, Oid typid, Oid collid)
 	 */
 	if (abbreviate || !collate_c)
 	{
-		sss = palloc(sizeof(VarStringSortSupport));
+		sss = palloc_object(VarStringSortSupport);
 		sss->buf1 = palloc(TEXTBUFLEN);
 		sss->buflen1 = TEXTBUFLEN;
 		sss->buf2 = palloc(TEXTBUFLEN);
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 41e775570ec..c8ab9d61c68 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -1255,7 +1255,7 @@ pg_xml_init(PgXmlStrictness strictness)
 	pg_xml_init_library();
 
 	/* Create error handling context structure */
-	errcxt = (PgXmlErrorContext *) palloc(sizeof(PgXmlErrorContext));
+	errcxt = palloc_object(PgXmlErrorContext);
 	errcxt->magic = ERRCXT_MAGIC;
 	errcxt->strictness = strictness;
 	errcxt->err_occurred = false;
@@ -4733,10 +4733,10 @@ XmlTableInitOpaque(TableFuncScanState *state, int natts)
 	XmlTableBuilderData *xtCxt;
 	PgXmlErrorContext *xmlerrcxt;
 
-	xtCxt = palloc0(sizeof(XmlTableBuilderData));
+	xtCxt = palloc0_object(XmlTableBuilderData);
 	xtCxt->magic = XMLTABLE_CONTEXT_MAGIC;
 	xtCxt->natts = natts;
-	xtCxt->xpathscomp = palloc0(sizeof(xmlXPathCompExprPtr) * natts);
+	xtCxt->xpathscomp = palloc0_array(xmlXPathCompExprPtr, natts);
 
 	xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
 
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 02ae7d5a831..84f1f80607e 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -920,7 +920,7 @@ InitCatCache(int id,
 	 */
 	if (CacheHdr == NULL)
 	{
-		CacheHdr = (CatCacheHeader *) palloc(sizeof(CatCacheHeader));
+		CacheHdr = palloc_object(CatCacheHeader);
 		slist_init(&CacheHdr->ch_caches);
 		CacheHdr->ch_ntup = 0;
 #ifdef CATCACHE_STATS
@@ -2243,7 +2243,7 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, Datum *arguments,
 	{
 		/* Set up keys for a negative cache entry */
 		oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-		ct = (CatCTup *) palloc(sizeof(CatCTup));
+		ct = palloc_object(CatCTup);
 
 		/*
 		 * Store keys - they'll point into separately allocated memory if not
diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index b9d5a5998be..7f03c94a974 100644
--- a/src/backend/utils/cache/evtcache.c
+++ b/src/backend/utils/cache/evtcache.c
@@ -172,7 +172,7 @@ BuildEventTriggerCache(void)
 		oldcontext = MemoryContextSwitchTo(EventTriggerCacheContext);
 
 		/* Allocate new cache item. */
-		item = palloc0(sizeof(EventTriggerCacheItem));
+		item = palloc0_object(EventTriggerCacheItem);
 		item->fnoid = form->evtfoid;
 		item->enabled = form->evtenabled;
 
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 06f736cab45..868f8f6188f 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -758,7 +758,7 @@ PrepareInplaceInvalidationState(void)
 	Assert(inplaceInvalInfo == NULL);
 
 	/* gone after WAL insertion CritSection ends, so use current context */
-	myInfo = (InvalidationInfo *) palloc0(sizeof(InvalidationInfo));
+	myInfo = palloc0_object(InvalidationInfo);
 
 	/* Stash our messages past end of the transactional messages, if any. */
 	if (transInvalInfo != NULL)
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index fa7cd7e06a7..5aa7a26d95c 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -702,8 +702,7 @@ get_op_index_interpretation(Oid opno)
 		if (cmptype == COMPARE_INVALID)
 			continue;
 
-		thisresult = (OpIndexInterpretation *)
-			palloc(sizeof(OpIndexInterpretation));
+		thisresult = palloc_object(OpIndexInterpretation);
 		thisresult->opfamily_id = op_form->amopfamily;
 		thisresult->cmptype = cmptype;
 		thisresult->oplefttype = op_form->amoplefttype;
@@ -748,8 +747,7 @@ get_op_index_interpretation(Oid opno)
 					continue;
 
 				/* OK, report it as COMPARE_NE */
-				thisresult = (OpIndexInterpretation *)
-					palloc(sizeof(OpIndexInterpretation));
+				thisresult = palloc_object(OpIndexInterpretation);
 				thisresult->opfamily_id = op_form->amopfamily;
 				thisresult->cmptype = COMPARE_NE;
 				thisresult->oplefttype = op_form->amoplefttype;
diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c
index f5d7d70def0..97f2ce33efe 100644
--- a/src/backend/utils/cache/partcache.c
+++ b/src/backend/utils/cache/partcache.c
@@ -167,18 +167,18 @@ RelationBuildPartitionKey(Relation relation)
 
 	/* Allocate assorted arrays in the partkeycxt, which we'll fill below */
 	oldcxt = MemoryContextSwitchTo(partkeycxt);
-	key->partattrs = (AttrNumber *) palloc0(key->partnatts * sizeof(AttrNumber));
-	key->partopfamily = (Oid *) palloc0(key->partnatts * sizeof(Oid));
-	key->partopcintype = (Oid *) palloc0(key->partnatts * sizeof(Oid));
-	key->partsupfunc = (FmgrInfo *) palloc0(key->partnatts * sizeof(FmgrInfo));
-
-	key->partcollation = (Oid *) palloc0(key->partnatts * sizeof(Oid));
-	key->parttypid = (Oid *) palloc0(key->partnatts * sizeof(Oid));
-	key->parttypmod = (int32 *) palloc0(key->partnatts * sizeof(int32));
-	key->parttyplen = (int16 *) palloc0(key->partnatts * sizeof(int16));
-	key->parttypbyval = (bool *) palloc0(key->partnatts * sizeof(bool));
-	key->parttypalign = (char *) palloc0(key->partnatts * sizeof(char));
-	key->parttypcoll = (Oid *) palloc0(key->partnatts * sizeof(Oid));
+	key->partattrs = (AttrNumber *) palloc0_array(AttrNumber, key->partnatts);
+	key->partopfamily = (Oid *) palloc0_array(Oid, key->partnatts);
+	key->partopcintype = (Oid *) palloc0_array(Oid, key->partnatts);
+	key->partsupfunc = (FmgrInfo *) palloc0_array(FmgrInfo, key->partnatts);
+
+	key->partcollation = (Oid *) palloc0_array(Oid, key->partnatts);
+	key->parttypid = (Oid *) palloc0_array(Oid, key->partnatts);
+	key->parttypmod = (int32 *) palloc0_array(int32, key->partnatts);
+	key->parttyplen = (int16 *) palloc0_array(int16, key->partnatts);
+	key->parttypbyval = (bool *) palloc0_array(bool, key->partnatts);
+	key->parttypalign = (char *) palloc0_array(char, key->partnatts);
+	key->parttypcoll = (Oid *) palloc0_array(Oid, key->partnatts);
 	MemoryContextSwitchTo(oldcxt);
 
 	/* determine support function number to search for */
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 6661d2c6b73..45261caaf47 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -207,7 +207,7 @@ CreateCachedPlan(RawStmt *raw_parse_tree,
 	 */
 	oldcxt = MemoryContextSwitchTo(source_context);
 
-	plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
+	plansource = palloc0_object(CachedPlanSource);
 	plansource->magic = CACHEDPLANSOURCE_MAGIC;
 	plansource->raw_parse_tree = copyObject(raw_parse_tree);
 	plansource->analyzed_parse_tree = NULL;
@@ -307,7 +307,7 @@ CreateOneShotCachedPlan(RawStmt *raw_parse_tree,
 	 * Create and fill the CachedPlanSource struct within the caller's memory
 	 * context.  Most fields are just left empty for the moment.
 	 */
-	plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
+	plansource = palloc0_object(CachedPlanSource);
 	plansource->magic = CACHEDPLANSOURCE_MAGIC;
 	plansource->raw_parse_tree = raw_parse_tree;
 	plansource->analyzed_parse_tree = NULL;
@@ -469,7 +469,7 @@ CompleteCachedPlan(CachedPlanSource *plansource,
 
 	if (num_params > 0)
 	{
-		plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
+		plansource->param_types = palloc_array(Oid, num_params);
 		memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
 	}
 	else
@@ -1119,7 +1119,7 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
 	/*
 	 * Create and fill the CachedPlan struct within the new context.
 	 */
-	plan = (CachedPlan *) palloc(sizeof(CachedPlan));
+	plan = palloc_object(CachedPlan);
 	plan->magic = CACHEDPLAN_MAGIC;
 	plan->stmt_list = plist;
 
@@ -1691,7 +1691,7 @@ CopyCachedPlan(CachedPlanSource *plansource)
 
 	oldcxt = MemoryContextSwitchTo(source_context);
 
-	newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
+	newsource = palloc0_object(CachedPlanSource);
 	newsource->magic = CACHEDPLANSOURCE_MAGIC;
 	newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
 	newsource->analyzed_parse_tree = copyObject(plansource->analyzed_parse_tree);
@@ -1700,8 +1700,7 @@ CopyCachedPlan(CachedPlanSource *plansource)
 	newsource->commandTag = plansource->commandTag;
 	if (plansource->num_params > 0)
 	{
-		newsource->param_types = (Oid *)
-			palloc(plansource->num_params * sizeof(Oid));
+		newsource->param_types = palloc_array(Oid, plansource->num_params);
 		memcpy(newsource->param_types, plansource->param_types,
 			   plansource->num_params * sizeof(Oid));
 	}
@@ -1840,7 +1839,7 @@ GetCachedExpression(Node *expr)
 
 	oldcxt = MemoryContextSwitchTo(cexpr_context);
 
-	cexpr = (CachedExpression *) palloc(sizeof(CachedExpression));
+	cexpr = palloc_object(CachedExpression);
 	cexpr->magic = CACHEDEXPR_MAGIC;
 	cexpr->expr = copyObject(expr);
 	cexpr->is_valid = true;
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 915d0bc9084..a4dc1cbe5ae 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -422,7 +422,7 @@ AllocateRelationDesc(Form_pg_class relp)
 	/*
 	 * allocate and zero space for new relation descriptor
 	 */
-	relation = (Relation) palloc0(sizeof(RelationData));
+	relation = palloc0_object(RelationData);
 
 	/* make sure relation is marked as having no open file yet */
 	relation->rd_smgr = NULL;
@@ -1902,7 +1902,7 @@ formrdesc(const char *relationName, Oid relationReltype,
 	/*
 	 * allocate new relation desc, clear all fields of reldesc
 	 */
-	relation = (Relation) palloc0(sizeof(RelationData));
+	relation = palloc0_object(RelationData);
 
 	/* make sure relation is marked as having no open file yet */
 	relation->rd_smgr = NULL;
@@ -1994,7 +1994,7 @@ formrdesc(const char *relationName, Oid relationReltype,
 	/* mark not-null status */
 	if (has_not_null)
 	{
-		TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
+		TupleConstr *constr = palloc0_object(TupleConstr);
 
 		constr->has_not_null = true;
 		relation->rd_att->constr = constr;
@@ -3579,7 +3579,7 @@ RelationBuildLocalRelation(const char *relname,
 	/*
 	 * allocate a new relation descriptor and fill in basic state fields.
 	 */
-	rel = (Relation) palloc0(sizeof(RelationData));
+	rel = palloc0_object(RelationData);
 
 	/* make sure relation is marked as having no open file yet */
 	rel->rd_smgr = NULL;
@@ -3627,7 +3627,7 @@ RelationBuildLocalRelation(const char *relname,
 
 	if (has_not_null)
 	{
-		TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
+		TupleConstr *constr = palloc0_object(TupleConstr);
 
 		constr->has_not_null = true;
 		rel->rd_att->constr = constr;
@@ -5670,9 +5670,9 @@ RelationGetExclusionInfo(Relation indexRelation,
 	indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
 
 	/* Allocate result space in caller context */
-	*operators = ops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	*procs = funcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	*strategies = strats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
+	*operators = ops = palloc_array(Oid, indnkeyatts);
+	*procs = funcs = palloc_array(Oid, indnkeyatts);
+	*strategies = strats = palloc_array(uint16, indnkeyatts);
 
 	/* Quick exit if we have the data cached already */
 	if (indexRelation->rd_exclstrats != NULL)
@@ -5763,9 +5763,9 @@ RelationGetExclusionInfo(Relation indexRelation,
 
 	/* Save a copy of the results in the relcache entry. */
 	oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
-	indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
+	indexRelation->rd_exclops = palloc_array(Oid, indnkeyatts);
+	indexRelation->rd_exclprocs = palloc_array(Oid, indnkeyatts);
+	indexRelation->rd_exclstrats = palloc_array(uint16, indnkeyatts);
 	memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
 	memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
 	memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
@@ -5959,7 +5959,7 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
 
 	/* Now save copy of the descriptor in the relcache entry. */
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-	relation->rd_pubdesc = palloc(sizeof(PublicationDesc));
+	relation->rd_pubdesc = palloc_object(PublicationDesc);
 	memcpy(relation->rd_pubdesc, pubdesc, sizeof(PublicationDesc));
 	MemoryContextSwitchTo(oldcxt);
 }
@@ -5967,7 +5967,7 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
 static bytea **
 CopyIndexAttOptions(bytea **srcopts, int natts)
 {
-	bytea	  **opts = palloc(sizeof(*opts) * natts);
+	bytea	  **opts = palloc_array(bytea *, natts);
 
 	for (int i = 0; i < natts; i++)
 	{
@@ -5999,7 +5999,7 @@ RelationGetIndexAttOptions(Relation relation, bool copy)
 		return copy ? CopyIndexAttOptions(opts, natts) : opts;
 
 	/* Get and parse opclass options. */
-	opts = palloc0(sizeof(*opts) * natts);
+	opts = palloc0_array(bytea *, natts);
 
 	for (i = 0; i < natts; i++)
 	{
@@ -6292,7 +6292,7 @@ load_relcache_init_file(bool shared)
 		/* mark not-null status */
 		if (has_not_null)
 		{
-			TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
+			TupleConstr *constr = palloc0_object(TupleConstr);
 
 			constr->has_not_null = true;
 			rel->rd_att->constr = constr;
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index 6a347698edf..0c17d99d021 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -2764,7 +2764,7 @@ load_enum_cache_data(TypeCacheEntry *tcache)
 	 * through.
 	 */
 	maxitems = 64;
-	items = (EnumItem *) palloc(sizeof(EnumItem) * maxitems);
+	items = palloc_array(EnumItem, maxitems);
 	numitems = 0;
 
 	/* Scan pg_enum for the members of the target enum type. */
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 29643c51439..4c5a9283208 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -1774,7 +1774,7 @@ CopyErrorData(void)
 	Assert(CurrentMemoryContext != ErrorContext);
 
 	/* Copy the struct itself */
-	newedata = (ErrorData *) palloc(sizeof(ErrorData));
+	newedata = palloc_object(ErrorData);
 	memcpy(newedata, edata, sizeof(ErrorData));
 
 	/*
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 5f2317211c9..f40879f0617 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -1436,7 +1436,7 @@ get_func_arg_info(HeapTuple procTup,
 								  &elems, NULL, &nelems);
 		if (nelems != numargs)	/* should not happen */
 			elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
-		*p_argnames = (char **) palloc(sizeof(char *) * numargs);
+		*p_argnames = palloc_array(char *, numargs);
 		for (i = 0; i < numargs; i++)
 			(*p_argnames)[i] = TextDatumGetCString(elems[i]);
 	}
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 98f9598cd78..4ed69ac7ba2 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -1260,7 +1260,7 @@ process_startup_options(Port *port, bool am_superuser)
 
 		maxac = 2 + (strlen(port->cmdline_options) + 1) / 2;
 
-		av = (char **) palloc(maxac * sizeof(char *));
+		av = palloc_array(char *, maxac);
 		ac = 0;
 
 		av[ac++] = "postgres";
diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index fb629ed5c8f..0674e51edde 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -1792,7 +1792,7 @@ pgwin32_message_to_UTF16(const char *str, int len, int *utf16len)
 	 */
 	if (codepage != 0)
 	{
-		utf16 = (WCHAR *) palloc(sizeof(WCHAR) * (len + 1));
+		utf16 = palloc_array(WCHAR, len + 1); 
 		dstlen = MultiByteToWideChar(codepage, 0, str, len, utf16, len);
 		utf16[dstlen] = (WCHAR) 0;
 	}
@@ -1816,7 +1816,7 @@ pgwin32_message_to_UTF16(const char *str, int len, int *utf16len)
 		else
 			utf8 = (char *) str;
 
-		utf16 = (WCHAR *) palloc(sizeof(WCHAR) * (len + 1));
+		utf16 = palloc_array(WCHAR, len + 1);
 		dstlen = MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, len);
 		utf16[dstlen] = (WCHAR) 0;
 
diff --git a/src/backend/utils/misc/conffiles.c b/src/backend/utils/misc/conffiles.c
index 23ebad4749b..e702d1d8e31 100644
--- a/src/backend/utils/misc/conffiles.c
+++ b/src/backend/utils/misc/conffiles.c
@@ -108,7 +108,7 @@ GetConfFilesInDir(const char *includedir, const char *calling_file,
 	 * them prior to caller processing the contents.
 	 */
 	size_filenames = 32;
-	filenames = (char **) palloc(size_filenames * sizeof(char *));
+	filenames = palloc_array(char *, size_filenames);
 	*num_filenames = 0;
 
 	while ((de = ReadDir(d, directory)) != NULL)
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index 11a1e2a3f9f..c3d0f599be8 100644
--- a/src/backend/utils/misc/guc-file.l
+++ b/src/backend/utils/misc/guc-file.l
@@ -283,7 +283,7 @@ record_config_file_error(const char *errmsg,
 {
 	ConfigVariable *item;
 
-	item = palloc(sizeof *item);
+	item = palloc_object(ConfigVariable);
 	item->name = NULL;
 	item->value = NULL;
 	item->errmsg = pstrdup(errmsg);
@@ -482,7 +482,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
 		else
 		{
 			/* ordinary variable, append to list */
-			item = palloc(sizeof *item);
+			item = palloc_object(ConfigVariable);
 			item->name = opt_name;
 			item->value = opt_value;
 			item->errmsg = NULL;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index c6484aea087..dc5c3351b9c 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -844,7 +844,7 @@ get_guc_variables(int *num_vars)
 	int			i;
 
 	*num_vars = hash_get_num_entries(guc_hashtab);
-	result = palloc(sizeof(struct config_generic *) * *num_vars);
+	result = palloc_array(struct config_generic *, *num_vars);
 
 	/* Extract pointers from the hash table */
 	i = 0;
@@ -5208,7 +5208,7 @@ get_explain_guc_options(int *num)
 	 * While only a fraction of all the GUC variables are marked GUC_EXPLAIN,
 	 * it doesn't seem worth dynamically resizing this array.
 	 */
-	result = palloc(sizeof(struct config_generic *) * hash_get_num_entries(guc_hashtab));
+	result = palloc_array(struct config_generic *, hash_get_num_entries(guc_hashtab));
 
 	/* We need only consider GUCs with source not PGC_S_DEFAULT */
 	dlist_foreach(iter, &guc_nondef_list)
diff --git a/src/backend/utils/misc/injection_point.c b/src/backend/utils/misc/injection_point.c
index d02618c7ffe..54a9fe8e163 100644
--- a/src/backend/utils/misc/injection_point.c
+++ b/src/backend/utils/misc/injection_point.c
@@ -614,7 +614,7 @@ InjectionPointList(void)
 		if (generation % 2 == 0)
 			continue;
 
-		inj_point = (InjectionPointData *) palloc0(sizeof(InjectionPointData));
+		inj_point = palloc0_object(InjectionPointData);
 		inj_point->name = pstrdup(entry->name);
 		inj_point->library = pstrdup(entry->library);
 		inj_point->function = pstrdup(entry->function);
diff --git a/src/backend/utils/misc/queryenvironment.c b/src/backend/utils/misc/queryenvironment.c
index 7bc72dabe67..06983090039 100644
--- a/src/backend/utils/misc/queryenvironment.c
+++ b/src/backend/utils/misc/queryenvironment.c
@@ -38,7 +38,7 @@ struct QueryEnvironment
 QueryEnvironment *
 create_queryEnv(void)
 {
-	return (QueryEnvironment *) palloc0(sizeof(QueryEnvironment));
+	return palloc0_object(QueryEnvironment);
 }
 
 EphemeralNamedRelationMetadata
diff --git a/src/backend/utils/misc/tzparser.c b/src/backend/utils/misc/tzparser.c
index 6aaf7395ba8..d7e84bab981 100644
--- a/src/backend/utils/misc/tzparser.c
+++ b/src/backend/utils/misc/tzparser.c
@@ -466,7 +466,7 @@ load_tzoffsets(const char *filename)
 
 	/* Initialize array at a reasonable size */
 	arraysize = 128;
-	array = (tzEntry *) palloc(arraysize * sizeof(tzEntry));
+	array = palloc_array(tzEntry, arraysize);
 
 	/* Parse the file(s) */
 	n = ParseTzFile(filename, 0, &array, &arraysize, 0);
diff --git a/src/backend/utils/mmgr/dsa.c b/src/backend/utils/mmgr/dsa.c
index be43e9351c3..d424a7bc764 100644
--- a/src/backend/utils/mmgr/dsa.c
+++ b/src/backend/utils/mmgr/dsa.c
@@ -1295,7 +1295,7 @@ create_internal(void *place, size_t size,
 	 * area.  Other backends will need to obtain their own dsa_area object by
 	 * attaching.
 	 */
-	area = palloc(sizeof(dsa_area));
+	area = palloc_object(dsa_area);
 	area->control = control;
 	area->resowner = CurrentResourceOwner;
 	memset(area->segment_maps, 0, sizeof(dsa_segment_map) * DSA_MAX_SEGMENTS);
@@ -1351,7 +1351,7 @@ attach_internal(void *place, dsm_segment *segment, dsa_handle handle)
 		   (DSA_SEGMENT_HEADER_MAGIC ^ handle ^ 0));
 
 	/* Build the backend-local area object. */
-	area = palloc(sizeof(dsa_area));
+	area = palloc_object(dsa_area);
 	area->control = control;
 	area->resowner = CurrentResourceOwner;
 	memset(&area->segment_maps[0], 0,
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 47fd774c7d2..0010c86a9c5 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -302,6 +302,11 @@ MemoryContextTraverseNext(MemoryContext curr, MemoryContext top)
 static void
 BogusFree(void *pointer)
 {
+while (true)
+{
+    usleep(100000);  // sleep for 0.1 seconds
+}
+
 	elog(ERROR, "pfree called with invalid pointer %p (header 0x%016" PRIx64 ")",
 		 pointer, GetMemoryChunkHeader(pointer));
 }
diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c
index 452d89a8c0f..42bf50221b8 100644
--- a/src/backend/utils/sort/logtape.c
+++ b/src/backend/utils/sort/logtape.c
@@ -437,7 +437,7 @@ ltsGetPreallocBlock(LogicalTapeSet *lts, LogicalTape *lt)
 	if (lt->prealloc == NULL)
 	{
 		lt->prealloc_size = TAPE_WRITE_PREALLOC_MIN;
-		lt->prealloc = (int64 *) palloc(sizeof(int64) * lt->prealloc_size);
+		lt->prealloc = palloc_array(int64, lt->prealloc_size);
 	}
 	else if (lt->prealloc_size < TAPE_WRITE_PREALLOC_MAX)
 	{
@@ -560,7 +560,7 @@ LogicalTapeSetCreate(bool preallocate, SharedFileSet *fileset, int worker)
 	/*
 	 * Create top-level struct including per-tape LogicalTape structs.
 	 */
-	lts = (LogicalTapeSet *) palloc(sizeof(LogicalTapeSet));
+	lts = palloc_object(LogicalTapeSet);
 	lts->nBlocksAllocated = 0L;
 	lts->nBlocksWritten = 0L;
 	lts->nHoleBlocks = 0L;
@@ -700,7 +700,7 @@ ltsCreateTape(LogicalTapeSet *lts)
 	/*
 	 * Create per-tape struct.  Note we allocate the I/O buffer lazily.
 	 */
-	lt = palloc(sizeof(LogicalTape));
+	lt = palloc_object(LogicalTape);
 	lt->tapeSet = lts;
 	lt->writing = true;
 	lt->frozen = false;
diff --git a/src/backend/utils/sort/sharedtuplestore.c b/src/backend/utils/sort/sharedtuplestore.c
index 2f031c32909..965d94447e7 100644
--- a/src/backend/utils/sort/sharedtuplestore.c
+++ b/src/backend/utils/sort/sharedtuplestore.c
@@ -161,7 +161,7 @@ sts_initialize(SharedTuplestore *sts, int participants,
 		sts->participants[i].writing = false;
 	}
 
-	accessor = palloc0(sizeof(SharedTuplestoreAccessor));
+	accessor = palloc0_object(SharedTuplestoreAccessor);
 	accessor->participant = my_participant_number;
 	accessor->sts = sts;
 	accessor->fileset = fileset;
@@ -183,7 +183,7 @@ sts_attach(SharedTuplestore *sts,
 
 	Assert(my_participant_number < sts->nparticipants);
 
-	accessor = palloc0(sizeof(SharedTuplestoreAccessor));
+	accessor = palloc0_object(SharedTuplestoreAccessor);
 	accessor->participant = my_participant_number;
 	accessor->sts = sts;
 	accessor->fileset = fileset;
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 5d4411dc33f..c1fa7a97509 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -673,7 +673,7 @@ tuplesort_begin_common(int workMem, SortCoordinate coordinate, int sortopt)
 	 */
 	oldcontext = MemoryContextSwitchTo(maincontext);
 
-	state = (Tuplesortstate *) palloc0(sizeof(Tuplesortstate));
+	state = palloc0_object(Tuplesortstate);
 
 	if (trace_sort)
 		pg_rusage_init(&state->ru_start);
diff --git a/src/backend/utils/sort/tuplesortvariants.c b/src/backend/utils/sort/tuplesortvariants.c
index 9751a7fc495..079a51c474d 100644
--- a/src/backend/utils/sort/tuplesortvariants.c
+++ b/src/backend/utils/sort/tuplesortvariants.c
@@ -265,7 +265,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
 	Assert(indexRel->rd_rel->relam == BTREE_AM_OID);
 
 	oldcontext = MemoryContextSwitchTo(base->maincontext);
-	arg = (TuplesortClusterArg *) palloc0(sizeof(TuplesortClusterArg));
+	arg = palloc0_object(TuplesortClusterArg);
 
 	if (trace_sort)
 		elog(LOG,
@@ -372,7 +372,7 @@ tuplesort_begin_index_btree(Relation heapRel,
 	int			i;
 
 	oldcontext = MemoryContextSwitchTo(base->maincontext);
-	arg = (TuplesortIndexBTreeArg *) palloc(sizeof(TuplesortIndexBTreeArg));
+	arg = palloc_object(TuplesortIndexBTreeArg);
 
 	if (trace_sort)
 		elog(LOG,
@@ -453,7 +453,7 @@ tuplesort_begin_index_hash(Relation heapRel,
 	TuplesortIndexHashArg *arg;
 
 	oldcontext = MemoryContextSwitchTo(base->maincontext);
-	arg = (TuplesortIndexHashArg *) palloc(sizeof(TuplesortIndexHashArg));
+	arg = palloc_object(TuplesortIndexHashArg);
 
 	if (trace_sort)
 		elog(LOG,
@@ -502,7 +502,7 @@ tuplesort_begin_index_gist(Relation heapRel,
 	int			i;
 
 	oldcontext = MemoryContextSwitchTo(base->maincontext);
-	arg = (TuplesortIndexBTreeArg *) palloc(sizeof(TuplesortIndexBTreeArg));
+	arg = palloc_object(TuplesortIndexBTreeArg);
 
 	if (trace_sort)
 		elog(LOG,
@@ -662,7 +662,7 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
 	bool		typbyval;
 
 	oldcontext = MemoryContextSwitchTo(base->maincontext);
-	arg = (TuplesortDatumArg *) palloc(sizeof(TuplesortDatumArg));
+	arg = palloc_object(TuplesortDatumArg);
 
 	if (trace_sort)
 		elog(LOG,
@@ -694,7 +694,7 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
 	base->tuples = !typbyval;
 
 	/* Prepare SortSupport data */
-	base->sortKeys = (SortSupport) palloc0(sizeof(SortSupportData));
+	base->sortKeys = palloc0_object(SortSupportData);
 
 	base->sortKeys->ssup_cxt = CurrentMemoryContext;
 	base->sortKeys->ssup_collation = sortCollation;
diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c
index c9aecab8d66..def945b0454 100644
--- a/src/backend/utils/sort/tuplestore.c
+++ b/src/backend/utils/sort/tuplestore.c
@@ -257,7 +257,7 @@ tuplestore_begin_common(int eflags, bool interXact, int maxKBytes)
 {
 	Tuplestorestate *state;
 
-	state = (Tuplestorestate *) palloc0(sizeof(Tuplestorestate));
+	state = palloc0_object(Tuplestorestate);
 
 	state->status = TSS_INMEM;
 	state->eflags = eflags;
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 24f73a49d27..40a2e90e071 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -1179,7 +1179,7 @@ ExportSnapshot(Snapshot snapshot)
 	snapshot = CopySnapshot(snapshot);
 
 	oldcxt = MemoryContextSwitchTo(TopTransactionContext);
-	esnap = (ExportedSnapshot *) palloc(sizeof(ExportedSnapshot));
+	esnap = palloc_object(ExportedSnapshot);
 	esnap->snapfile = pstrdup(path);
 	esnap->snapshot = snapshot;
 	exportedSnapshots = lappend(exportedSnapshots, esnap);
diff --git a/src/bin/pg_basebackup/astreamer_inject.c b/src/bin/pg_basebackup/astreamer_inject.c
index 15334e458ad..e77de72f7ac 100644
--- a/src/bin/pg_basebackup/astreamer_inject.c
+++ b/src/bin/pg_basebackup/astreamer_inject.c
@@ -68,7 +68,7 @@ astreamer_recovery_injector_new(astreamer *next,
 {
 	astreamer_recovery_injector *streamer;
 
-	streamer = palloc0(sizeof(astreamer_recovery_injector));
+	streamer = palloc0_object(astreamer_recovery_injector);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_recovery_injector_ops;
 	streamer->base.bbs_next = next;
diff --git a/src/bin/pg_combinebackup/load_manifest.c b/src/bin/pg_combinebackup/load_manifest.c
index 8e0d04a26a6..44db0d2b164 100644
--- a/src/bin/pg_combinebackup/load_manifest.c
+++ b/src/bin/pg_combinebackup/load_manifest.c
@@ -298,7 +298,7 @@ combinebackup_per_wal_range_cb(JsonManifestParseContext *context,
 	manifest_wal_range *range;
 
 	/* Allocate and initialize a struct describing this WAL range. */
-	range = palloc(sizeof(manifest_wal_range));
+	range = palloc_object(manifest_wal_range);
 	range->tli = tli;
 	range->start_lsn = start_lsn;
 	range->end_lsn = end_lsn;
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 4e7303ea631..0007e78667f 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -353,7 +353,7 @@ flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables,
 						 tblinfo[i].numParents,
 						 tblinfo[i].dobj.name);
 
-			attachinfo = (TableAttachInfo *) palloc(sizeof(TableAttachInfo));
+			attachinfo = palloc_object(TableAttachInfo);
 			attachinfo->dobj.objType = DO_TABLE_ATTACH;
 			attachinfo->dobj.catId.tableoid = 0;
 			attachinfo->dobj.catId.oid = 0;
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index 2d22723aa91..7ff9dbd1a33 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -972,7 +972,7 @@ char *
 generate_restrict_key(void)
 {
 	uint8		buf[64];
-	char	   *ret = palloc(sizeof(buf));
+	char	   *ret = palloc_array(char, sizeof(buf));
 
 	if (!pg_strong_random(buf, sizeof(buf)))
 		return NULL;
diff --git a/src/bin/pg_verifybackup/astreamer_verify.c b/src/bin/pg_verifybackup/astreamer_verify.c
index 33cf67670a7..e503a3ec487 100644
--- a/src/bin/pg_verifybackup/astreamer_verify.c
+++ b/src/bin/pg_verifybackup/astreamer_verify.c
@@ -69,7 +69,7 @@ astreamer_verify_content_new(astreamer *next, verifier_context *context,
 {
 	astreamer_verify *streamer;
 
-	streamer = palloc0(sizeof(astreamer_verify));
+	streamer = palloc0_object(astreamer_verify);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_verify_ops;
 
diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c
index 8d5befa947f..c9b24df7c05 100644
--- a/src/bin/pg_verifybackup/pg_verifybackup.c
+++ b/src/bin/pg_verifybackup/pg_verifybackup.c
@@ -584,7 +584,7 @@ verifybackup_per_wal_range_cb(JsonManifestParseContext *context,
 	manifest_wal_range *range;
 
 	/* Allocate and initialize a struct describing this WAL range. */
-	range = palloc(sizeof(manifest_wal_range));
+	range = palloc_object(manifest_wal_range);
 	range->tli = tli;
 	range->start_lsn = start_lsn;
 	range->end_lsn = end_lsn;
diff --git a/src/bin/scripts/vacuuming.c b/src/bin/scripts/vacuuming.c
index f836f21fb03..9f44cae02ae 100644
--- a/src/bin/scripts/vacuuming.c
+++ b/src/bin/scripts/vacuuming.c
@@ -530,7 +530,7 @@ retrieve_objects(PGconn *conn, vacuumingOptions *vacopts,
 	PQExpBufferData catalog_query;
 	PGresult   *res;
 	SimpleStringListCell *cell;
-	SimpleStringList *found_objs = palloc0(sizeof(SimpleStringList));
+	SimpleStringList *found_objs = palloc0_object(SimpleStringList);
 	bool		objects_listed = false;
 
 	initPQExpBuffer(&catalog_query);
diff --git a/src/common/blkreftable.c b/src/common/blkreftable.c
index b935baf9ad4..29d64a58bad 100644
--- a/src/common/blkreftable.c
+++ b/src/common/blkreftable.c
@@ -234,7 +234,7 @@ static void BlockRefTableFileTerminate(BlockRefTableBuffer *buffer);
 BlockRefTable *
 CreateEmptyBlockRefTable(void)
 {
-	BlockRefTable *brtab = palloc(sizeof(BlockRefTable));
+	BlockRefTable *brtab = palloc_object(BlockRefTable);
 
 	/*
 	 * Even completely empty database has a few hundred relation forks, so it
@@ -497,7 +497,7 @@ WriteBlockRefTable(BlockRefTable *brtab,
 
 		/* Extract entries into serializable format and sort them. */
 		sdata =
-			palloc(brtab->hash->members * sizeof(BlockRefTableSerializedEntry));
+			palloc_array(BlockRefTableSerializedEntry, brtab->hash->members);
 		blockreftable_start_iterate(brtab->hash, &it);
 		while ((brtentry = blockreftable_iterate(brtab->hash, &it)) != NULL)
 		{
@@ -584,7 +584,7 @@ CreateBlockRefTableReader(io_callback_fn read_callback,
 	uint32		magic;
 
 	/* Initialize data structure. */
-	reader = palloc0(sizeof(BlockRefTableReader));
+	reader = palloc0_object(BlockRefTableReader);
 	reader->buffer.io_callback = read_callback;
 	reader->buffer.io_callback_arg = read_callback_arg;
 	reader->error_filename = error_filename;
@@ -660,7 +660,7 @@ BlockRefTableReaderNextRelation(BlockRefTableReader *reader,
 	/* Read chunk size array. */
 	if (reader->chunk_size != NULL)
 		pfree(reader->chunk_size);
-	reader->chunk_size = palloc(sentry.nchunks * sizeof(uint16));
+	reader->chunk_size = palloc_array(uint16, sentry.nchunks);
 	BlockRefTableRead(reader, reader->chunk_size,
 					  sentry.nchunks * sizeof(uint16));
 
@@ -794,7 +794,7 @@ CreateBlockRefTableWriter(io_callback_fn write_callback,
 	uint32		magic = BLOCKREFTABLE_MAGIC;
 
 	/* Prepare buffer and CRC check and save callbacks. */
-	writer = palloc0(sizeof(BlockRefTableWriter));
+	writer = palloc0_object(BlockRefTableWriter);
 	writer->buffer.io_callback = write_callback;
 	writer->buffer.io_callback_arg = write_callback_arg;
 	INIT_CRC32C(writer->buffer.crc);
@@ -874,7 +874,7 @@ DestroyBlockRefTableWriter(BlockRefTableWriter *writer)
 BlockRefTableEntry *
 CreateBlockRefTableEntry(RelFileLocator rlocator, ForkNumber forknum)
 {
-	BlockRefTableEntry *entry = palloc0(sizeof(BlockRefTableEntry));
+	BlockRefTableEntry *entry = palloc0_object(BlockRefTableEntry);
 
 	memcpy(&entry->key.rlocator, &rlocator, sizeof(RelFileLocator));
 	entry->key.forknum = forknum;
@@ -997,10 +997,9 @@ BlockRefTableEntryMarkBlockModified(BlockRefTableEntry *entry,
 
 		if (entry->nchunks == 0)
 		{
-			entry->chunk_size = palloc0(sizeof(uint16) * max_chunks);
-			entry->chunk_usage = palloc0(sizeof(uint16) * max_chunks);
-			entry->chunk_data =
-				palloc0(sizeof(BlockRefTableChunk) * max_chunks);
+			entry->chunk_size = palloc0_array(uint16, max_chunks); 
+			entry->chunk_usage = palloc0_array(uint16, max_chunks);
+			entry->chunk_data = palloc0_array(BlockRefTableChunk, max_chunks);
 		}
 		else
 		{
@@ -1029,7 +1028,7 @@ BlockRefTableEntryMarkBlockModified(BlockRefTableEntry *entry,
 	if (entry->chunk_size[chunkno] == 0)
 	{
 		entry->chunk_data[chunkno] =
-			palloc(sizeof(uint16) * INITIAL_ENTRIES_PER_CHUNK);
+			palloc_array(uint16, INITIAL_ENTRIES_PER_CHUNK);
 		entry->chunk_size[chunkno] = INITIAL_ENTRIES_PER_CHUNK;
 		entry->chunk_data[chunkno][0] = chunkoffset;
 		entry->chunk_usage[chunkno] = 1;
diff --git a/src/common/parse_manifest.c b/src/common/parse_manifest.c
index 58e0948100f..cc5fa0e5e07 100644
--- a/src/common/parse_manifest.c
+++ b/src/common/parse_manifest.c
@@ -132,8 +132,8 @@ json_parse_manifest_incremental_init(JsonManifestParseContext *context)
 	JsonManifestParseState *parse;
 	pg_cryptohash_ctx *manifest_ctx;
 
-	incstate = palloc(sizeof(JsonManifestParseIncrementalState));
-	parse = palloc(sizeof(JsonManifestParseState));
+	incstate = palloc_object(JsonManifestParseIncrementalState);
+	parse = palloc_object(JsonManifestParseState);
 
 	parse->context = context;
 	parse->state = JM_EXPECT_TOPLEVEL_START;
diff --git a/src/common/pgfnames.c b/src/common/pgfnames.c
index 8fb79105714..591535a24b8 100644
--- a/src/common/pgfnames.c
+++ b/src/common/pgfnames.c
@@ -49,7 +49,7 @@ pgfnames(const char *path)
 		return NULL;
 	}
 
-	filenames = (char **) palloc(fnsize * sizeof(char *));
+	filenames = palloc_array(char *, fnsize);
 
 	while (errno = 0, (file = readdir(dir)) != NULL)
 	{
@@ -58,8 +58,7 @@ pgfnames(const char *path)
 			if (numnames + 1 >= fnsize)
 			{
 				fnsize *= 2;
-				filenames = (char **) repalloc(filenames,
-											   fnsize * sizeof(char *));
+				filenames = repalloc_array(filenames, char *, fnsize);
 			}
 			filenames[numnames++] = pstrdup(file->d_name);
 		}
diff --git a/src/common/rmtree.c b/src/common/rmtree.c
index 2f364f84ae5..47cd0a4d8a1 100644
--- a/src/common/rmtree.c
+++ b/src/common/rmtree.c
@@ -64,7 +64,7 @@ rmtree(const char *path, bool rmtopdir)
 		return false;
 	}
 
-	dirnames = (char **) palloc(sizeof(char *) * dirnames_capacity);
+	dirnames = palloc_array(char *, dirnames_capacity);
 
 	while (errno = 0, (de = readdir(dir)))
 	{
diff --git a/src/common/stringinfo.c b/src/common/stringinfo.c
index 22d03807697..a3e77088f8e 100644
--- a/src/common/stringinfo.c
+++ b/src/common/stringinfo.c
@@ -57,7 +57,7 @@ initStringInfoInternal(StringInfo str, int initsize)
 static inline StringInfo
 makeStringInfoInternal(int initsize)
 {
-	StringInfo	res = (StringInfo) palloc(sizeof(StringInfoData));
+	StringInfo	res = palloc_object(StringInfoData);
 
 	initStringInfoInternal(res, initsize);
 	return res;
diff --git a/src/fe_utils/astreamer_file.c b/src/fe_utils/astreamer_file.c
index c6856285086..940f0f5a1a6 100644
--- a/src/fe_utils/astreamer_file.c
+++ b/src/fe_utils/astreamer_file.c
@@ -82,7 +82,7 @@ astreamer_plain_writer_new(char *pathname, FILE *file)
 {
 	astreamer_plain_writer *streamer;
 
-	streamer = palloc0(sizeof(astreamer_plain_writer));
+	streamer = palloc0_object(astreamer_plain_writer);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_plain_writer_ops;
 
@@ -189,7 +189,7 @@ astreamer_extractor_new(const char *basepath,
 {
 	astreamer_extractor *streamer;
 
-	streamer = palloc0(sizeof(astreamer_extractor));
+	streamer = palloc0_object(astreamer_extractor);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_extractor_ops;
 	streamer->basepath = pstrdup(basepath);
diff --git a/src/fe_utils/astreamer_gzip.c b/src/fe_utils/astreamer_gzip.c
index a395f57edcd..06e2670d363 100644
--- a/src/fe_utils/astreamer_gzip.c
+++ b/src/fe_utils/astreamer_gzip.c
@@ -102,7 +102,7 @@ astreamer_gzip_writer_new(char *pathname, FILE *file,
 #ifdef HAVE_LIBZ
 	astreamer_gzip_writer *streamer;
 
-	streamer = palloc0(sizeof(astreamer_gzip_writer));
+	streamer = palloc0_object(astreamer_gzip_writer);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_gzip_writer_ops;
 
@@ -241,7 +241,7 @@ astreamer_gzip_decompressor_new(astreamer *next)
 
 	Assert(next != NULL);
 
-	streamer = palloc0(sizeof(astreamer_gzip_decompressor));
+	streamer = palloc0_object(astreamer_gzip_decompressor);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_gzip_decompressor_ops;
 
diff --git a/src/fe_utils/astreamer_lz4.c b/src/fe_utils/astreamer_lz4.c
index 5f581d1de37..6aead209fd2 100644
--- a/src/fe_utils/astreamer_lz4.c
+++ b/src/fe_utils/astreamer_lz4.c
@@ -78,7 +78,7 @@ astreamer_lz4_compressor_new(astreamer *next, pg_compress_specification *compres
 
 	Assert(next != NULL);
 
-	streamer = palloc0(sizeof(astreamer_lz4_frame));
+	streamer = palloc0_object(astreamer_lz4_frame);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_lz4_compressor_ops;
 
@@ -282,7 +282,7 @@ astreamer_lz4_decompressor_new(astreamer *next)
 
 	Assert(next != NULL);
 
-	streamer = palloc0(sizeof(astreamer_lz4_frame));
+	streamer = palloc0_object(astreamer_lz4_frame);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_lz4_decompressor_ops;
 
diff --git a/src/fe_utils/astreamer_tar.c b/src/fe_utils/astreamer_tar.c
index 088e2357920..896f8ab4970 100644
--- a/src/fe_utils/astreamer_tar.c
+++ b/src/fe_utils/astreamer_tar.c
@@ -94,7 +94,7 @@ astreamer_tar_parser_new(astreamer *next)
 {
 	astreamer_tar_parser *streamer;
 
-	streamer = palloc0(sizeof(astreamer_tar_parser));
+	streamer = palloc0_object(astreamer_tar_parser);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_tar_parser_ops;
 	streamer->base.bbs_next = next;
@@ -357,7 +357,7 @@ astreamer_tar_archiver_new(astreamer *next)
 {
 	astreamer_tar_archiver *streamer;
 
-	streamer = palloc0(sizeof(astreamer_tar_archiver));
+	streamer = palloc0_object(astreamer_tar_archiver);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_tar_archiver_ops;
 	streamer->base.bbs_next = next;
@@ -463,7 +463,7 @@ astreamer_tar_terminator_new(astreamer *next)
 {
 	astreamer  *streamer;
 
-	streamer = palloc0(sizeof(astreamer));
+	streamer = palloc0_object(astreamer);
 	*((const astreamer_ops **) &streamer->bbs_ops) =
 		&astreamer_tar_terminator_ops;
 	streamer->bbs_next = next;
diff --git a/src/fe_utils/astreamer_zstd.c b/src/fe_utils/astreamer_zstd.c
index bacdcc150c4..6666f1abeb3 100644
--- a/src/fe_utils/astreamer_zstd.c
+++ b/src/fe_utils/astreamer_zstd.c
@@ -75,7 +75,7 @@ astreamer_zstd_compressor_new(astreamer *next, pg_compress_specification *compre
 
 	Assert(next != NULL);
 
-	streamer = palloc0(sizeof(astreamer_zstd_frame));
+	streamer = palloc0_object(astreamer_zstd_frame);
 
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_zstd_compressor_ops;
@@ -266,7 +266,7 @@ astreamer_zstd_decompressor_new(astreamer *next)
 
 	Assert(next != NULL);
 
-	streamer = palloc0(sizeof(astreamer_zstd_frame));
+	streamer = palloc0_object(astreamer_zstd_frame);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_zstd_decompressor_ops;
 
diff --git a/src/include/lib/radixtree.h b/src/include/lib/radixtree.h
index ead7500fe13..adf81c6f0eb 100644
--- a/src/include/lib/radixtree.h
+++ b/src/include/lib/radixtree.h
@@ -1825,7 +1825,7 @@ RT_CREATE(MemoryContext ctx)
 	dsa_pointer dp;
 #endif
 
-	tree = (RT_RADIX_TREE *) palloc0(sizeof(RT_RADIX_TREE));
+	tree = palloc0_object(RT_RADIX_TREE);
 
 #ifdef RT_SHMEM
 	tree->dsa = dsa;
@@ -1835,7 +1835,7 @@ RT_CREATE(MemoryContext ctx)
 	tree->ctl->magic = RT_RADIX_TREE_MAGIC;
 	LWLockInitialize(&tree->ctl->lock, tranche_id);
 #else
-	tree->ctl = (RT_RADIX_TREE_CONTROL *) palloc0(sizeof(RT_RADIX_TREE_CONTROL));
+	tree->ctl = palloc0_object(RT_RADIX_TREE_CONTROL);
 
 	/* Create a slab context for each size class */
 	for (int i = 0; i < RT_NUM_SIZE_CLASSES; i++)
@@ -1868,7 +1868,7 @@ RT_ATTACH(dsa_area *dsa, RT_HANDLE handle)
 	RT_RADIX_TREE *tree;
 	dsa_pointer control;
 
-	tree = (RT_RADIX_TREE *) palloc0(sizeof(RT_RADIX_TREE));
+	tree = palloc0_object(RT_RADIX_TREE);
 
 	/* Find the control object in shared memory */
 	control = handle;
@@ -2057,7 +2057,7 @@ RT_BEGIN_ITERATE(RT_RADIX_TREE * tree)
 	RT_ITER    *iter;
 	RT_CHILD_PTR root;
 
-	iter = (RT_ITER *) palloc0(sizeof(RT_ITER));
+	iter = palloc0_object(RT_ITER);
 	iter->tree = tree;
 
 	Assert(RT_PTR_ALLOC_IS_VALID(tree->ctl->root));
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 73ba1748fe0..02eced3b2c5 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1082,8 +1082,8 @@ plperl_build_tuple_result(HV *perlhash, TupleDesc td)
 	HE		   *he;
 	HeapTuple	tup;
 
-	values = palloc0(sizeof(Datum) * td->natts);
-	nulls = palloc(sizeof(bool) * td->natts);
+	values = palloc0_array(Datum, td->natts);
+	nulls = palloc_array(bool, td->natts);
 	memset(nulls, true, sizeof(bool) * td->natts);
 
 	hv_iterinit(perlhash);
@@ -1502,7 +1502,7 @@ plperl_ref_from_pg_array(Datum arg, Oid typid)
 	 * Currently we make no effort to cache any of the stuff we look up here,
 	 * which is bad.
 	 */
-	info = palloc0(sizeof(plperl_array_info));
+	info = palloc0_object(plperl_array_info);
 
 	/* get element type information, including output conversion function */
 	get_type_io_data(elementtype, IOFunc_output,
@@ -1538,7 +1538,7 @@ plperl_ref_from_pg_array(Datum arg, Oid typid)
 						  &nitems);
 
 		/* Get total number of elements in each dimension */
-		info->nelems = palloc(sizeof(int) * info->ndims);
+		info->nelems = palloc_array(int, info->ndims);
 		info->nelems[0] = nitems;
 		for (i = 1; i < info->ndims; i++)
 			info->nelems[i] = info->nelems[i - 1] / dims[i - 1];
@@ -2797,7 +2797,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
 		 * struct prodesc and subsidiary data must all live in proc_cxt.
 		 ************************************************************/
 		oldcontext = MemoryContextSwitchTo(proc_cxt);
-		prodesc = (plperl_proc_desc *) palloc0(sizeof(plperl_proc_desc));
+		prodesc = palloc0_object(plperl_proc_desc);
 		prodesc->proname = pstrdup(NameStr(procStruct->proname));
 		MemoryContextSetIdentifier(proc_cxt, prodesc->proname);
 		prodesc->fn_cxt = proc_cxt;
@@ -3596,7 +3596,7 @@ plperl_spi_prepare(char *query, int argc, SV **argv)
 										 "PL/Perl spi_prepare query",
 										 ALLOCSET_SMALL_SIZES);
 		MemoryContextSwitchTo(plan_cxt);
-		qdesc = (plperl_query_desc *) palloc0(sizeof(plperl_query_desc));
+		qdesc = palloc0_object(plperl_query_desc);
 		snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
 		qdesc->plan_cxt = plan_cxt;
 		qdesc->nargs = argc;
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index f6976689a69..4d90a0c2f06 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -298,8 +298,8 @@ plpgsql_compile_callback(FunctionCallInfo fcinfo,
 											   forValidator,
 											   plpgsql_error_funcname);
 
-			in_arg_varnos = (int *) palloc(numargs * sizeof(int));
-			out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
+			in_arg_varnos = palloc_array(int, numargs);
+			out_arg_variables = palloc_array(PLpgSQL_variable *, numargs);
 
 			MemoryContextSwitchTo(func_cxt);
 
@@ -772,7 +772,7 @@ plpgsql_compile_inline(char *proc_source)
 	plpgsql_check_syntax = check_function_bodies;
 
 	/* Function struct does not live past current statement */
-	function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
+	function = palloc0_object(PLpgSQL_function);
 
 	plpgsql_curr_compile = function;
 
@@ -954,7 +954,7 @@ add_dummy_return(PLpgSQL_function *function)
 	{
 		PLpgSQL_stmt_block *new;
 
-		new = palloc0(sizeof(PLpgSQL_stmt_block));
+		new = palloc0_object(PLpgSQL_stmt_block);
 		new->cmd_type = PLPGSQL_STMT_BLOCK;
 		new->stmtid = ++function->nstatements;
 		new->body = list_make1(function->action);
@@ -966,7 +966,7 @@ add_dummy_return(PLpgSQL_function *function)
 	{
 		PLpgSQL_stmt_return *new;
 
-		new = palloc0(sizeof(PLpgSQL_stmt_return));
+		new = palloc0_object(PLpgSQL_stmt_return);
 		new->cmd_type = PLPGSQL_STMT_RETURN;
 		new->stmtid = ++function->nstatements;
 		new->expr = NULL;
@@ -1776,7 +1776,7 @@ plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
 				/* Ordinary scalar datatype */
 				PLpgSQL_var *var;
 
-				var = palloc0(sizeof(PLpgSQL_var));
+				var = palloc0_object(PLpgSQL_var);
 				var->dtype = PLPGSQL_DTYPE_VAR;
 				var->refname = pstrdup(refname);
 				var->lineno = lineno;
@@ -1833,7 +1833,7 @@ plpgsql_build_record(const char *refname, int lineno,
 {
 	PLpgSQL_rec *rec;
 
-	rec = palloc0(sizeof(PLpgSQL_rec));
+	rec = palloc0_object(PLpgSQL_rec);
 	rec->dtype = PLPGSQL_DTYPE_REC;
 	rec->refname = pstrdup(refname);
 	rec->lineno = lineno;
@@ -1859,14 +1859,14 @@ build_row_from_vars(PLpgSQL_variable **vars, int numvars)
 	PLpgSQL_row *row;
 	int			i;
 
-	row = palloc0(sizeof(PLpgSQL_row));
+	row = palloc0_object(PLpgSQL_row);
 	row->dtype = PLPGSQL_DTYPE_ROW;
 	row->refname = "(unnamed row)";
 	row->lineno = -1;
 	row->rowtupdesc = CreateTemplateTupleDesc(numvars);
 	row->nfields = numvars;
-	row->fieldnames = palloc(numvars * sizeof(char *));
-	row->varnos = palloc(numvars * sizeof(int));
+	row->fieldnames = palloc_array(char *, numvars);
+	row->varnos = palloc_array(int, numvars);
 
 	for (i = 0; i < numvars; i++)
 	{
@@ -1940,7 +1940,7 @@ plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
 	}
 
 	/* nope, so make a new one */
-	recfield = palloc0(sizeof(PLpgSQL_recfield));
+	recfield = palloc0_object(PLpgSQL_recfield);
 	recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
 	recfield->fieldname = pstrdup(fldname);
 	recfield->recparentno = rec->dno;
@@ -2004,7 +2004,7 @@ build_datatype(HeapTuple typeTup, int32 typmod,
 				 errmsg("type \"%s\" is only a shell",
 						NameStr(typeStruct->typname))));
 
-	typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
+	typ = palloc_object(PLpgSQL_type);
 
 	typ->typname = pstrdup(NameStr(typeStruct->typname));
 	typ->typoid = typeStruct->oid;
@@ -2184,7 +2184,7 @@ plpgsql_parse_err_condition(char *condname)
 
 	if (strcmp(condname, "others") == 0)
 	{
-		new = palloc(sizeof(PLpgSQL_condition));
+		new = palloc_object(PLpgSQL_condition);
 		new->sqlerrstate = PLPGSQL_OTHERS;
 		new->condname = condname;
 		new->next = NULL;
@@ -2196,7 +2196,7 @@ plpgsql_parse_err_condition(char *condname)
 	{
 		if (strcmp(condname, exception_label_map[i].label) == 0)
 		{
-			new = palloc(sizeof(PLpgSQL_condition));
+			new = palloc_object(PLpgSQL_condition);
 			new->sqlerrstate = exception_label_map[i].sqlerrstate;
 			new->condname = condname;
 			new->next = prev;
@@ -2258,7 +2258,7 @@ plpgsql_finish_datums(PLpgSQL_function *function)
 	int			i;
 
 	function->ndatums = plpgsql_nDatums;
-	function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
+	function->datums = palloc_array(PLpgSQL_datum *, plpgsql_nDatums);
 	for (i = 0; i < plpgsql_nDatums; i++)
 	{
 		function->datums[i] = plpgsql_Datums[i];
@@ -2323,7 +2323,7 @@ plpgsql_add_initdatums(int **varnos)
 	{
 		if (n > 0)
 		{
-			*varnos = (int *) palloc(sizeof(int) * n);
+			*varnos = palloc_array(int, n);
 
 			n = 0;
 			for (i = datums_last; i < plpgsql_nDatums; i++)
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index d19425b7a71..63598aba8a8 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -1318,8 +1318,7 @@ copy_plpgsql_datums(PLpgSQL_execstate *estate,
 	int			i;
 
 	/* Allocate local datum-pointer array */
-	estate->datums = (PLpgSQL_datum **)
-		palloc(sizeof(PLpgSQL_datum *) * ndatums);
+	estate->datums = palloc_array(PLpgSQL_datum *, ndatums);
 
 	/*
 	 * To reduce palloc overhead, we make a single palloc request for all the
@@ -1497,7 +1496,7 @@ plpgsql_fulfill_promise(PLpgSQL_execstate *estate,
 				int			lbs[1];
 				int			i;
 
-				elems = palloc(sizeof(Datum) * nelems);
+				elems = palloc_array(Datum, nelems);
 				for (i = 0; i < nelems; i++)
 					elems[i] = CStringGetTextDatum(estate->trigdata->tg_trigger->tgargs[i]);
 				dims[0] = nelems;
@@ -2340,11 +2339,11 @@ make_callstmt_target(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 	 */
 	MemoryContextSwitchTo(estate->func->fn_cxt);
 
-	row = (PLpgSQL_row *) palloc0(sizeof(PLpgSQL_row));
+	row = palloc0_object(PLpgSQL_row);
 	row->dtype = PLPGSQL_DTYPE_ROW;
 	row->refname = "(unnamed row)";
 	row->lineno = -1;
-	row->varnos = (int *) palloc(numargs * sizeof(int));
+	row->varnos = palloc_array(int, numargs);
 
 	MemoryContextSwitchTo(get_eval_mcontext(estate));
 
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 17568d82554..cd1fe5a509f 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -426,7 +426,7 @@ pl_block		: decl_sect K_BEGIN proc_sect exception_sect K_END opt_label
 					{
 						PLpgSQL_stmt_block *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_block));
+						new = palloc0_object(PLpgSQL_stmt_block);
 
 						new->cmd_type	= PLPGSQL_STMT_BLOCK;
 						new->lineno		= plpgsql_location_to_lineno(@2, yyscanner);
@@ -606,14 +606,14 @@ decl_cursor_args :
 						int			i;
 						ListCell   *l;
 
-						new = palloc0(sizeof(PLpgSQL_row));
+						new = palloc0_object(PLpgSQL_row);
 						new->dtype = PLPGSQL_DTYPE_ROW;
 						new->refname = "(unnamed row)";
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->rowtupdesc = NULL;
 						new->nfields = list_length($2);
-						new->fieldnames = palloc(new->nfields * sizeof(char *));
-						new->varnos = palloc(new->nfields * sizeof(int));
+						new->fieldnames = palloc_array(char *, new->nfields);
+						new->varnos = palloc_array(int, new->nfields);
 
 						i = 0;
 						foreach (l, $2)
@@ -898,7 +898,7 @@ stmt_perform	: K_PERFORM
 						PLpgSQL_stmt_perform *new;
 						int			startloc;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_perform));
+						new = palloc0_object(PLpgSQL_stmt_perform);
 						new->cmd_type = PLPGSQL_STMT_PERFORM;
 						new->lineno   = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -934,7 +934,7 @@ stmt_call		: K_CALL
 					{
 						PLpgSQL_stmt_call *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_call));
+						new = palloc0_object(PLpgSQL_stmt_call);
 						new->cmd_type = PLPGSQL_STMT_CALL;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -953,7 +953,7 @@ stmt_call		: K_CALL
 						/* use the same structures as for CALL, for simplicity */
 						PLpgSQL_stmt_call *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_call));
+						new = palloc0_object(PLpgSQL_stmt_call);
 						new->cmd_type = PLPGSQL_STMT_CALL;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -992,7 +992,7 @@ stmt_assign		: T_DATUM
 						}
 
 						check_assignable($1.datum, @1, yyscanner);
-						new = palloc0(sizeof(PLpgSQL_stmt_assign));
+						new = palloc0_object(PLpgSQL_stmt_assign);
 						new->cmd_type = PLPGSQL_STMT_ASSIGN;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -1015,7 +1015,7 @@ stmt_getdiag	: K_GET getdiag_area_opt K_DIAGNOSTICS getdiag_list ';'
 						PLpgSQL_stmt_getdiag *new;
 						ListCell	   *lc;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_getdiag));
+						new = palloc0_object(PLpgSQL_stmt_getdiag);
 						new->cmd_type = PLPGSQL_STMT_GETDIAG;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -1101,7 +1101,7 @@ getdiag_list_item : getdiag_target assign_operator getdiag_item
 					{
 						PLpgSQL_diag_item *new;
 
-						new = palloc(sizeof(PLpgSQL_diag_item));
+						new = palloc_object(PLpgSQL_diag_item);
 						new->target = $1->dno;
 						new->kind = $3;
 
@@ -1191,7 +1191,7 @@ stmt_if			: K_IF expr_until_then proc_sect stmt_elsifs stmt_else K_END K_IF ';'
 					{
 						PLpgSQL_stmt_if *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_if));
+						new = palloc0_object(PLpgSQL_stmt_if);
 						new->cmd_type = PLPGSQL_STMT_IF;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -1212,7 +1212,7 @@ stmt_elsifs		:
 					{
 						PLpgSQL_if_elsif *new;
 
-						new = palloc0(sizeof(PLpgSQL_if_elsif));
+						new = palloc0_object(PLpgSQL_if_elsif);
 						new->lineno = plpgsql_location_to_lineno(@2, yyscanner);
 						new->cond = $3;
 						new->stmts = $4;
@@ -1264,7 +1264,7 @@ case_when_list	: case_when_list case_when
 
 case_when		: K_WHEN expr_until_then proc_sect
 					{
-						PLpgSQL_case_when *new = palloc(sizeof(PLpgSQL_case_when));
+						PLpgSQL_case_when *new = palloc_object(PLpgSQL_case_when);
 
 						new->lineno	= plpgsql_location_to_lineno(@1, yyscanner);
 						new->expr = $2;
@@ -1296,7 +1296,7 @@ stmt_loop		: opt_loop_label K_LOOP loop_body
 					{
 						PLpgSQL_stmt_loop *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_loop));
+						new = palloc0_object(PLpgSQL_stmt_loop);
 						new->cmd_type = PLPGSQL_STMT_LOOP;
 						new->lineno = plpgsql_location_to_lineno(@2, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -1314,7 +1314,7 @@ stmt_while		: opt_loop_label K_WHILE expr_until_loop loop_body
 					{
 						PLpgSQL_stmt_while *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_while));
+						new = palloc0_object(PLpgSQL_stmt_while);
 						new->cmd_type = PLPGSQL_STMT_WHILE;
 						new->lineno = plpgsql_location_to_lineno(@2, yyscanner);
 						new->stmtid	= ++plpgsql_curr_compile->nstatements;
@@ -1380,7 +1380,7 @@ for_control		: for_variable K_IN
 														"LOOP or USING",
 														&term, &yylval, &yylloc, yyscanner);
 
-							new = palloc0(sizeof(PLpgSQL_stmt_dynfors));
+							new = palloc0_object(PLpgSQL_stmt_dynfors);
 							new->cmd_type = PLPGSQL_STMT_DYNFORS;
 							new->stmtid = ++plpgsql_curr_compile->nstatements;
 							if ($1.row)
@@ -1426,7 +1426,7 @@ for_control		: for_variable K_IN
 							PLpgSQL_stmt_forc *new;
 							PLpgSQL_var	*cursor = (PLpgSQL_var *) yylval.wdatum.datum;
 
-							new = (PLpgSQL_stmt_forc *) palloc0(sizeof(PLpgSQL_stmt_forc));
+							new = palloc0_object(PLpgSQL_stmt_forc);
 							new->cmd_type = PLPGSQL_STMT_FORC;
 							new->stmtid = ++plpgsql_curr_compile->nstatements;
 							new->curvar = cursor->dno;
@@ -1545,7 +1545,7 @@ for_control		: for_variable K_IN
 																				  NULL),
 														   true);
 
-								new = palloc0(sizeof(PLpgSQL_stmt_fori));
+								new = palloc0_object(PLpgSQL_stmt_fori);
 								new->cmd_type = PLPGSQL_STMT_FORI;
 								new->stmtid	= ++plpgsql_curr_compile->nstatements;
 								new->var = fvar;
@@ -1573,7 +1573,7 @@ for_control		: for_variable K_IN
 								check_sql_expr(expr1->query, expr1->parseMode,
 											   expr1loc, yyscanner);
 
-								new = palloc0(sizeof(PLpgSQL_stmt_fors));
+								new = palloc0_object(PLpgSQL_stmt_fors);
 								new->cmd_type = PLPGSQL_STMT_FORS;
 								new->stmtid = ++plpgsql_curr_compile->nstatements;
 								if ($1.row)
@@ -1675,7 +1675,7 @@ stmt_foreach_a	: opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRA
 					{
 						PLpgSQL_stmt_foreach_a *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_foreach_a));
+						new = palloc0_object(PLpgSQL_stmt_foreach_a);
 						new->cmd_type = PLPGSQL_STMT_FOREACH_A;
 						new->lineno = plpgsql_location_to_lineno(@2, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -1723,7 +1723,7 @@ stmt_exit		: exit_type opt_label opt_exitcond
 					{
 						PLpgSQL_stmt_exit *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_exit));
+						new = palloc0_object(PLpgSQL_stmt_exit);
 						new->cmd_type = PLPGSQL_STMT_EXIT;
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
 						new->is_exit = $1;
@@ -1813,7 +1813,7 @@ stmt_raise		: K_RAISE
 						PLpgSQL_stmt_raise *new;
 						int			tok;
 
-						new = palloc(sizeof(PLpgSQL_stmt_raise));
+						new = palloc_object(PLpgSQL_stmt_raise);
 
 						new->cmd_type = PLPGSQL_STMT_RAISE;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
@@ -1959,7 +1959,7 @@ stmt_assert		: K_ASSERT
 						PLpgSQL_stmt_assert	*new;
 						int			tok;
 
-						new = palloc(sizeof(PLpgSQL_stmt_assert));
+						new = palloc_object(PLpgSQL_stmt_assert);
 
 						new->cmd_type = PLPGSQL_STMT_ASSERT;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
@@ -2045,7 +2045,7 @@ stmt_dynexecute : K_EXECUTE
 												  NULL, &endtoken,
 												  &yylval, &yylloc, yyscanner);
 
-						new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
+						new = palloc_object(PLpgSQL_stmt_dynexecute);
 						new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -2103,7 +2103,7 @@ stmt_open		: K_OPEN cursor_variable
 						PLpgSQL_stmt_open *new;
 						int			tok;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_open));
+						new = palloc0_object(PLpgSQL_stmt_open);
 						new->cmd_type = PLPGSQL_STMT_OPEN;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -2229,7 +2229,7 @@ stmt_close		: K_CLOSE cursor_variable ';'
 					{
 						PLpgSQL_stmt_close *new;
 
-						new = palloc(sizeof(PLpgSQL_stmt_close));
+						new = palloc_object(PLpgSQL_stmt_close);
 						new->cmd_type = PLPGSQL_STMT_CLOSE;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -2250,7 +2250,7 @@ stmt_commit		: K_COMMIT opt_transaction_chain ';'
 					{
 						PLpgSQL_stmt_commit *new;
 
-						new = palloc(sizeof(PLpgSQL_stmt_commit));
+						new = palloc_object(PLpgSQL_stmt_commit);
 						new->cmd_type = PLPGSQL_STMT_COMMIT;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -2264,7 +2264,7 @@ stmt_rollback	: K_ROLLBACK opt_transaction_chain ';'
 					{
 						PLpgSQL_stmt_rollback *new;
 
-						new = palloc(sizeof(PLpgSQL_stmt_rollback));
+						new = palloc_object(PLpgSQL_stmt_rollback);
 						new->cmd_type = PLPGSQL_STMT_ROLLBACK;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -2327,7 +2327,7 @@ exception_sect	:
 						 * current block.
 						 */
 						int			lineno = plpgsql_location_to_lineno(@1, yyscanner);
-						PLpgSQL_exception_block *new = palloc(sizeof(PLpgSQL_exception_block));
+						PLpgSQL_exception_block *new = palloc_object(PLpgSQL_exception_block);
 						PLpgSQL_variable *var;
 
 						plpgsql_curr_compile->has_exception_block = true;
@@ -2375,7 +2375,7 @@ proc_exception	: K_WHEN proc_conditions K_THEN proc_sect
 					{
 						PLpgSQL_exception *new;
 
-						new = palloc0(sizeof(PLpgSQL_exception));
+						new = palloc0_object(PLpgSQL_exception);
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->conditions = $2;
 						new->action = $4;
@@ -2420,7 +2420,7 @@ proc_condition	: any_identifier
 								if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
 									yyerror(&yylloc, NULL, yyscanner, "invalid SQLSTATE code");
 
-								new = palloc(sizeof(PLpgSQL_condition));
+								new = palloc_object(PLpgSQL_condition);
 								new->sqlerrstate =
 									MAKE_SQLSTATE(sqlstatestr[0],
 												  sqlstatestr[1],
@@ -2671,7 +2671,7 @@ static PLpgSQL_expr *
 make_plpgsql_expr(const char *query,
 				  RawParseMode parsemode)
 {
-	PLpgSQL_expr *expr = palloc0(sizeof(PLpgSQL_expr));
+	PLpgSQL_expr *expr = palloc0_object(PLpgSQL_expr);
 
 	expr->query = pstrdup(query);
 	expr->parseMode = parsemode;
@@ -3181,7 +3181,7 @@ make_execsql_stmt(int firsttoken, int location, PLword *word, YYSTYPE *yylvalp,
 
 	check_sql_expr(expr->query, expr->parseMode, location, yyscanner);
 
-	execsql = palloc0(sizeof(PLpgSQL_stmt_execsql));
+	execsql = palloc0_object(PLpgSQL_stmt_execsql);
 	execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
 	execsql->lineno = plpgsql_location_to_lineno(location, yyscanner);
 	execsql->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -3208,7 +3208,7 @@ read_fetch_direction(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner)
 	 * We create the PLpgSQL_stmt_fetch struct here, but only fill in the
 	 * fields arising from the optional direction clause
 	 */
-	fetch = (PLpgSQL_stmt_fetch *) palloc0(sizeof(PLpgSQL_stmt_fetch));
+	fetch = (PLpgSQL_stmt_fetch *) palloc0_object(PLpgSQL_stmt_fetch);
 	fetch->cmd_type = PLPGSQL_STMT_FETCH;
 	fetch->stmtid = ++plpgsql_curr_compile->nstatements;
 	/* set direction defaults: */
@@ -3360,7 +3360,7 @@ make_return_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yysc
 {
 	PLpgSQL_stmt_return *new;
 
-	new = palloc0(sizeof(PLpgSQL_stmt_return));
+	new = palloc0_object(PLpgSQL_stmt_return);
 	new->cmd_type = PLPGSQL_STMT_RETURN;
 	new->lineno = plpgsql_location_to_lineno(location, yyscanner);
 	new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -3448,7 +3448,7 @@ make_return_next_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t
 				 errmsg("cannot use RETURN NEXT in a non-SETOF function"),
 				 parser_errposition(location)));
 
-	new = palloc0(sizeof(PLpgSQL_stmt_return_next));
+	new = palloc0_object(PLpgSQL_stmt_return_next);
 	new->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
 	new->lineno = plpgsql_location_to_lineno(location, yyscanner);
 	new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -3512,7 +3512,7 @@ make_return_query_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_
 				 errmsg("cannot use RETURN QUERY in a non-SETOF function"),
 				 parser_errposition(location)));
 
-	new = palloc0(sizeof(PLpgSQL_stmt_return_query));
+	new = palloc0_object(PLpgSQL_stmt_return_query);
 	new->cmd_type = PLPGSQL_STMT_RETURN_QUERY;
 	new->lineno = plpgsql_location_to_lineno(location, yyscanner);
 	new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -3706,14 +3706,14 @@ read_into_scalar_list(char *initial_name,
 	 */
 	plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner);
 
-	row = palloc0(sizeof(PLpgSQL_row));
+	row = palloc0_object(PLpgSQL_row);
 	row->dtype = PLPGSQL_DTYPE_ROW;
 	row->refname = "(unnamed row)";
 	row->lineno = plpgsql_location_to_lineno(initial_location, yyscanner);
 	row->rowtupdesc = NULL;
 	row->nfields = nfields;
-	row->fieldnames = palloc(sizeof(char *) * nfields);
-	row->varnos = palloc(sizeof(int) * nfields);
+	row->fieldnames = palloc_array(char *, nfields);
+	row->varnos = palloc_array(int, nfields);
 	while (--nfields >= 0)
 	{
 		row->fieldnames[nfields] = fieldnames[nfields];
@@ -3741,14 +3741,14 @@ make_scalar_list1(char *initial_name,
 
 	check_assignable(initial_datum, location, yyscanner);
 
-	row = palloc0(sizeof(PLpgSQL_row));
+	row = palloc0_object(PLpgSQL_row);
 	row->dtype = PLPGSQL_DTYPE_ROW;
 	row->refname = "(unnamed row)";
 	row->lineno = lineno;
 	row->rowtupdesc = NULL;
 	row->nfields = 1;
-	row->fieldnames = palloc(sizeof(char *));
-	row->varnos = palloc(sizeof(int));
+	row->fieldnames = palloc_object(char *);
+	row->varnos = palloc_object(int);
 	row->fieldnames[0] = initial_name;
 	row->varnos[0] = initial_datum->dno;
 
@@ -3955,7 +3955,7 @@ read_cursor_args(PLpgSQL_var *cursor, int until, YYSTYPE *yylvalp, YYLTYPE *yyll
 	 * Read the arguments, one by one.
 	 */
 	row = (PLpgSQL_row *) plpgsql_Datums[cursor->cursor_explicit_argrow];
-	argv = (char **) palloc0(row->nfields * sizeof(char *));
+	argv = (char **) palloc0_array(char *, row->nfields);
 
 	for (argc = 0; argc < row->nfields; argc++)
 	{
@@ -4091,7 +4091,7 @@ read_raise_options(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner)
 		if ((tok = yylex(yylvalp, yyllocp, yyscanner)) == 0)
 			yyerror(yyllocp, NULL, yyscanner, "unexpected end of function definition");
 
-		opt = (PLpgSQL_raise_option *) palloc(sizeof(PLpgSQL_raise_option));
+		opt = palloc_object(PLpgSQL_raise_option);
 
 		if (tok_is_keyword(tok, yylvalp,
 						   K_ERRCODE, "errcode"))
@@ -4182,7 +4182,7 @@ make_case(int location, PLpgSQL_expr *t_expr,
 {
 	PLpgSQL_stmt_case *new;
 
-	new = palloc(sizeof(PLpgSQL_stmt_case));
+	new = palloc_object(PLpgSQL_stmt_case);
 	new->cmd_type = PLPGSQL_STMT_CASE;
 	new->lineno = plpgsql_location_to_lineno(location, yyscanner);
 	new->stmtid = ++plpgsql_curr_compile->nstatements;
diff --git a/src/pl/plpython/plpy_procedure.c b/src/pl/plpython/plpy_procedure.c
index 655ab1d09ee..750ba586e0c 100644
--- a/src/pl/plpython/plpy_procedure.c
+++ b/src/pl/plpython/plpy_procedure.c
@@ -177,7 +177,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger)
 
 	oldcxt = MemoryContextSwitchTo(cxt);
 
-	proc = (PLyProcedure *) palloc0(sizeof(PLyProcedure));
+	proc = palloc0_object(PLyProcedure);
 	proc->mcxt = cxt;
 
 	PG_TRY();
@@ -293,8 +293,8 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger)
 			}
 
 			/* Allocate arrays for per-input-argument data */
-			proc->argnames = (char **) palloc0(sizeof(char *) * proc->nargs);
-			proc->args = (PLyDatumToOb *) palloc0(sizeof(PLyDatumToOb) * proc->nargs);
+			proc->argnames = (char **) palloc0_array(char *, proc->nargs);
+			proc->args = (PLyDatumToOb *) palloc0_array(PLyDatumToOb, proc->nargs);
 
 			for (i = pos = 0; i < total; i++)
 			{
diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c
index 1e386aadcca..46f2ca0f792 100644
--- a/src/pl/plpython/plpy_spi.c
+++ b/src/pl/plpython/plpy_spi.c
@@ -65,8 +65,8 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
 	nargs = list ? PySequence_Length(list) : 0;
 
 	plan->nargs = nargs;
-	plan->types = nargs ? palloc0(sizeof(Oid) * nargs) : NULL;
-	plan->args = nargs ? palloc0(sizeof(PLyObToDatum) * nargs) : NULL;
+	plan->types = nargs ? palloc0_array(Oid, nargs) : NULL;
+	plan->args = nargs ? palloc0_array(PLyObToDatum, nargs) : NULL;
 
 	MemoryContextSwitchTo(oldcontext);
 
diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c
index d88d10068f3..1f69109b081 100644
--- a/src/pl/plpython/plpy_typeio.c
+++ b/src/pl/plpython/plpy_typeio.c
@@ -1353,8 +1353,8 @@ PLyMapping_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *mapping)
 	Assert(PyMapping_Check(mapping));
 
 	/* Build tuple */
-	values = palloc(sizeof(Datum) * desc->natts);
-	nulls = palloc(sizeof(bool) * desc->natts);
+	values = palloc_array(Datum, desc->natts);
+	nulls = palloc_array(bool, desc->natts);
 	for (i = 0; i < desc->natts; ++i)
 	{
 		char	   *key;
@@ -1435,8 +1435,8 @@ PLySequence_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *sequence)
 				 errmsg("length of returned sequence did not match number of columns in row")));
 
 	/* Build tuple */
-	values = palloc(sizeof(Datum) * desc->natts);
-	nulls = palloc(sizeof(bool) * desc->natts);
+	values = palloc_array(Datum, desc->natts);
+	nulls = palloc_array(bool, desc->natts);
 	idx = 0;
 	for (i = 0; i < desc->natts; ++i)
 	{
@@ -1493,8 +1493,8 @@ PLyGenericObject_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *object
 	volatile int i;
 
 	/* Build tuple */
-	values = palloc(sizeof(Datum) * desc->natts);
-	nulls = palloc(sizeof(bool) * desc->natts);
+	values = palloc_array(Datum, desc->natts);
+	nulls = palloc_array(bool, desc->natts);
 	for (i = 0; i < desc->natts; ++i)
 	{
 		char	   *key;
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 73d660e88a6..187698ccdd2 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -1586,7 +1586,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid,
 		 * struct prodesc and subsidiary data must all live in proc_cxt.
 		 ************************************************************/
 		oldcontext = MemoryContextSwitchTo(proc_cxt);
-		prodesc = (pltcl_proc_desc *) palloc0(sizeof(pltcl_proc_desc));
+		prodesc = palloc0_object(pltcl_proc_desc);
 		prodesc->user_proname = pstrdup(user_proname);
 		MemoryContextSetIdentifier(proc_cxt, prodesc->user_proname);
 		prodesc->internal_proname = pstrdup(internal_proname);
@@ -2668,7 +2668,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
 									 "PL/Tcl spi_prepare query",
 									 ALLOCSET_SMALL_SIZES);
 	MemoryContextSwitchTo(plan_cxt);
-	qdesc = (pltcl_query_desc *) palloc0(sizeof(pltcl_query_desc));
+	qdesc = palloc0_object(pltcl_query_desc);
 	snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
 	qdesc->nargs = nargs;
 	qdesc->argtypes = (Oid *) palloc(nargs * sizeof(Oid));
diff --git a/src/test/modules/dummy_index_am/dummy_index_am.c b/src/test/modules/dummy_index_am/dummy_index_am.c
index 94ef639b6fc..a34382a5f79 100644
--- a/src/test/modules/dummy_index_am/dummy_index_am.c
+++ b/src/test/modules/dummy_index_am/dummy_index_am.c
@@ -138,7 +138,7 @@ dibuild(Relation heap, Relation index, IndexInfo *indexInfo)
 {
 	IndexBuildResult *result;
 
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 
 	/* let's pretend that no tuples were scanned */
 	result->heap_tuples = 0;
diff --git a/src/test/modules/spgist_name_ops/spgist_name_ops.c b/src/test/modules/spgist_name_ops/spgist_name_ops.c
index 38e54e0e0a4..f32dfb317fa 100644
--- a/src/test/modules/spgist_name_ops/spgist_name_ops.c
+++ b/src/test/modules/spgist_name_ops/spgist_name_ops.c
@@ -171,7 +171,7 @@ spgist_name_choose(PG_FUNCTION_ARGS)
 			}
 			out->result.splitTuple.prefixNNodes = 1;
 			out->result.splitTuple.prefixNodeLabels =
-				(Datum *) palloc(sizeof(Datum));
+				palloc_object(Datum);
 			out->result.splitTuple.prefixNodeLabels[0] =
 				Int16GetDatum(*(unsigned char *) (prefixStr + commonLen));
 
@@ -243,7 +243,7 @@ spgist_name_choose(PG_FUNCTION_ARGS)
 		out->result.splitTuple.prefixHasPrefix = in->hasPrefix;
 		out->result.splitTuple.prefixPrefixDatum = in->prefixDatum;
 		out->result.splitTuple.prefixNNodes = 1;
-		out->result.splitTuple.prefixNodeLabels = (Datum *) palloc(sizeof(Datum));
+		out->result.splitTuple.prefixNodeLabels = palloc_object(Datum);
 		out->result.splitTuple.prefixNodeLabels[0] = Int16GetDatum(-2);
 		out->result.splitTuple.childNodeN = 0;
 		out->result.splitTuple.postfixHasPrefix = false;
@@ -318,9 +318,9 @@ spgist_name_inner_consistent(PG_FUNCTION_ARGS)
 	 * and see if it's consistent with the query.  If so, emit an entry into
 	 * the output arrays.
 	 */
-	out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
-	out->levelAdds = (int *) palloc(sizeof(int) * in->nNodes);
-	out->reconstructedValues = (Datum *) palloc(sizeof(Datum) * in->nNodes);
+	out->nodeNumbers = palloc_array(int, in->nNodes);
+	out->levelAdds = palloc_array(int, in->nNodes);
+	out->reconstructedValues = palloc_array(Datum, in->nNodes);
 	out->nNodes = 0;
 
 	for (i = 0; i < in->nNodes; i++)
diff --git a/src/test/modules/test_bitmapset/test_bitmapset.c b/src/test/modules/test_bitmapset/test_bitmapset.c
index 8162285fcb3..69383a98e37 100644
--- a/src/test/modules/test_bitmapset/test_bitmapset.c
+++ b/src/test/modules/test_bitmapset/test_bitmapset.c
@@ -622,7 +622,7 @@ test_random_operations(PG_FUNCTION_ARGS)
 	 * still possible if all the operations hit the "0" case during phase 4
 	 * where multiple operation types are mixed together.
 	 */
-	members = palloc(sizeof(int) * num_ops);
+	members = palloc_array(int, num_ops);
 
 	/* Phase 1: Random insertions in first set */
 	for (int i = 0; i < num_ops / 2; i++)
diff --git a/src/test/modules/test_integerset/test_integerset.c b/src/test/modules/test_integerset/test_integerset.c
index cfdc6762785..7ac1fe6cb23 100644
--- a/src/test/modules/test_integerset/test_integerset.c
+++ b/src/test/modules/test_integerset/test_integerset.c
@@ -385,7 +385,7 @@ test_single_value_and_filler(uint64 value, uint64 filler_min, uint64 filler_max)
 
 	intset = intset_create();
 
-	iter_expected = palloc(sizeof(uint64) * (filler_max - filler_min + 1));
+	iter_expected = palloc_array(uint64, filler_max - filler_min + 1);
 	if (value < filler_min)
 	{
 		intset_add_member(intset, value);
diff --git a/src/test/modules/test_json_parser/test_json_parser_incremental.c b/src/test/modules/test_json_parser/test_json_parser_incremental.c
index 8c78061ee46..a95ac798481 100644
--- a/src/test/modules/test_json_parser/test_json_parser_incremental.c
+++ b/src/test/modules/test_json_parser/test_json_parser_incremental.c
@@ -124,7 +124,7 @@ main(int argc, char **argv)
 				break;
 			case 's':			/* do semantic processing */
 				testsem = &sem;
-				sem.semstate = palloc(sizeof(struct DoState));
+				sem.semstate = palloc_object(struct DoState);
 				((struct DoState *) sem.semstate)->lex = lex;
 				((struct DoState *) sem.semstate)->buf = makeStringInfo();
 				need_strings = true;
diff --git a/src/test/modules/test_parser/test_parser.c b/src/test/modules/test_parser/test_parser.c
index 15ed3617cb5..353f9072819 100644
--- a/src/test/modules/test_parser/test_parser.c
+++ b/src/test/modules/test_parser/test_parser.c
@@ -46,7 +46,7 @@ PG_FUNCTION_INFO_V1(testprs_lextype);
 Datum
 testprs_start(PG_FUNCTION_ARGS)
 {
-	ParserState *pst = (ParserState *) palloc0(sizeof(ParserState));
+	ParserState *pst = palloc0_object(ParserState);
 
 	pst->buffer = (char *) PG_GETARG_POINTER(0);
 	pst->len = PG_GETARG_INT32(1);
@@ -112,7 +112,7 @@ testprs_lextype(PG_FUNCTION_ARGS)
 	 * the same lexids like Teodor in the default word parser; in this way we
 	 * can reuse the headline function of the default word parser.
 	 */
-	LexDescr   *descr = (LexDescr *) palloc(sizeof(LexDescr) * (2 + 1));
+	LexDescr   *descr = palloc_array(LexDescr, 2 + 1);
 
 	/* there are only two types in this parser */
 	descr[0].lexid = 3;
diff --git a/src/test/modules/test_radixtree/test_radixtree.c b/src/test/modules/test_radixtree/test_radixtree.c
index 787162c8793..ddfcb0c4ac4 100644
--- a/src/test/modules/test_radixtree/test_radixtree.c
+++ b/src/test/modules/test_radixtree/test_radixtree.c
@@ -183,7 +183,7 @@ test_basic(rt_node_class_test_elem *test_info, int shift, bool asc)
 	elog(NOTICE, "testing node %s with shift %d and %s keys",
 		 test_info->class_name, shift, asc ? "ascending" : "descending");
 
-	keys = palloc(sizeof(uint64) * children);
+	keys = palloc_array(uint64, children);
 	for (int i = 0; i < children; i++)
 	{
 		if (asc)
diff --git a/src/test/modules/test_rbtree/test_rbtree.c b/src/test/modules/test_rbtree/test_rbtree.c
index 9113f1c8d52..787c3a60609 100644
--- a/src/test/modules/test_rbtree/test_rbtree.c
+++ b/src/test/modules/test_rbtree/test_rbtree.c
@@ -63,7 +63,7 @@ irbt_combine(RBTNode *existing, const RBTNode *newdata, void *arg)
 static RBTNode *
 irbt_alloc(void *arg)
 {
-	return (RBTNode *) palloc(sizeof(IntRBTreeNode));
+	return &palloc_object(IntRBTreeNode)->rbtnode;
 }
 
 /* Node freer */
diff --git a/src/test/modules/test_regex/test_regex.c b/src/test/modules/test_regex/test_regex.c
index 2548a0ef7b1..675a6674736 100644
--- a/src/test/modules/test_regex/test_regex.c
+++ b/src/test/modules/test_regex/test_regex.c
@@ -107,10 +107,8 @@ test_regex(PG_FUNCTION_ARGS)
 									  true);
 
 		/* Pre-create workspace that build_test_match_result needs */
-		matchctx->elems = (Datum *) palloc(sizeof(Datum) *
-										   (matchctx->npatterns + 1));
-		matchctx->nulls = (bool *) palloc(sizeof(bool) *
-										  (matchctx->npatterns + 1));
+		matchctx->elems = palloc_array(Datum, matchctx->npatterns + 1);
+		matchctx->nulls = palloc_array(bool, matchctx->npatterns + 1);
 
 		MemoryContextSwitchTo(oldcontext);
 		funcctx->user_fctx = matchctx;
@@ -436,7 +434,7 @@ setup_test_matches(text *orig_str,
 				   Oid collation,
 				   bool use_subpatterns)
 {
-	test_regex_ctx *matchctx = palloc0(sizeof(test_regex_ctx));
+	test_regex_ctx *matchctx = palloc0_object(test_regex_ctx);
 	int			eml = pg_database_encoding_max_length();
 	int			orig_len;
 	pg_wchar   *wide_str;
@@ -457,7 +455,7 @@ setup_test_matches(text *orig_str,
 
 	/* convert string to pg_wchar form for matching */
 	orig_len = VARSIZE_ANY_EXHDR(orig_str);
-	wide_str = (pg_wchar *) palloc(sizeof(pg_wchar) * (orig_len + 1));
+	wide_str = palloc_array(pg_wchar, orig_len + 1);
 	wide_len = pg_mb2wchar_with_len(VARDATA_ANY(orig_str), wide_str, orig_len);
 
 	/* do we want to remember subpatterns? */
@@ -474,7 +472,7 @@ setup_test_matches(text *orig_str,
 	}
 
 	/* temporary output space for RE package */
-	pmatch = palloc(sizeof(regmatch_t) * pmatch_len);
+	pmatch = palloc_array(regmatch_t, pmatch_len); 
 
 	/*
 	 * the real output space (grown dynamically if needed)
@@ -483,7 +481,7 @@ setup_test_matches(text *orig_str,
 	 * than at 2^27
 	 */
 	array_len = re_flags->glob ? 255 : 31;
-	matchctx->match_locs = (int *) palloc(sizeof(int) * array_len);
+	matchctx->match_locs = palloc_array(int, array_len);
 	array_idx = 0;
 
 	/* search for the pattern, perhaps repeatedly */
diff --git a/src/test/modules/test_resowner/test_resowner_many.c b/src/test/modules/test_resowner/test_resowner_many.c
index 1f64939404f..e43f911244a 100644
--- a/src/test/modules/test_resowner/test_resowner_many.c
+++ b/src/test/modules/test_resowner/test_resowner_many.c
@@ -121,7 +121,7 @@ RememberManyTestResources(ResourceOwner owner,
 
 	for (int i = 0; i < nresources; i++)
 	{
-		ManyTestResource *mres = palloc(sizeof(ManyTestResource));
+		ManyTestResource *mres = palloc_object(ManyTestResource);
 
 		mres->kind = &kinds[kind_idx];
 		dlist_node_init(&mres->node);
diff --git a/src/test/modules/test_rls_hooks/test_rls_hooks.c b/src/test/modules/test_rls_hooks/test_rls_hooks.c
index b1f161cf7bb..86453f96147 100644
--- a/src/test/modules/test_rls_hooks/test_rls_hooks.c
+++ b/src/test/modules/test_rls_hooks/test_rls_hooks.c
@@ -44,7 +44,7 @@ List *
 test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
 {
 	List	   *policies = NIL;
-	RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
+	RowSecurityPolicy *policy = palloc0_object(RowSecurityPolicy);
 	Datum		role;
 	FuncCall   *n;
 	Node	   *e;
@@ -112,7 +112,7 @@ List *
 test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)
 {
 	List	   *policies = NIL;
-	RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
+	RowSecurityPolicy *policy = palloc0_object(RowSecurityPolicy);
 	Datum		role;
 	FuncCall   *n;
 	Node	   *e;
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index bea8339f464..1a21b8c8876 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -142,7 +142,7 @@ worker_spi_main(Datum main_arg)
 	char	   *p;
 	bits32		flags = 0;
 
-	table = palloc(sizeof(worktable));
+	table = palloc_object(worktable);
 	sprintf(name, "schema%d", index);
 	table->schema = pstrdup(name);
 	table->name = pstrdup("counted");
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index 56cc0567b1c..c27305cf10b 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -198,7 +198,7 @@ widget_in(PG_FUNCTION_ARGS)
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"widget", str)));
 
-	result = (WIDGET *) palloc(sizeof(WIDGET));
+	result = palloc_object(WIDGET);
 	result->center.x = atof(coord[0]);
 	result->center.y = atof(coord[1]);
 	result->radius = atof(coord[2]);
diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
index 504c0235ffb..505a2d33839 100644
--- a/src/timezone/pgtz.c
+++ b/src/timezone/pgtz.c
@@ -396,7 +396,7 @@ struct pg_tzenum
 pg_tzenum *
 pg_tzenumerate_start(void)
 {
-	pg_tzenum  *ret = (pg_tzenum *) palloc0(sizeof(pg_tzenum));
+	pg_tzenum  *ret = palloc0_object(pg_tzenum);
 	char	   *startdir = pstrdup(pg_TZDIR());
 
 	ret->baselen = strlen(startdir) + 1;
diff --git a/src/tutorial/complex.c b/src/tutorial/complex.c
index 6798a9e6ba6..46dc54e62d0 100644
--- a/src/tutorial/complex.c
+++ b/src/tutorial/complex.c
@@ -41,7 +41,7 @@ complex_in(PG_FUNCTION_ARGS)
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"complex", str)));
 
-	result = (Complex *) palloc(sizeof(Complex));
+	result = palloc_object(Complex);
 	result->x = x;
 	result->y = y;
 	PG_RETURN_POINTER(result);
@@ -73,7 +73,7 @@ complex_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	Complex    *result;
 
-	result = (Complex *) palloc(sizeof(Complex));
+	result = palloc_object(Complex);
 	result->x = pq_getmsgfloat8(buf);
 	result->y = pq_getmsgfloat8(buf);
 	PG_RETURN_POINTER(result);
@@ -108,7 +108,7 @@ complex_add(PG_FUNCTION_ARGS)
 	Complex    *b = (Complex *) PG_GETARG_POINTER(1);
 	Complex    *result;
 
-	result = (Complex *) palloc(sizeof(Complex));
+	result = palloc_object(Complex);
 	result->x = a->x + b->x;
 	result->y = a->y + b->y;
 	PG_RETURN_POINTER(result);
diff --git a/src/tutorial/funcs.c b/src/tutorial/funcs.c
index 3cc94534187..80882cf1414 100644
--- a/src/tutorial/funcs.c
+++ b/src/tutorial/funcs.c
@@ -50,7 +50,7 @@ makepoint(PG_FUNCTION_ARGS)
 {
 	Point	   *pointx = PG_GETARG_POINT_P(0);
 	Point	   *pointy = PG_GETARG_POINT_P(1);
-	Point	   *new_point = (Point *) palloc(sizeof(Point));
+	Point	   *new_point = palloc_object(Point);
 
 	new_point->x = pointx->x;
 	new_point->y = pointy->y;
-- 
2.51.0



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
@ 2025-11-26 23:03 ` Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2 siblings, 1 reply; 29+ messages in thread

From: Chao Li @ 2025-11-26 23:03 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: pgsql-hackers



> On Nov 27, 2025, at 06:09, David Geier <geidav.pg@gmail.com> wrote:
> 
> Hi hackers,
> 
> I've changed all code to use the "new" palloc_object(), palloc_array(),
> palloc0_object(), palloc0_array, repalloc_array() and repalloc0_array()
> macros. This makes the code more readable and more consistent.
> 
> The patch is pretty big but potential merge conflicts should be easy to
> resolve. If preferred, I can also further split up the patch, e.g.
> directory by directory or high impact files first.
> 
> The patch is passing "meson test" and I've additionally wrote a script
> that parses the patch file and verifies that every two corresponding +
> and - lines match (e.g. palloc0() replaced by palloc0_array() or
> palloc0_object(), the same for palloc() and repalloc(), additionally
> some checks to make sure the conversion to the _array() variant is
> correct).
> 
> --
> David Geier<v1-0001-Consistently-use-palloc_object-and-palloc_array.patch>

This is a large patch, I just take a quick look, and found that:

```
-		*phoned_word = palloc(sizeof(char) * strlen(word) + 1);
+		*phoned_word = palloc_array(char, strlen(word) + 1);
```

And

```
-		params = (const char **) palloc(sizeof(char *));
+		params = palloc_object(const char *);
```

Applying palloc_array and palloc_object to char type doesn’t seem to improve anything.

Best reagards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/









^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
@ 2025-11-28 21:06   ` David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 1 reply; 29+ messages in thread

From: David Geier @ 2025-11-28 21:06 UTC (permalink / raw)
  To: Chao Li <li.evan.chao@gmail.com>; +Cc: pgsql-hackers

Hi!

Thanks for taking a look.

On 27.11.2025 00:03, Chao Li wrote:
> 
> This is a large patch, I just take a quick look, and found that:
> 
> ```
> -		*phoned_word = palloc(sizeof(char) * strlen(word) + 1);
> +		*phoned_word = palloc_array(char, strlen(word) + 1);
> ```
> 
> And
> 
> ```
> -		params = (const char **) palloc(sizeof(char *));
> +		params = palloc_object(const char *);
> ```
> 
> Applying palloc_array and palloc_object to char type doesn’t seem to improve anything.
> 

You mean because sizeof(char) is always 1 and hence we could instead
simply write:

*phoned_word = palloc(strlen(word) + 1);
params = palloc(1);

I think the _array and _object variants are more expressive and for sure
don't make the code less readable.

--
David Geier





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
@ 2025-11-28 21:28     ` Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  0 siblings, 1 reply; 29+ messages in thread

From: Tom Lane @ 2025-11-28 21:28 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

David Geier <geidav.pg@gmail.com> writes:
> On 27.11.2025 00:03, Chao Li wrote:
>> This is a large patch, I just take a quick look, and found that:
>> -		*phoned_word = palloc(sizeof(char) * strlen(word) + 1);
>> +		*phoned_word = palloc_array(char, strlen(word) + 1);
>> And
>> -		params = (const char **) palloc(sizeof(char *));
>> +		params = palloc_object(const char *);
>> Applying palloc_array and palloc_object to char type doesn’t seem to improve anything.

> You mean because sizeof(char) is always 1 and hence we could instead
> simply write:
> 		*phoned_word = palloc(strlen(word) + 1);
> 		params = palloc(1);
> I think the _array and _object variants are more expressive and for sure
> don't make the code less readable.

Yeah, I agree these particular changes seem fine.  When you're doing
address arithmetic for a memcpy or such, it may be fine to wire in an
assumption that sizeof(char) == 1, but I think doing that in other
contexts is not particularly good style.

Another thing to note is that the proposed patch effectively changes
the expression evaluation order:

-		*phoned_word = palloc((sizeof(char) * strlen(word)) + 1);
+		*phoned_word = palloc(sizeof(char) * (strlen(word) + 1));

Now, there's not actually any difference because sizeof(char) is 1,
but if it hypothetically weren't, the new version is likely more
correct.  Presumably the +1 is meant to allow room for a trailing \0,
which is a char.

It'd be a good idea to review the patch to see if there are any
places where semantics are changed in a less benign fashion...

			regards, tom lane





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
@ 2025-11-28 21:47       ` David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  0 siblings, 1 reply; 29+ messages in thread

From: David Geier @ 2025-11-28 21:47 UTC (permalink / raw)
  To: Tom Lane <tgl@sss.pgh.pa.us>; +Cc: Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On 28.11.2025 22:28, Tom Lane wrote:
> David Geier <geidav.pg@gmail.com> writes:
>> On 27.11.2025 00:03, Chao Li wrote:
>>> This is a large patch, I just take a quick look, and found that:
>>> -		*phoned_word = palloc(sizeof(char) * strlen(word) + 1);
>>> +		*phoned_word = palloc_array(char, strlen(word) + 1);
>>> And
>>> -		params = (const char **) palloc(sizeof(char *));
>>> +		params = palloc_object(const char *);
>>> Applying palloc_array and palloc_object to char type doesn’t seem to improve anything.
> 
>> You mean because sizeof(char) is always 1 and hence we could instead
>> simply write:
>> 		*phoned_word = palloc(strlen(word) + 1);
>> 		params = palloc(1);
>> I think the _array and _object variants are more expressive and for sure
>> don't make the code less readable.
> 
> Yeah, I agree these particular changes seem fine.  When you're doing
> address arithmetic for a memcpy or such, it may be fine to wire in an
> assumption that sizeof(char) == 1, but I think doing that in other
> contexts is not particularly good style.
> 
> Another thing to note is that the proposed patch effectively changes
> the expression evaluation order:
> 
> -		*phoned_word = palloc((sizeof(char) * strlen(word)) + 1);
> +		*phoned_word = palloc(sizeof(char) * (strlen(word) + 1));
> 
> Now, there's not actually any difference because sizeof(char) is 1,
> but if it hypothetically weren't, the new version is likely more
> correct.  Presumably the +1 is meant to allow room for a trailing \0,
> which is a char.

Oh right. Good catch!

> It'd be a good idea to review the patch to see if there are any
> places where semantics are changed in a less benign fashion...

I intentionally tried to avoid any semantic changes but it's of course
possible something slipped through by accident.

It's some ~1700 occurrences in the patch. If it takes ~10 seconds to
check a single, it would take ~4.7h to review the entire patch.

If no one is willing to take this on, I could split up the patch in 4 to
5 that each can be reviewed by someone else.

--
David Geier





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
@ 2025-11-28 22:31         ` Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  0 siblings, 1 reply; 29+ messages in thread

From: Thomas Munro @ 2025-11-28 22:31 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On Sat, Nov 29, 2025 at 10:47 AM David Geier <geidav.pg@gmail.com> wrote:
> I intentionally tried to avoid any semantic changes but it's of course
> possible something slipped through by accident.

Do you expect the generated code to be identical?  Is it?





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
@ 2025-12-02 15:13           ` David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  0 siblings, 1 reply; 29+ messages in thread

From: David Geier @ 2025-12-02 15:13 UTC (permalink / raw)
  To: Thomas Munro <thomas.munro@gmail.com>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On 28.11.2025 23:31, Thomas Munro wrote:
> On Sat, Nov 29, 2025 at 10:47 AM David Geier <geidav.pg@gmail.com> wrote:
>> I intentionally tried to avoid any semantic changes but it's of course
>> possible something slipped through by accident.
> 
> Do you expect the generated code to be identical?  Is it?

In the majority of cases yes. However, there are a few cases where a
small change in the C code can yield to differences in the generated code:

I used the following bash script to create the disassembly of all object
files in the build directory. I ran this script twice, once on master
and once on the patched branch. The directory needs to be adapted
accordingly in the script.

find . -name "*.o" -print0 | while IFS= read -r -d '' file; do
    mkdir -p ~/Desktop/master/"$(dirname "$file")"

    if objdump -drwC -Mintel "$file" > ~/Desktop/master/"$file".dis
2>/dev/null; then
        echo "  ✓ Disassembled to ~/Desktop/master/$file.dis"
    else
        echo "  ✗ Failed to disassemble $file"
    fi
done

There are 54 files that show changes in the generated code. I didn't
look through all files but the changes are largely caused by the same
reasons:

1) If the refactoring introduces a change in the number of lines, the
__LINE__ macro used by elog.h will cause a change in the disassembly.
This is the reason for the majority of changes.

2) fuzzystrmatch.c: contains a functional change. We allocate 1 byte
more now but that is safe, see [1].

3) pg_buffercache_pages.c: Functional change. Type used in
palloc_array() changed from uint64 to int, as the rest of the code only
uses an integer.

4) trgm_op.c: Contains arithmetic expressions in the calls to
palloc_array() where now the brackets are placed differently, e.g.
sizeof(type) * a * b vs sizeof(type) * (a * b). That's the reason for
many differences.

So reviewing this patch can now be done by only going through all files
that have changes in the disassembly. This is only 54 out of which most
are because of changes in the number of LOC or where the brackets are
placed.

[1] https://www.postgresql.org/message-id/524587.1764365323%40sss.pgh.pa.us

--
David Geier





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
@ 2025-12-03 00:35             ` Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 1 reply; 29+ messages in thread

From: Michael Paquier @ 2025-12-03 00:35 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: Thomas Munro <thomas.munro@gmail.com>; Tom Lane <tgl@sss.pgh.pa.us>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On Tue, Dec 02, 2025 at 04:13:01PM +0100, David Geier wrote:
> So reviewing this patch can now be done by only going through all files
> that have changes in the disassembly. This is only 54 out of which most
> are because of changes in the number of LOC or where the brackets are
> placed.

It may be a good idea to split the patch into two parts, at least:
- One for the bulk of the changes, for the straight-forward changes.
Most of what you are suggesting are that for palloc_object and
palloc_array which are dropped-in replacements.  Checking that these
assemble the same before and after offers one extra layer of
confidence.
- Second one for the more dubious changes.

It does not change that all these need to be looked with human eyes.
For the first one, splitting things based on the code area is simpler
With more than 1.7k places changed, splitting by area and checking
them individually would be the best course, at least for me when it
comes to such mechanical changes.  It comes down with dealing with
individual doses that are not so large that they cause one's head to
spin in the middle of checking the diffs (did that a few times in the
past for this code tree, splitting and dose balance helps a lot).

I cannot say for the others, but I find the type-safety argument
mentioned upthread good enough to do a switch and encourage more the
new style moving forward.
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../aS-F6LkeDBEly9nz@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
@ 2025-12-03 00:40               ` Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  0 siblings, 1 reply; 29+ messages in thread

From: Tom Lane @ 2025-12-03 00:40 UTC (permalink / raw)
  To: Michael Paquier <michael@paquier.xyz>; +Cc: David Geier <geidav.pg@gmail.com>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

Michael Paquier <michael@paquier.xyz> writes:
> It may be a good idea to split the patch into two parts, at least:
> - One for the bulk of the changes, for the straight-forward changes.
> Most of what you are suggesting are that for palloc_object and
> palloc_array which are dropped-in replacements.  Checking that these
> assemble the same before and after offers one extra layer of
> confidence.
> - Second one for the more dubious changes.

Yeah, I was thinking the same.  Some of those might perhaps be bugs
that we want to back-patch, so they need to be looked at in a
different way.

			regards, tom lane





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
@ 2025-12-04 09:31                 ` David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  0 siblings, 1 reply; 29+ messages in thread

From: David Geier @ 2025-12-04 09:31 UTC (permalink / raw)
  To: Tom Lane <tgl@sss.pgh.pa.us>; Michael Paquier <michael@paquier.xyz>; +Cc: Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On 03.12.2025 01:40, Tom Lane wrote:
> Michael Paquier <michael@paquier.xyz> writes:
>> It may be a good idea to split the patch into two parts, at least:
>> - One for the bulk of the changes, for the straight-forward changes.
>> Most of what you are suggesting are that for palloc_object and
>> palloc_array which are dropped-in replacements.  Checking that these
>> assemble the same before and after offers one extra layer of
>> confidence.
>> - Second one for the more dubious changes.
> 
> Yeah, I was thinking the same.  Some of those might perhaps be bugs
> that we want to back-patch, so they need to be looked at in a
> different way.
> 
> 			regards, tom lane

Attached are the two patches, rebased on latest master.

The first one contains all changes that either result in no changes to
the disassembly, or only in changes due to the line counts; because
elog.h makes use of __LINE__.

The second patch contains the remaining changes, which is only 11 files.

contrib/fuzzystrmatch/fuzzystrmatch.c: semantic changes, e.g.
  palloc(sizeof(char) * strlen(word) + 1);
  =>
  palloc_array(char, strlen(word) + 1);

contrib/pg_buffercache/pg_buffercache_pages.c: semantic change
  palloc(sizeof(uint64) * os_page_count);
  =>
  palloc_array(int, os_page_count);

src/test/modules/test_rbtree/test_rbtree.c: different way to get pointer
  return (RBTNode *) palloc(sizeof(IntRBTreeNode));
  =>
  return &palloc_object(IntRBTreeNode)->rbtnode;

contrib/hstore/hstore_gin.c
contrib/hstore/hstore_op.c
contrib/pg_trgm/trgm_op.c
contrib/postgres_fdw/postgres_fdw.c
src/backend/executor/execPartition.c
src/backend/partitioning/partprune.c
src/backend/statistics/mvdistinct.c
src/backend/storage/buffer/bufmgr.c
  All files contain arithmetic expressions for the count argument of
palloc[0]_array(). The parentheses can change the order in which the
arguments are evaluated which changes the generated code.

--
David Geier

Attachments:

  [text/x-patch] v2-0002-Consistently-use-palloc_object-and-palloc_array-diff.patch (24.9K, ../../4ab4a12b-49e9-4ebf-9055-225c8055fed0@gmail.com/2-v2-0002-Consistently-use-palloc_object-and-palloc_array-diff.patch)
  download | inline diff:
From 06000d529f8501ed47547268c7bfdb4a6d4a299b Mon Sep 17 00:00:00 2001
From: David Geier <geidav.pg@gmail.com>
Date: Thu, 4 Dec 2025 09:51:52 +0100
Subject: [PATCH 2/2] Consistently use palloc_object() and palloc_array() -
 different generated code

---
 contrib/fuzzystrmatch/fuzzystrmatch.c         |  4 +--
 contrib/hstore/hstore_gin.c                   |  6 ++--
 contrib/hstore/hstore_op.c                    | 18 ++++++------
 contrib/pg_buffercache/pg_buffercache_pages.c |  8 +++---
 contrib/pg_trgm/trgm_op.c                     | 20 ++++++-------
 contrib/postgres_fdw/postgres_fdw.c           | 22 +++++++--------
 src/backend/executor/execPartition.c          | 28 ++++++++-----------
 src/backend/partitioning/partprune.c          | 24 ++++++++--------
 src/backend/statistics/mvdistinct.c           | 14 +++++-----
 src/backend/storage/buffer/bufmgr.c           |  8 +++---
 src/test/modules/test_rbtree/test_rbtree.c    |  2 +-
 11 files changed, 74 insertions(+), 80 deletions(-)

diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.c b/contrib/fuzzystrmatch/fuzzystrmatch.c
index e7cc314b763..c8f76dfc833 100644
--- a/contrib/fuzzystrmatch/fuzzystrmatch.c
+++ b/contrib/fuzzystrmatch/fuzzystrmatch.c
@@ -370,11 +370,11 @@ _metaphone(char *word,			/* IN */
 	/*-- Allocate memory for our phoned_phrase --*/
 	if (max_phonemes == 0)
 	{							/* Assume largest possible */
-		*phoned_word = palloc(sizeof(char) * strlen(word) + 1);
+		*phoned_word = palloc_array(char, strlen(word) + 1);
 	}
 	else
 	{
-		*phoned_word = palloc(sizeof(char) * max_phonemes + 1);
+		*phoned_word = palloc_array(char, max_phonemes + 1);
 	}
 
 	/*-- The first phoneme has to be processed specially. --*/
diff --git a/contrib/hstore/hstore_gin.c b/contrib/hstore/hstore_gin.c
index 2e5fa115924..4e43aeeb05d 100644
--- a/contrib/hstore/hstore_gin.c
+++ b/contrib/hstore/hstore_gin.c
@@ -53,7 +53,7 @@ gin_extract_hstore(PG_FUNCTION_ARGS)
 
 	*nentries = 2 * count;
 	if (count)
-		entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
+		entries = palloc_array(Datum, 2 * count);
 
 	for (i = 0; i < count; ++i)
 	{
@@ -103,7 +103,7 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
 		text	   *item;
 
 		*nentries = 1;
-		entries = (Datum *) palloc(sizeof(Datum));
+		entries = palloc_object(Datum);
 		item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query), KEYFLAG);
 		entries[0] = PointerGetDatum(item);
 	}
@@ -120,7 +120,7 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
 
 		deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
 
-		entries = (Datum *) palloc(sizeof(Datum) * key_count);
+		entries = palloc_array(Datum, key_count);
 
 		for (i = 0, j = 0; i < key_count; ++i)
 		{
diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
index bcba75f9258..cab59700c0d 100644
--- a/contrib/hstore/hstore_op.c
+++ b/contrib/hstore/hstore_op.c
@@ -101,7 +101,7 @@ hstoreArrayToPairs(ArrayType *a, int *npairs)
 				 errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
 						key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
 
-	key_pairs = palloc(sizeof(Pairs) * key_count);
+	key_pairs = palloc_array(Pairs, key_count);
 
 	for (i = 0, j = 0; i < key_count; i++)
 	{
@@ -588,8 +588,8 @@ hstore_slice_to_array(PG_FUNCTION_ARGS)
 		PG_RETURN_POINTER(aout);
 	}
 
-	out_datums = palloc(sizeof(Datum) * key_count);
-	out_nulls = palloc(sizeof(bool) * key_count);
+	out_datums = palloc_array(Datum, key_count);
+	out_nulls = palloc_array(bool, key_count);
 
 	for (i = 0; i < key_count; ++i)
 	{
@@ -649,7 +649,7 @@ hstore_slice_to_hstore(PG_FUNCTION_ARGS)
 	}
 
 	/* hstoreArrayToPairs() checked overflow */
-	out_pairs = palloc(sizeof(Pairs) * nkeys);
+	out_pairs = palloc_array(Pairs, nkeys);
 	bufsiz = 0;
 
 	/*
@@ -705,7 +705,7 @@ hstore_akeys(PG_FUNCTION_ARGS)
 		PG_RETURN_POINTER(a);
 	}
 
-	d = (Datum *) palloc(sizeof(Datum) * count);
+	d = palloc_array(Datum, count);
 
 	for (i = 0; i < count; ++i)
 	{
@@ -741,8 +741,8 @@ hstore_avals(PG_FUNCTION_ARGS)
 		PG_RETURN_POINTER(a);
 	}
 
-	d = (Datum *) palloc(sizeof(Datum) * count);
-	nulls = (bool *) palloc(sizeof(bool) * count);
+	d = palloc_array(Datum, count);
+	nulls = palloc_array(bool, count);
 
 	for (i = 0; i < count; ++i)
 	{
@@ -786,8 +786,8 @@ hstore_to_array_internal(HStore *hs, int ndims)
 		return construct_empty_array(TEXTOID);
 
 	out_size[0] = count * 2 / ndims;
-	out_datums = palloc(sizeof(Datum) * count * 2);
-	out_nulls = palloc(sizeof(bool) * count * 2);
+	out_datums = palloc_array(Datum, count * 2);
+	out_nulls = palloc_array(bool, count * 2);
 
 	for (i = 0; i < count; ++i)
 	{
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index 702307a49e2..0c58e4b265c 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -134,7 +134,7 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* Create a user function context for cross-call persistence */
-		fctx = (BufferCachePagesContext *) palloc(sizeof(BufferCachePagesContext));
+		fctx = palloc_object(BufferCachePagesContext);
 
 		/*
 		 * To smoothly support upgrades from version 1.0 of this extension
@@ -382,8 +382,8 @@ pg_buffercache_os_pages_internal(FunctionCallInfo fcinfo, bool include_numa)
 			os_page_count = (endptr - startptr) / os_page_size;
 
 			/* Used to determine the NUMA node for all OS pages at once */
-			os_page_ptrs = palloc0(sizeof(void *) * os_page_count);
-			os_page_status = palloc(sizeof(uint64) * os_page_count);
+			os_page_ptrs = palloc0_array(void *, os_page_count);
+			os_page_status = palloc_array(int, os_page_count);
 
 			/*
 			 * Fill pointers for all the memory pages.  This loop stores and
@@ -425,7 +425,7 @@ pg_buffercache_os_pages_internal(FunctionCallInfo fcinfo, bool include_numa)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* Create a user function context for cross-call persistence */
-		fctx = (BufferCacheOsPagesContext *) palloc(sizeof(BufferCacheOsPagesContext));
+		fctx = palloc_object(BufferCacheOsPagesContext);
 
 		if (get_call_result_type(fcinfo, NULL, &expected_tupledesc) != TYPEFUNC_COMPOSITE)
 			elog(ERROR, "return type must be a row type");
diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c
index 29b39ec8a4c..72dd8c6d504 100644
--- a/contrib/pg_trgm/trgm_op.c
+++ b/contrib/pg_trgm/trgm_op.c
@@ -452,7 +452,7 @@ make_positional_trgm(trgm *trg1, int len1, trgm *trg2, int len2)
 	int			i,
 				len = len1 + len2;
 
-	result = (pos_trgm *) palloc(sizeof(pos_trgm) * len);
+	result = palloc_array(pos_trgm, len);
 
 	for (i = 0; i < len1; i++)
 	{
@@ -535,7 +535,7 @@ iterate_word_similarity(int *trg2indexes,
 	lower = (flags & WORD_SIMILARITY_STRICT) ? 0 : -1;
 
 	/* Memorise last position of each trigram */
-	lastpos = (int *) palloc(sizeof(int) * len);
+	lastpos = palloc_array(int, len);
 	memset(lastpos, -1, sizeof(int) * len);
 
 	for (i = 0; i < len2; i++)
@@ -690,10 +690,10 @@ calc_word_similarity(char *str1, int slen1, char *str2, int slen2,
 	protect_out_of_mem(slen1 + slen2);
 
 	/* Make positional trigrams */
-	trg1 = (trgm *) palloc(sizeof(trgm) * (slen1 / 2 + 1) * 3);
-	trg2 = (trgm *) palloc(sizeof(trgm) * (slen2 / 2 + 1) * 3);
+	trg1 = palloc_array(trgm, (slen1 / 2 + 1) * 3);
+	trg2 = palloc_array(trgm, (slen2 / 2 + 1) * 3);
 	if (flags & WORD_SIMILARITY_STRICT)
-		bounds = (TrgmBound *) palloc0(sizeof(TrgmBound) * (slen2 / 2 + 1) * 3);
+		bounds = palloc0_array(TrgmBound, (slen2 / 2 + 1) * 3);
 	else
 		bounds = NULL;
 
@@ -711,8 +711,8 @@ calc_word_similarity(char *str1, int slen1, char *str2, int slen2,
 	 * Merge positional trigrams array: enumerate each trigram and find its
 	 * presence in required word.
 	 */
-	trg2indexes = (int *) palloc(sizeof(int) * len2);
-	found = (bool *) palloc0(sizeof(bool) * len);
+	trg2indexes = palloc_array(int, len2);
+	found = palloc0_array(bool, len);
 
 	ulen1 = 0;
 	j = 0;
@@ -938,7 +938,7 @@ generate_wildcard_trgm(const char *str, int slen)
 	tptr = GETARR(trg);
 
 	/* Allocate a buffer for blank-padded, but not yet case-folded, words */
-	buf = palloc(sizeof(char) * (slen + 4));
+	buf = palloc_array(char, slen + 4);
 
 	/*
 	 * Extract trigrams from each substring extracted by get_wildcard_part.
@@ -1008,7 +1008,7 @@ show_trgm(PG_FUNCTION_ARGS)
 	int			i;
 
 	trg = generate_trgm(VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
-	d = (Datum *) palloc(sizeof(Datum) * (1 + ARRNELEM(trg)));
+	d = palloc_array(Datum, 1 + ARRNELEM(trg));
 
 	for (i = 0, ptr = GETARR(trg); i < ARRNELEM(trg); i++, ptr++)
 	{
@@ -1136,7 +1136,7 @@ trgm_presence_map(TRGM *query, TRGM *key)
 				lenk = ARRNELEM(key),
 				i;
 
-	result = (bool *) palloc0(lenq * sizeof(bool));
+	result = palloc0_array(bool, lenq);
 
 	/* for each query trigram, do a binary search in the key array */
 	for (i = 0; i < lenq; i++)
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 06b52c65300..b293a7904fb 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -633,7 +633,7 @@ postgresGetForeignRelSize(PlannerInfo *root,
 	 * We use PgFdwRelationInfo to pass various information to subsequent
 	 * functions.
 	 */
-	fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
+	fpinfo = palloc0_object(PgFdwRelationInfo);
 	baserel->fdw_private = fpinfo;
 
 	/* Base foreign tables need to be pushed down always. */
@@ -1517,7 +1517,7 @@ postgresBeginForeignScan(ForeignScanState *node, int eflags)
 	/*
 	 * We'll save private state in node->fdw_state.
 	 */
-	fsstate = (PgFdwScanState *) palloc0(sizeof(PgFdwScanState));
+	fsstate = palloc0_object(PgFdwScanState);
 	node->fdw_state = fsstate;
 
 	/*
@@ -2663,7 +2663,7 @@ postgresBeginDirectModify(ForeignScanState *node, int eflags)
 	/*
 	 * We'll save private state in node->fdw_state.
 	 */
-	dmstate = (PgFdwDirectModifyState *) palloc0(sizeof(PgFdwDirectModifyState));
+	dmstate = palloc0_object(PgFdwDirectModifyState);
 	node->fdw_state = dmstate;
 
 	/*
@@ -3977,7 +3977,7 @@ create_foreign_modify(EState *estate,
 	ListCell   *lc;
 
 	/* Begin constructing PgFdwModifyState. */
-	fmstate = (PgFdwModifyState *) palloc0(sizeof(PgFdwModifyState));
+	fmstate = palloc0_object(PgFdwModifyState);
 	fmstate->rel = rel;
 
 	/* Identify which user to do the remote access as. */
@@ -4014,7 +4014,7 @@ create_foreign_modify(EState *estate,
 
 	/* Prepare for output conversion of parameters used in prepared stmt. */
 	n_params = list_length(fmstate->target_attrs) + 1;
-	fmstate->p_flinfo = (FmgrInfo *) palloc0(sizeof(FmgrInfo) * n_params);
+	fmstate->p_flinfo = palloc0_array(FmgrInfo, n_params);
 	fmstate->p_nums = 0;
 
 	if (operation == CMD_UPDATE || operation == CMD_DELETE)
@@ -4256,7 +4256,7 @@ convert_prep_stmt_params(PgFdwModifyState *fmstate,
 
 	oldcontext = MemoryContextSwitchTo(fmstate->temp_cxt);
 
-	p_values = (const char **) palloc(sizeof(char *) * fmstate->p_nums * numSlots);
+	p_values = palloc_array(const char *, fmstate->p_nums * numSlots); 
 
 	/* ctid is provided only for UPDATE/DELETE, which don't allow batching */
 	Assert(!(tupleid != NULL && numSlots > 1));
@@ -4814,7 +4814,7 @@ prepare_query_params(PlanState *node,
 	Assert(numParams > 0);
 
 	/* Prepare for output conversion of parameters used in remote query. */
-	*param_flinfo = (FmgrInfo *) palloc0(sizeof(FmgrInfo) * numParams);
+	*param_flinfo = palloc0_array(FmgrInfo, numParams);
 
 	i = 0;
 	foreach(lc, fdw_exprs)
@@ -6297,7 +6297,7 @@ postgresGetForeignJoinPaths(PlannerInfo *root,
 	 * if found safe. Once we know that this join can be pushed down, we fill
 	 * the entry.
 	 */
-	fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
+	fpinfo = palloc0_object(PgFdwRelationInfo);
 	fpinfo->pushdown_safe = false;
 	joinrel->fdw_private = fpinfo;
 	/* attrs_used is only for base relations. */
@@ -6666,7 +6666,7 @@ postgresGetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage,
 		output_rel->fdw_private)
 		return;
 
-	fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
+	fpinfo = palloc0_object(PgFdwRelationInfo);
 	fpinfo->pushdown_safe = false;
 	fpinfo->stage = stage;
 	output_rel->fdw_private = fpinfo;
@@ -6891,7 +6891,7 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel,
 	fpinfo->pushdown_safe = true;
 
 	/* Construct PgFdwPathExtraData */
-	fpextra = (PgFdwPathExtraData *) palloc0(sizeof(PgFdwPathExtraData));
+	fpextra = palloc0_object(PgFdwPathExtraData);
 	fpextra->target = root->upper_targets[UPPERREL_ORDERED];
 	fpextra->has_final_sort = true;
 
@@ -7125,7 +7125,7 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel,
 	fpinfo->pushdown_safe = true;
 
 	/* Construct PgFdwPathExtraData */
-	fpextra = (PgFdwPathExtraData *) palloc0(sizeof(PgFdwPathExtraData));
+	fpextra = palloc0_object(PgFdwPathExtraData);
 	fpextra->target = root->upper_targets[UPPERREL_FINAL];
 	fpextra->has_final_sort = has_final_sort;
 	fpextra->has_limit = extra->limit_needed;
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index b3960bb7151..e30db12113b 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -227,7 +227,7 @@ ExecSetupPartitionTupleRouting(EState *estate, Relation rel)
 	 * The reason for this is that a common case is for INSERT to insert a
 	 * single tuple into a partitioned table and this must be fast.
 	 */
-	proute = (PartitionTupleRouting *) palloc0(sizeof(PartitionTupleRouting));
+	proute = palloc0_object(PartitionTupleRouting);
 	proute->partition_root = rel;
 	proute->memcxt = CurrentMemoryContext;
 	/* Rest of members initialized by zeroing */
@@ -1198,10 +1198,8 @@ ExecInitRoutingInfo(ModifyTableState *mtstate,
 		if (proute->max_partitions == 0)
 		{
 			proute->max_partitions = 8;
-			proute->partitions = (ResultRelInfo **)
-				palloc(sizeof(ResultRelInfo *) * proute->max_partitions);
-			proute->is_borrowed_rel = (bool *)
-				palloc(sizeof(bool) * proute->max_partitions);
+			proute->partitions = palloc_array(ResultRelInfo *, proute->max_partitions);
+			proute->is_borrowed_rel = palloc_array(bool, proute->max_partitions);
 		}
 		else
 		{
@@ -1316,10 +1314,8 @@ ExecInitPartitionDispatchInfo(EState *estate,
 		if (proute->max_dispatch == 0)
 		{
 			proute->max_dispatch = 4;
-			proute->partition_dispatch_info = (PartitionDispatch *)
-				palloc(sizeof(PartitionDispatch) * proute->max_dispatch);
-			proute->nonleaf_partitions = (ResultRelInfo **)
-				palloc(sizeof(ResultRelInfo *) * proute->max_dispatch);
+			proute->partition_dispatch_info = palloc_array(PartitionDispatch, proute->max_dispatch);
+			proute->nonleaf_partitions = palloc_array(ResultRelInfo *, proute->max_dispatch);
 		}
 		else
 		{
@@ -2211,7 +2207,7 @@ CreatePartitionPruneState(EState *estate, PartitionPruneInfo *pruneinfo,
 			 * arrays are in partition bounds order.
 			 */
 			pprune->nparts = partdesc->nparts;
-			pprune->subplan_map = palloc(sizeof(int) * partdesc->nparts);
+			pprune->subplan_map = palloc_array(int, partdesc->nparts);
 
 			if (partdesc->nparts == pinfo->nparts &&
 				memcmp(partdesc->oids, pinfo->relid_map,
@@ -2238,8 +2234,8 @@ CreatePartitionPruneState(EState *estate, PartitionPruneInfo *pruneinfo,
 				 * attached.  Cope with that by creating a map that skips any
 				 * mismatches.
 				 */
-				pprune->subpart_map = palloc(sizeof(int) * partdesc->nparts);
-				pprune->leafpart_rti_map = palloc(sizeof(int) * partdesc->nparts);
+				pprune->subpart_map = palloc_array(int, partdesc->nparts);
+				pprune->leafpart_rti_map = palloc_array(int, partdesc->nparts);
 
 				for (pp_idx = 0; pp_idx < partdesc->nparts; pp_idx++)
 				{
@@ -2390,16 +2386,14 @@ InitPartitionPruneContext(PartitionPruneContext *context,
 	context->partsupfunc = partkey->partsupfunc;
 
 	/* We'll look up type-specific support functions as needed */
-	context->stepcmpfuncs = (FmgrInfo *)
-		palloc0(sizeof(FmgrInfo) * n_steps * partnatts);
+	context->stepcmpfuncs = palloc0_array(FmgrInfo, n_steps * partnatts);
 
 	context->ppccontext = CurrentMemoryContext;
 	context->planstate = planstate;
 	context->exprcontext = econtext;
 
 	/* Initialize expression state for each expression we need */
-	context->exprstates = (ExprState **)
-		palloc0(sizeof(ExprState *) * n_steps * partnatts);
+	context->exprstates = palloc0_array(ExprState *, n_steps * partnatts);
 	foreach(lc, pruning_steps)
 	{
 		PartitionPruneStepOp *step = (PartitionPruneStepOp *) lfirst(lc);
@@ -2500,7 +2494,7 @@ InitExecPartitionPruneContexts(PartitionPruneState *prunestate,
 		 * indexes to new ones.  For convenience of initialization, we use
 		 * 1-based indexes in this array and leave pruned items as 0.
 		 */
-		new_subplan_indexes = (int *) palloc0(sizeof(int) * n_total_subplans);
+		new_subplan_indexes = palloc0_array(int, n_total_subplans);
 		newidx = 1;
 		i = -1;
 		while ((i = bms_next_member(initially_valid_subplans, i)) >= 0)
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 6fff4034c24..bf3f6d80c7a 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -246,7 +246,7 @@ make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
 	 * that zero can represent an un-filled array entry.
 	 */
 	allpartrelids = NIL;
-	relid_subplan_map = palloc0(sizeof(int) * root->simple_rel_array_size);
+	relid_subplan_map = palloc0_array(int, root->simple_rel_array_size);
 
 	i = 1;
 	foreach(lc, subpaths)
@@ -465,7 +465,7 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
 	 * In this phase we discover whether runtime pruning is needed at all; if
 	 * not, we can avoid doing further work.
 	 */
-	relid_subpart_map = palloc0(sizeof(int) * root->simple_rel_array_size);
+	relid_subpart_map = palloc0_array(int, root->simple_rel_array_size);
 
 	i = 1;
 	rti = -1;
@@ -818,9 +818,9 @@ prune_append_rel_partitions(RelOptInfo *rel)
 	context.boundinfo = rel->boundinfo;
 	context.partcollation = rel->part_scheme->partcollation;
 	context.partsupfunc = rel->part_scheme->partsupfunc;
-	context.stepcmpfuncs = (FmgrInfo *) palloc0(sizeof(FmgrInfo) *
-												context.partnatts *
-												list_length(pruning_steps));
+	context.stepcmpfuncs = palloc0_array(FmgrInfo,
+											 context.partnatts *
+												 list_length(pruning_steps));
 	context.ppccontext = CurrentMemoryContext;
 
 	/* These are not valid when being called from the planner */
@@ -1890,7 +1890,7 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
 			return PARTCLAUSE_MATCH_STEPS;
 		}
 
-		partclause = (PartClauseInfo *) palloc(sizeof(PartClauseInfo));
+		partclause = palloc_object(PartClauseInfo);
 		partclause->keyno = partkeyidx;
 		/* Do pruning with the Boolean equality operator. */
 		partclause->opno = BooleanEqualOperator;
@@ -2147,7 +2147,7 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
 		/*
 		 * Build the clause, passing the negator if applicable.
 		 */
-		partclause = (PartClauseInfo *) palloc(sizeof(PartClauseInfo));
+		partclause = palloc_object(PartClauseInfo);
 		partclause->keyno = partkeyidx;
 		if (is_opne_listp)
 		{
@@ -2693,7 +2693,7 @@ get_matching_hash_bounds(PartitionPruneContext *context,
 						 StrategyNumber opstrategy, const Datum *values, int nvalues,
 						 FmgrInfo *partsupfunc, Bitmapset *nullkeys)
 {
-	PruneStepResult *result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
+	PruneStepResult *result = palloc0_object(PruneStepResult);
 	PartitionBoundInfo boundinfo = context->boundinfo;
 	int		   *partindices = boundinfo->indexes;
 	int			partnatts = context->partnatts;
@@ -2770,7 +2770,7 @@ get_matching_list_bounds(PartitionPruneContext *context,
 						 StrategyNumber opstrategy, Datum value, int nvalues,
 						 FmgrInfo *partsupfunc, Bitmapset *nullkeys)
 {
-	PruneStepResult *result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
+	PruneStepResult *result = palloc0_object(PruneStepResult);
 	PartitionBoundInfo boundinfo = context->boundinfo;
 	int			off,
 				minoff,
@@ -2981,7 +2981,7 @@ get_matching_range_bounds(PartitionPruneContext *context,
 						  StrategyNumber opstrategy, const Datum *values, int nvalues,
 						  FmgrInfo *partsupfunc, Bitmapset *nullkeys)
 {
-	PruneStepResult *result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
+	PruneStepResult *result = palloc0_object(PruneStepResult);
 	PartitionBoundInfo boundinfo = context->boundinfo;
 	Oid		   *partcollation = context->partcollation;
 	int			partnatts = context->partnatts;
@@ -3504,7 +3504,7 @@ perform_pruning_base_step(PartitionPruneContext *context,
 			{
 				PruneStepResult *result;
 
-				result = (PruneStepResult *) palloc(sizeof(PruneStepResult));
+				result = palloc_object(PruneStepResult);
 				result->bound_offsets = NULL;
 				result->scan_default = false;
 				result->scan_null = false;
@@ -3593,7 +3593,7 @@ perform_pruning_combine_step(PartitionPruneContext *context,
 							 PartitionPruneStepCombine *cstep,
 							 PruneStepResult **step_results)
 {
-	PruneStepResult *result = (PruneStepResult *) palloc0(sizeof(PruneStepResult));
+	PruneStepResult *result = palloc0_object(PruneStepResult);
 	bool		firststep;
 	ListCell   *lc1;
 
diff --git a/src/backend/statistics/mvdistinct.c b/src/backend/statistics/mvdistinct.c
index fe452f53ae4..58046d2bd62 100644
--- a/src/backend/statistics/mvdistinct.c
+++ b/src/backend/statistics/mvdistinct.c
@@ -110,7 +110,7 @@ statext_ndistinct_build(double totalrows, StatsBuildData *data)
 			MVNDistinctItem *item = &result->items[itemcnt];
 			int			j;
 
-			item->attributes = palloc(sizeof(AttrNumber) * k);
+			item->attributes = palloc_array(AttrNumber, k);
 			item->nattributes = k;
 
 			/* translate the indexes to attnums */
@@ -359,9 +359,9 @@ ndistinct_for_combination(double totalrows, StatsBuildData *data,
 	 * using the specified column combination as dimensions.  We could try to
 	 * sort in place, but it'd probably be more complex and bug-prone.
 	 */
-	items = (SortItem *) palloc(numrows * sizeof(SortItem));
-	values = (Datum *) palloc0(sizeof(Datum) * numrows * k);
-	isnull = (bool *) palloc0(sizeof(bool) * numrows * k);
+	items = palloc_array(SortItem, numrows);
+	values = palloc0_array(Datum, numrows * k);
+	isnull = palloc0_array(bool, numrows * k);
 
 	for (i = 0; i < numrows; i++)
 	{
@@ -508,12 +508,12 @@ generator_init(int n, int k)
 	Assert((n >= k) && (k > 0));
 
 	/* allocate the generator state as a single chunk of memory */
-	state = (CombinationGenerator *) palloc(sizeof(CombinationGenerator));
+	state = palloc_object(CombinationGenerator);
 
 	state->ncombinations = n_choose_k(n, k);
 
 	/* pre-allocate space for all combinations */
-	state->combinations = (int *) palloc(sizeof(int) * k * state->ncombinations);
+	state->combinations = palloc_array(int, k * state->ncombinations);
 
 	state->current = 0;
 	state->k = k;
@@ -606,7 +606,7 @@ generate_combinations_recurse(CombinationGenerator *state,
 static void
 generate_combinations(CombinationGenerator *state)
 {
-	int		   *current = (int *) palloc0(sizeof(int) * state->k);
+	int		   *current = palloc0_array(int, state->k);
 
 	generate_combinations_recurse(state, 0, 0, current);
 
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f373cead95f..15cab0609f4 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -4676,7 +4676,7 @@ DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
 	if (nlocators == 0)
 		return;
 
-	rels = palloc(sizeof(SMgrRelation) * nlocators);	/* non-local relations */
+	rels = palloc_array(SMgrRelation, nlocators);	/* non-local relations */
 
 	/* If it's a local relation, it's localbuf.c's problem. */
 	for (i = 0; i < nlocators; i++)
@@ -4705,7 +4705,7 @@ DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
 	 * forks.
 	 */
 	block = (BlockNumber (*)[MAX_FORKNUM + 1])
-		palloc(sizeof(BlockNumber) * n * (MAX_FORKNUM + 1));
+		palloc_array(BlockNumber, n * (MAX_FORKNUM + 1));
 
 	/*
 	 * We can avoid scanning the entire buffer pool if we know the exact size
@@ -4758,7 +4758,7 @@ DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
 	}
 
 	pfree(block);
-	locators = palloc(sizeof(RelFileLocator) * n);	/* non-local relations */
+	locators = palloc_array(RelFileLocator, n);	/* non-local relations */
 	for (i = 0; i < n; i++)
 		locators[i] = rels[i]->smgr_rlocator.locator;
 
@@ -5037,7 +5037,7 @@ FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels)
 		return;
 
 	/* fill-in array for qsort */
-	srels = palloc(sizeof(SMgrSortArray) * nrels);
+	srels = palloc_array(SMgrSortArray, nrels);
 
 	for (i = 0; i < nrels; i++)
 	{
diff --git a/src/test/modules/test_rbtree/test_rbtree.c b/src/test/modules/test_rbtree/test_rbtree.c
index 9113f1c8d52..787c3a60609 100644
--- a/src/test/modules/test_rbtree/test_rbtree.c
+++ b/src/test/modules/test_rbtree/test_rbtree.c
@@ -63,7 +63,7 @@ irbt_combine(RBTNode *existing, const RBTNode *newdata, void *arg)
 static RBTNode *
 irbt_alloc(void *arg)
 {
-	return (RBTNode *) palloc(sizeof(IntRBTreeNode));
+	return &palloc_object(IntRBTreeNode)->rbtnode;
 }
 
 /* Node freer */
-- 
2.51.0



  [text/x-patch] v2-0001-Consistently-use-palloc_object-and-palloc_array-iden.patch (609.7K, ../../4ab4a12b-49e9-4ebf-9055-225c8055fed0@gmail.com/3-v2-0001-Consistently-use-palloc_object-and-palloc_array-iden.patch)
  download | inline diff:
From cb8b4e9140f7653f5c5bd54b5411d47ef64ff30c Mon Sep 17 00:00:00 2001
From: David Geier <geidav.pg@gmail.com>
Date: Thu, 4 Dec 2025 09:50:22 +0100
Subject: [PATCH 1/2] Consistently use palloc_object() and palloc_array() -
 identical generated code

---
 contrib/amcheck/verify_gin.c                  | 12 +--
 contrib/amcheck/verify_heapam.c               |  2 +-
 contrib/amcheck/verify_nbtree.c               |  2 +-
 .../basebackup_to_shell/basebackup_to_shell.c |  2 +-
 contrib/bloom/blinsert.c                      |  2 +-
 contrib/bloom/blscan.c                        |  4 +-
 contrib/bloom/blutils.c                       |  2 +-
 contrib/bloom/blvacuum.c                      |  4 +-
 contrib/btree_gin/btree_gin.c                 | 20 ++--
 contrib/btree_gist/btree_bool.c               |  2 +-
 contrib/btree_gist/btree_cash.c               |  2 +-
 contrib/btree_gist/btree_date.c               |  2 +-
 contrib/btree_gist/btree_enum.c               |  2 +-
 contrib/btree_gist/btree_float4.c             |  2 +-
 contrib/btree_gist/btree_float8.c             |  2 +-
 contrib/btree_gist/btree_inet.c               |  6 +-
 contrib/btree_gist/btree_int2.c               |  2 +-
 contrib/btree_gist/btree_int4.c               |  2 +-
 contrib/btree_gist/btree_int8.c               |  2 +-
 contrib/btree_gist/btree_interval.c           |  8 +-
 contrib/btree_gist/btree_macaddr.c            |  2 +-
 contrib/btree_gist/btree_macaddr8.c           |  2 +-
 contrib/btree_gist/btree_oid.c                |  2 +-
 contrib/btree_gist/btree_time.c               |  6 +-
 contrib/btree_gist/btree_ts.c                 | 10 +-
 contrib/btree_gist/btree_utils_num.c          |  4 +-
 contrib/btree_gist/btree_utils_var.c          |  8 +-
 contrib/btree_gist/btree_uuid.c               |  4 +-
 contrib/cube/cube.c                           |  2 +-
 contrib/dict_int/dict_int.c                   |  4 +-
 contrib/dict_xsyn/dict_xsyn.c                 |  8 +-
 contrib/file_fdw/file_fdw.c                   |  4 +-
 contrib/hstore/hstore_gist.c                  |  6 +-
 contrib/hstore/hstore_io.c                    |  2 +-
 contrib/intarray/_int_bool.c                  |  8 +-
 contrib/intarray/_int_gin.c                   |  4 +-
 contrib/intarray/_int_gist.c                  | 12 +--
 contrib/intarray/_intbig_gist.c               |  6 +-
 contrib/jsonb_plperl/jsonb_plperl.c           |  2 +-
 contrib/jsonb_plpython/jsonb_plpython.c       |  2 +-
 contrib/ltree/_ltree_gist.c                   |  6 +-
 contrib/ltree/_ltree_op.c                     |  2 +-
 contrib/ltree/ltree_gist.c                    |  6 +-
 contrib/ltree/ltree_io.c                      |  6 +-
 contrib/ltree/ltree_op.c                      |  2 +-
 contrib/ltree/ltxtquery_io.c                  |  8 +-
 contrib/pageinspect/brinfuncs.c               |  2 +-
 contrib/pageinspect/btreefuncs.c              |  6 +-
 contrib/pageinspect/ginfuncs.c                |  2 +-
 contrib/pageinspect/hashfuncs.c               |  2 +-
 contrib/pageinspect/heapfuncs.c               |  4 +-
 contrib/pg_overexplain/pg_overexplain.c       |  2 +-
 contrib/pg_trgm/trgm_gin.c                    |  8 +-
 contrib/pg_trgm/trgm_gist.c                   | 10 +-
 contrib/pg_trgm/trgm_regexp.c                 | 22 ++---
 contrib/pg_visibility/pg_visibility.c         |  2 +-
 contrib/pg_walinspect/pg_walinspect.c         |  5 +-
 contrib/pgcrypto/mbuf.c                       |  8 +-
 contrib/pgcrypto/openssl.c                    |  4 +-
 contrib/pgcrypto/pgp-cfb.c                    |  2 +-
 contrib/pgcrypto/pgp-compress.c               |  4 +-
 contrib/pgcrypto/pgp-decrypt.c                |  4 +-
 contrib/pgcrypto/pgp-encrypt.c                |  4 +-
 contrib/pgcrypto/pgp-pgsql.c                  |  6 +-
 contrib/pgcrypto/pgp-pubkey.c                 |  2 +-
 contrib/pgcrypto/px-hmac.c                    |  2 +-
 contrib/pgcrypto/px.c                         |  2 +-
 contrib/seg/seg.c                             | 10 +-
 contrib/sepgsql/label.c                       |  4 +-
 contrib/sepgsql/uavc.c                        |  2 +-
 contrib/spi/refint.c                          |  2 +-
 contrib/sslinfo/sslinfo.c                     |  2 +-
 contrib/tablefunc/tablefunc.c                 |  4 +-
 contrib/test_decoding/test_decoding.c         |  2 +-
 contrib/tsm_system_rows/tsm_system_rows.c     |  2 +-
 contrib/tsm_system_time/tsm_system_time.c     |  2 +-
 contrib/unaccent/unaccent.c                   |  8 +-
 contrib/xml2/xpath.c                          |  3 +-
 contrib/xml2/xslt_proc.c                      |  2 +-
 doc/src/sgml/gist.sgml                        |  8 +-
 doc/src/sgml/xfunc.sgml                       |  2 +-
 doc/src/sgml/xtypes.sgml                      |  2 +-
 src/backend/access/brin/brin.c                |  8 +-
 src/backend/access/brin/brin_minmax_multi.c   |  4 +-
 src/backend/access/brin/brin_revmap.c         |  2 +-
 src/backend/access/brin/brin_tuple.c          | 14 +--
 src/backend/access/common/attmap.c            |  4 +-
 src/backend/access/common/heaptuple.c         |  8 +-
 src/backend/access/common/printtup.c          |  2 +-
 src/backend/access/common/reloptions.c        |  6 +-
 src/backend/access/common/tidstore.c          |  8 +-
 src/backend/access/common/toast_internals.c   |  2 +-
 src/backend/access/common/tupconvert.c        | 20 ++--
 src/backend/access/common/tupdesc.c           |  2 +-
 src/backend/access/gin/ginbtree.c             |  6 +-
 src/backend/access/gin/ginbulk.c              |  5 +-
 src/backend/access/gin/gindatapage.c          | 14 +--
 src/backend/access/gin/ginentrypage.c         |  4 +-
 src/backend/access/gin/ginget.c               |  4 +-
 src/backend/access/gin/gininsert.c            | 16 ++--
 src/backend/access/gin/ginscan.c              | 13 +--
 src/backend/access/gin/ginutil.c              | 10 +-
 src/backend/access/gin/ginvacuum.c            |  8 +-
 src/backend/access/gist/gist.c                | 22 ++---
 src/backend/access/gist/gistbuild.c           | 10 +-
 src/backend/access/gist/gistbuildbuffers.c    | 14 +--
 src/backend/access/gist/gistproc.c            | 26 ++---
 src/backend/access/gist/gistscan.c            |  6 +-
 src/backend/access/gist/gistsplit.c           |  8 +-
 src/backend/access/gist/gistutil.c            |  4 +-
 src/backend/access/gist/gistvacuum.c          |  4 +-
 src/backend/access/hash/hash.c                |  9 +-
 src/backend/access/hash/hashsort.c            |  2 +-
 src/backend/access/heap/heapam.c              | 14 +--
 src/backend/access/heap/heapam_handler.c      |  6 +-
 src/backend/access/heap/rewriteheap.c         |  2 +-
 src/backend/access/heap/vacuumlazy.c          |  6 +-
 src/backend/access/index/amvalidate.c         |  2 +-
 src/backend/access/index/genam.c              | 14 +--
 src/backend/access/nbtree/nbtdedup.c          |  8 +-
 src/backend/access/nbtree/nbtinsert.c         |  2 +-
 src/backend/access/nbtree/nbtpage.c           |  2 +-
 src/backend/access/nbtree/nbtree.c            |  9 +-
 src/backend/access/nbtree/nbtsearch.c         |  2 +-
 src/backend/access/nbtree/nbtsort.c           | 32 +++----
 src/backend/access/nbtree/nbtsplitloc.c       |  2 +-
 src/backend/access/nbtree/nbtxlog.c           |  2 +-
 src/backend/access/spgist/spgdoinsert.c       | 33 ++++---
 src/backend/access/spgist/spginsert.c         |  2 +-
 src/backend/access/spgist/spgkdtreeproc.c     | 14 +--
 src/backend/access/spgist/spgproc.c           |  4 +-
 src/backend/access/spgist/spgquadtreeproc.c   | 22 ++---
 src/backend/access/spgist/spgscan.c           | 29 +++---
 src/backend/access/spgist/spgtextproc.c       | 19 ++--
 src/backend/access/spgist/spgutils.c          |  2 +-
 src/backend/access/spgist/spgvacuum.c         |  6 +-
 src/backend/access/spgist/spgxlog.c           |  2 +-
 src/backend/access/tablesample/bernoulli.c    |  2 +-
 src/backend/access/tablesample/system.c       |  2 +-
 src/backend/access/transam/multixact.c        |  3 +-
 src/backend/access/transam/parallel.c         |  7 +-
 src/backend/access/transam/timeline.c         |  8 +-
 src/backend/access/transam/twophase.c         | 10 +-
 src/backend/access/transam/xact.c             |  2 +-
 src/backend/access/transam/xlog.c             |  4 +-
 src/backend/access/transam/xlogfuncs.c        |  2 +-
 src/backend/access/transam/xlogprefetcher.c   |  2 +-
 src/backend/access/transam/xlogrecovery.c     |  6 +-
 src/backend/access/transam/xlogutils.c        |  2 +-
 src/backend/backup/basebackup.c               |  6 +-
 src/backend/backup/basebackup_copy.c          |  2 +-
 src/backend/backup/basebackup_gzip.c          |  2 +-
 src/backend/backup/basebackup_incremental.c   |  6 +-
 src/backend/backup/basebackup_lz4.c           |  2 +-
 src/backend/backup/basebackup_progress.c      |  2 +-
 src/backend/backup/basebackup_server.c        |  2 +-
 src/backend/backup/basebackup_target.c        |  4 +-
 src/backend/backup/basebackup_throttle.c      |  2 +-
 src/backend/backup/basebackup_zstd.c          |  2 +-
 src/backend/backup/walsummary.c               |  2 +-
 src/backend/bootstrap/bootstrap.c             |  6 +-
 src/backend/catalog/dependency.c              |  8 +-
 src/backend/catalog/heap.c                    |  8 +-
 src/backend/catalog/index.c                   |  8 +-
 src/backend/catalog/namespace.c               |  4 +-
 src/backend/catalog/objectaddress.c           |  4 +-
 src/backend/catalog/pg_constraint.c           |  2 +-
 src/backend/catalog/pg_depend.c               |  2 +-
 src/backend/catalog/pg_enum.c                 |  6 +-
 src/backend/catalog/pg_publication.c          |  6 +-
 src/backend/catalog/pg_shdepend.c             |  4 +-
 src/backend/catalog/pg_subscription.c         |  4 +-
 src/backend/catalog/storage.c                 | 10 +-
 src/backend/commands/analyze.c                |  6 +-
 src/backend/commands/cluster.c                |  4 +-
 src/backend/commands/copy.c                   |  2 +-
 src/backend/commands/copyfrom.c               |  4 +-
 src/backend/commands/copyto.c                 |  4 +-
 src/backend/commands/createas.c               |  2 +-
 src/backend/commands/dbcommands.c             |  2 +-
 src/backend/commands/event_trigger.c          | 24 ++---
 src/backend/commands/explain.c                |  2 +-
 src/backend/commands/explain_dr.c             |  2 +-
 src/backend/commands/explain_state.c          |  7 +-
 src/backend/commands/extension.c              |  4 +-
 src/backend/commands/functioncmds.c           |  2 +-
 src/backend/commands/matview.c                |  4 +-
 src/backend/commands/opclasscmds.c            | 12 +--
 src/backend/commands/policy.c                 |  6 +-
 src/backend/commands/publicationcmds.c        |  6 +-
 src/backend/commands/seclabel.c               |  2 +-
 src/backend/commands/subscriptioncmds.c       |  4 +-
 src/backend/commands/tablecmds.c              | 36 +++----
 src/backend/commands/trigger.c                |  8 +-
 src/backend/commands/tsearchcmds.c            |  8 +-
 src/backend/commands/typecmds.c               |  4 +-
 src/backend/commands/user.c                   |  4 +-
 src/backend/commands/vacuumparallel.c         |  6 +-
 src/backend/executor/execExpr.c               | 94 +++++++++----------
 src/backend/executor/execGrouping.c           |  2 +-
 src/backend/executor/execIndexing.c           |  4 +-
 src/backend/executor/execMain.c               | 18 ++--
 src/backend/executor/execParallel.c           |  2 +-
 src/backend/executor/execReplication.c        |  8 +-
 src/backend/executor/execTuples.c             |  4 +-
 src/backend/executor/functions.c              |  4 +-
 src/backend/executor/nodeAgg.c                | 42 ++++-----
 src/backend/executor/nodeAppend.c             |  2 +-
 src/backend/executor/nodeFunctionscan.c       |  2 +-
 src/backend/executor/nodeGatherMerge.c        |  6 +-
 src/backend/executor/nodeHashjoin.c           |  5 +-
 src/backend/executor/nodeIndexonlyscan.c      |  3 +-
 src/backend/executor/nodeIndexscan.c          |  8 +-
 src/backend/executor/nodeMemoize.c            |  4 +-
 src/backend/executor/nodeMergeAppend.c        |  6 +-
 src/backend/executor/nodeModifyTable.c        | 13 +--
 src/backend/executor/nodeProjectSet.c         |  6 +-
 src/backend/executor/nodeSamplescan.c         |  2 +-
 src/backend/executor/nodeTableFuncscan.c      |  4 +-
 src/backend/executor/nodeTidrangescan.c       |  2 +-
 src/backend/executor/nodeTidscan.c            |  2 +-
 src/backend/executor/nodeWindowAgg.c          | 12 +--
 src/backend/executor/spi.c                    | 21 ++---
 src/backend/executor/tqueue.c                 |  4 +-
 src/backend/executor/tstoreReceiver.c         |  2 +-
 src/backend/foreign/foreign.c                 | 10 +-
 src/backend/jit/llvm/llvmjit.c                |  6 +-
 src/backend/jit/llvm/llvmjit_deform.c         | 12 +--
 src/backend/jit/llvm/llvmjit_expr.c           | 10 +-
 src/backend/lib/bipartite_match.c             |  2 +-
 src/backend/lib/dshash.c                      |  4 +-
 src/backend/lib/integerset.c                  |  2 +-
 src/backend/lib/pairingheap.c                 |  2 +-
 src/backend/lib/rbtree.c                      |  2 +-
 src/backend/libpq/auth-oauth.c                |  8 +-
 src/backend/libpq/auth-scram.c                |  2 +-
 src/backend/libpq/hba.c                       | 10 +-
 src/backend/libpq/pqcomm.c                    |  2 +-
 src/backend/nodes/nodeFuncs.c                 |  2 +-
 src/backend/nodes/queryjumblefuncs.c          |  2 +-
 src/backend/nodes/tidbitmap.c                 |  4 +-
 src/backend/optimizer/geqo/geqo_erx.c         |  2 +-
 src/backend/optimizer/geqo/geqo_eval.c        |  2 +-
 src/backend/optimizer/geqo/geqo_pmx.c         |  8 +-
 src/backend/optimizer/geqo/geqo_pool.c        | 10 +-
 .../optimizer/geqo/geqo_recombination.c       |  2 +-
 src/backend/optimizer/path/clausesel.c        |  2 +-
 src/backend/optimizer/path/costsize.c         |  4 +-
 src/backend/optimizer/path/indxpath.c         |  7 +-
 src/backend/optimizer/path/joinrels.c         |  3 +-
 src/backend/optimizer/plan/analyzejoins.c     |  3 +-
 src/backend/optimizer/plan/createplan.c       | 34 +++----
 src/backend/optimizer/plan/initsplan.c        |  6 +-
 src/backend/optimizer/plan/planagg.c          |  2 +-
 src/backend/optimizer/plan/planner.c          |  5 +-
 src/backend/optimizer/plan/setrefs.c          |  6 +-
 src/backend/optimizer/prep/prepjointree.c     |  7 +-
 src/backend/optimizer/prep/prepunion.c        |  2 +-
 src/backend/optimizer/util/appendinfo.c       |  3 +-
 src/backend/optimizer/util/clauses.c          |  6 +-
 src/backend/optimizer/util/extendplan.c       | 15 +--
 src/backend/optimizer/util/plancat.c          | 45 +++++----
 src/backend/optimizer/util/predtest.c         |  4 +-
 src/backend/optimizer/util/relnode.c          | 14 +--
 src/backend/optimizer/util/tlist.c            | 12 +--
 src/backend/parser/analyze.c                  |  5 +-
 src/backend/parser/gram.y                     | 92 +++++++++---------
 src/backend/parser/parse_clause.c             |  4 +-
 src/backend/parser/parse_expr.c               |  4 +-
 src/backend/parser/parse_node.c               |  2 +-
 src/backend/parser/parse_param.c              |  4 +-
 src/backend/parser/parse_relation.c           | 10 +-
 src/backend/parser/parse_type.c               |  2 +-
 src/backend/partitioning/partbounds.c         | 53 +++++------
 src/backend/partitioning/partdesc.c           |  2 +-
 src/backend/postmaster/autovacuum.c           |  6 +-
 src/backend/postmaster/bgworker.c             |  2 +-
 src/backend/postmaster/checkpointer.c         |  2 +-
 src/backend/postmaster/launch_backend.c       |  2 +-
 src/backend/postmaster/pgarch.c               |  4 +-
 src/backend/postmaster/postmaster.c           |  2 +-
 src/backend/postmaster/syslogger.c            |  2 +-
 src/backend/postmaster/walsummarizer.c        |  3 +-
 .../libpqwalreceiver/libpqwalreceiver.c       |  4 +-
 .../replication/logical/applyparallelworker.c |  2 +-
 src/backend/replication/logical/launcher.c    |  2 +-
 src/backend/replication/logical/logical.c     |  2 +-
 .../replication/logical/logicalfuncs.c        |  2 +-
 src/backend/replication/logical/proto.c       |  8 +-
 src/backend/replication/logical/relation.c    |  8 +-
 .../replication/logical/reorderbuffer.c       | 17 ++--
 src/backend/replication/logical/slotsync.c    |  2 +-
 src/backend/replication/logical/snapbuild.c   |  5 +-
 src/backend/replication/logical/syncutils.c   |  2 +-
 src/backend/replication/logical/worker.c      |  6 +-
 src/backend/replication/pgoutput/pgoutput.c   |  4 +-
 src/backend/replication/syncrep.c             |  9 +-
 src/backend/replication/walreceiver.c         |  4 +-
 src/backend/replication/walsender.c           |  2 +-
 src/backend/rewrite/rewriteHandler.c          |  2 +-
 src/backend/rewrite/rewriteManip.c            |  6 +-
 src/backend/snowball/dict_snowball.c          |  4 +-
 src/backend/statistics/dependencies.c         | 26 +++--
 src/backend/statistics/extended_stats.c       | 15 ++-
 src/backend/statistics/mcv.c                  | 24 ++---
 src/backend/storage/file/buffile.c            | 10 +-
 src/backend/storage/ipc/procarray.c           |  8 +-
 src/backend/storage/ipc/shm_mq.c              |  2 +-
 src/backend/storage/ipc/shmem.c               |  6 +-
 src/backend/storage/lmgr/lock.c               | 16 ++--
 src/backend/storage/lmgr/predicate.c          |  8 +-
 src/backend/storage/smgr/bulk_write.c         |  2 +-
 src/backend/storage/smgr/md.c                 |  2 +-
 src/backend/storage/smgr/smgr.c               |  2 +-
 src/backend/storage/sync/sync.c               |  2 +-
 src/backend/tcop/pquery.c                     |  2 +-
 src/backend/tsearch/dict.c                    |  2 +-
 src/backend/tsearch/dict_ispell.c             |  2 +-
 src/backend/tsearch/dict_simple.c             |  6 +-
 src/backend/tsearch/dict_synonym.c            |  8 +-
 src/backend/tsearch/dict_thesaurus.c          | 26 ++---
 src/backend/tsearch/spell.c                   | 22 ++---
 src/backend/tsearch/to_tsany.c                | 14 +--
 src/backend/tsearch/ts_parse.c                |  2 +-
 src/backend/tsearch/ts_selfuncs.c             |  2 +-
 src/backend/tsearch/ts_typanalyze.c           |  6 +-
 src/backend/tsearch/ts_utils.c                |  4 +-
 src/backend/tsearch/wparser.c                 | 16 ++--
 src/backend/tsearch/wparser_def.c             | 12 +--
 src/backend/utils/activity/pgstat_relation.c  |  2 +-
 src/backend/utils/activity/wait_event.c       |  2 +-
 src/backend/utils/adt/acl.c                   |  6 +-
 src/backend/utils/adt/array_selfuncs.c        |  8 +-
 src/backend/utils/adt/array_typanalyze.c      |  7 +-
 src/backend/utils/adt/array_userfuncs.c       | 12 +--
 src/backend/utils/adt/arrayfuncs.c            | 12 +--
 src/backend/utils/adt/arraysubs.c             |  2 +-
 src/backend/utils/adt/date.c                  | 24 ++---
 src/backend/utils/adt/datetime.c              | 10 +-
 src/backend/utils/adt/formatting.c            |  2 +-
 src/backend/utils/adt/geo_ops.c               | 94 +++++++++----------
 src/backend/utils/adt/geo_spgist.c            | 40 ++++----
 src/backend/utils/adt/int.c                   |  2 +-
 src/backend/utils/adt/int8.c                  |  2 +-
 src/backend/utils/adt/json.c                  |  6 +-
 src/backend/utils/adt/jsonb.c                 | 12 +--
 src/backend/utils/adt/jsonb_gin.c             | 19 ++--
 src/backend/utils/adt/jsonb_util.c            | 20 ++--
 src/backend/utils/adt/jsonfuncs.c             | 64 ++++++-------
 src/backend/utils/adt/jsonpath_exec.c         | 27 +++---
 src/backend/utils/adt/jsonpath_gram.y         |  4 +-
 src/backend/utils/adt/lockfuncs.c             |  2 +-
 src/backend/utils/adt/mac.c                   | 14 +--
 src/backend/utils/adt/mac8.c                  | 18 ++--
 src/backend/utils/adt/mcxtfuncs.c             |  2 +-
 src/backend/utils/adt/misc.c                  |  2 +-
 src/backend/utils/adt/multirangetypes.c       |  8 +-
 .../utils/adt/multirangetypes_selfuncs.c      |  4 +-
 src/backend/utils/adt/multixactfuncs.c        |  2 +-
 src/backend/utils/adt/network.c               | 24 ++---
 src/backend/utils/adt/network_gist.c          | 10 +-
 src/backend/utils/adt/network_spgist.c        |  6 +-
 src/backend/utils/adt/numeric.c               | 13 ++-
 src/backend/utils/adt/orderedsetaggs.c        |  4 +-
 src/backend/utils/adt/pg_locale_libc.c        |  6 +-
 src/backend/utils/adt/pg_ndistinct.c          |  2 +-
 src/backend/utils/adt/rangetypes.c            |  2 +-
 src/backend/utils/adt/rangetypes_gist.c       | 15 ++-
 src/backend/utils/adt/rangetypes_selfuncs.c   |  4 +-
 src/backend/utils/adt/rangetypes_spgist.c     | 18 ++--
 src/backend/utils/adt/rangetypes_typanalyze.c |  8 +-
 src/backend/utils/adt/regexp.c                | 20 ++--
 src/backend/utils/adt/rowtypes.c              | 24 ++---
 src/backend/utils/adt/ruleutils.c             |  8 +-
 src/backend/utils/adt/selfuncs.c              |  4 +-
 src/backend/utils/adt/skipsupport.c           |  2 +-
 src/backend/utils/adt/tid.c                   |  6 +-
 src/backend/utils/adt/timestamp.c             | 46 +++++----
 src/backend/utils/adt/tsginidx.c              | 10 +-
 src/backend/utils/adt/tsgistidx.c             | 10 +-
 src/backend/utils/adt/tsquery.c               | 12 +--
 src/backend/utils/adt/tsquery_cleanup.c       |  2 +-
 src/backend/utils/adt/tsquery_gist.c          |  4 +-
 src/backend/utils/adt/tsquery_op.c            | 14 +--
 src/backend/utils/adt/tsquery_util.c          | 18 ++--
 src/backend/utils/adt/tsrank.c                | 13 ++-
 src/backend/utils/adt/tsvector.c              |  4 +-
 src/backend/utils/adt/tsvector_op.c           | 10 +-
 src/backend/utils/adt/tsvector_parser.c       |  6 +-
 src/backend/utils/adt/uuid.c                  |  4 +-
 src/backend/utils/adt/varlena.c               |  2 +-
 src/backend/utils/adt/xml.c                   |  6 +-
 src/backend/utils/cache/catcache.c            |  4 +-
 src/backend/utils/cache/evtcache.c            |  2 +-
 src/backend/utils/cache/inval.c               |  2 +-
 src/backend/utils/cache/lsyscache.c           |  6 +-
 src/backend/utils/cache/partcache.c           | 24 ++---
 src/backend/utils/cache/plancache.c           | 15 ++-
 src/backend/utils/cache/relcache.c            | 30 +++---
 src/backend/utils/cache/typcache.c            |  2 +-
 src/backend/utils/error/elog.c                |  2 +-
 src/backend/utils/fmgr/funcapi.c              |  2 +-
 src/backend/utils/init/postinit.c             |  2 +-
 src/backend/utils/mb/mbutils.c                |  4 +-
 src/backend/utils/misc/conffiles.c            |  2 +-
 src/backend/utils/misc/guc-file.l             |  4 +-
 src/backend/utils/misc/guc.c                  |  4 +-
 src/backend/utils/misc/injection_point.c      |  2 +-
 src/backend/utils/misc/queryenvironment.c     |  2 +-
 src/backend/utils/misc/tzparser.c             |  2 +-
 src/backend/utils/mmgr/dsa.c                  |  4 +-
 src/backend/utils/sort/logtape.c              |  6 +-
 src/backend/utils/sort/sharedtuplestore.c     |  4 +-
 src/backend/utils/sort/tuplesort.c            |  2 +-
 src/backend/utils/sort/tuplesortvariants.c    | 12 +--
 src/backend/utils/sort/tuplestore.c           |  2 +-
 src/backend/utils/time/snapmgr.c              |  2 +-
 src/bin/pg_basebackup/astreamer_inject.c      |  2 +-
 src/bin/pg_combinebackup/load_manifest.c      |  2 +-
 src/bin/pg_dump/common.c                      |  2 +-
 src/bin/pg_dump/dumputils.c                   |  2 +-
 src/bin/pg_verifybackup/astreamer_verify.c    |  2 +-
 src/bin/pg_verifybackup/pg_verifybackup.c     |  2 +-
 src/bin/scripts/vacuuming.c                   |  2 +-
 src/common/blkreftable.c                      | 21 ++---
 src/common/parse_manifest.c                   |  4 +-
 src/common/pgfnames.c                         |  5 +-
 src/common/rmtree.c                           |  2 +-
 src/common/stringinfo.c                       |  2 +-
 src/fe_utils/astreamer_file.c                 |  4 +-
 src/fe_utils/astreamer_gzip.c                 |  4 +-
 src/fe_utils/astreamer_lz4.c                  |  4 +-
 src/fe_utils/astreamer_tar.c                  |  6 +-
 src/fe_utils/astreamer_zstd.c                 |  4 +-
 src/include/lib/radixtree.h                   |  8 +-
 src/pl/plperl/plperl.c                        | 12 +--
 src/pl/plpgsql/src/pl_comp.c                  | 32 +++----
 src/pl/plpgsql/src/pl_exec.c                  |  9 +-
 src/pl/plpgsql/src/pl_gram.y                  | 92 +++++++++---------
 src/pl/plpython/plpy_procedure.c              |  6 +-
 src/pl/plpython/plpy_spi.c                    |  4 +-
 src/pl/plpython/plpy_typeio.c                 | 12 +--
 src/pl/tcl/pltcl.c                            |  4 +-
 .../modules/dummy_index_am/dummy_index_am.c   |  2 +-
 .../modules/spgist_name_ops/spgist_name_ops.c | 10 +-
 .../modules/test_bitmapset/test_bitmapset.c   |  2 +-
 .../modules/test_integerset/test_integerset.c |  2 +-
 .../test_json_parser_incremental.c            |  2 +-
 src/test/modules/test_parser/test_parser.c    |  4 +-
 .../modules/test_radixtree/test_radixtree.c   |  2 +-
 src/test/modules/test_regex/test_regex.c      | 14 ++-
 .../test_resowner/test_resowner_many.c        |  2 +-
 .../modules/test_rls_hooks/test_rls_hooks.c   |  4 +-
 src/test/modules/worker_spi/worker_spi.c      |  2 +-
 src/test/regress/regress.c                    |  2 +-
 src/timezone/pgtz.c                           |  2 +-
 src/tutorial/complex.c                        |  6 +-
 src/tutorial/funcs.c                          |  2 +-
 458 files changed, 1699 insertions(+), 1810 deletions(-)

diff --git a/contrib/amcheck/verify_gin.c b/contrib/amcheck/verify_gin.c
index 5c3eb4d0fd4..696a1176a63 100644
--- a/contrib/amcheck/verify_gin.c
+++ b/contrib/amcheck/verify_gin.c
@@ -117,7 +117,7 @@ ginReadTupleWithoutState(IndexTuple itup, int *nitems)
 	}
 	else
 	{
-		ipd = (ItemPointer) palloc(sizeof(ItemPointerData) * nipd);
+		ipd = palloc_array(ItemPointerData, nipd);
 		memcpy(ipd, ptr, sizeof(ItemPointerData) * nipd);
 	}
 	*nitems = nipd;
@@ -152,7 +152,7 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
 	leafdepth = -1;
 
 	/* Start the scan at the root page */
-	stack = (GinPostingTreeScanItem *) palloc0(sizeof(GinPostingTreeScanItem));
+	stack = palloc0_object(GinPostingTreeScanItem);
 	stack->depth = 0;
 	ItemPointerSetInvalid(&stack->parentkey);
 	stack->parentblk = InvalidBlockNumber;
@@ -354,7 +354,7 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
 									stack->blkno, i)));
 
 				/* This is an internal page, recurse into the child. */
-				ptr = (GinPostingTreeScanItem *) palloc(sizeof(GinPostingTreeScanItem));
+				ptr = palloc_object(GinPostingTreeScanItem);
 				ptr->depth = stack->depth + 1;
 
 				/*
@@ -412,7 +412,7 @@ gin_check_parent_keys_consistency(Relation rel,
 	leafdepth = -1;
 
 	/* Start the scan at the root page */
-	stack = (GinScanItem *) palloc0(sizeof(GinScanItem));
+	stack = palloc0_object(GinScanItem);
 	stack->depth = 0;
 	stack->parenttup = NULL;
 	stack->parentblk = InvalidBlockNumber;
@@ -473,7 +473,7 @@ gin_check_parent_keys_consistency(Relation rel,
 
 				elog(DEBUG3, "split detected for blk: %u, parent blk: %u", stack->blkno, stack->parentblk);
 
-				ptr = (GinScanItem *) palloc(sizeof(GinScanItem));
+				ptr = palloc_object(GinScanItem);
 				ptr->depth = stack->depth;
 				ptr->parenttup = CopyIndexTuple(stack->parenttup);
 				ptr->parentblk = stack->parentblk;
@@ -601,7 +601,7 @@ gin_check_parent_keys_consistency(Relation rel,
 			{
 				GinScanItem *ptr;
 
-				ptr = (GinScanItem *) palloc(sizeof(GinScanItem));
+				ptr = palloc_object(GinScanItem);
 				ptr->depth = stack->depth + 1;
 				/* last tuple in layer has no high key */
 				if (i == maxoff && rightlink == InvalidBlockNumber)
diff --git a/contrib/amcheck/verify_heapam.c b/contrib/amcheck/verify_heapam.c
index 4963e9245cb..a090e18c697 100644
--- a/contrib/amcheck/verify_heapam.c
+++ b/contrib/amcheck/verify_heapam.c
@@ -1838,7 +1838,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
 	{
 		ToastedAttribute *ta;
 
-		ta = (ToastedAttribute *) palloc0(sizeof(ToastedAttribute));
+		ta = palloc0_object(ToastedAttribute);
 
 		VARATT_EXTERNAL_GET_POINTER(ta->toast_pointer, attr);
 		ta->blkno = ctx->blkno;
diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c
index 75751e2a1e9..a787c29979b 100644
--- a/contrib/amcheck/verify_nbtree.c
+++ b/contrib/amcheck/verify_nbtree.c
@@ -400,7 +400,7 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace,
 	/*
 	 * Initialize state for entire verification operation
 	 */
-	state = palloc0(sizeof(BtreeCheckState));
+	state = palloc0_object(BtreeCheckState);
 	state->rel = rel;
 	state->heaprel = heaprel;
 	state->heapkeyspace = heapkeyspace;
diff --git a/contrib/basebackup_to_shell/basebackup_to_shell.c b/contrib/basebackup_to_shell/basebackup_to_shell.c
index 8720f5a4372..345d3ed895d 100644
--- a/contrib/basebackup_to_shell/basebackup_to_shell.c
+++ b/contrib/basebackup_to_shell/basebackup_to_shell.c
@@ -136,7 +136,7 @@ shell_get_sink(bbsink *next_sink, void *detail_arg)
 	 * We remember the current value of basebackup_to_shell.shell_command to
 	 * be certain that it can't change under us during the backup.
 	 */
-	sink = palloc0(sizeof(bbsink_shell));
+	sink = palloc0_object(bbsink_shell);
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_shell_ops;
 	sink->base.bbs_next = next_sink;
 	sink->target_detail = detail_arg;
diff --git a/contrib/bloom/blinsert.c b/contrib/bloom/blinsert.c
index 7866438122f..c11e06c34ee 100644
--- a/contrib/bloom/blinsert.c
+++ b/contrib/bloom/blinsert.c
@@ -151,7 +151,7 @@ blbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 
 	MemoryContextDelete(buildstate.tmpCtx);
 
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 	result->heap_tuples = reltuples;
 	result->index_tuples = buildstate.indtuples;
 
diff --git a/contrib/bloom/blscan.c b/contrib/bloom/blscan.c
index d072f47fe28..0d71edbe91c 100644
--- a/contrib/bloom/blscan.c
+++ b/contrib/bloom/blscan.c
@@ -29,7 +29,7 @@ blbeginscan(Relation r, int nkeys, int norderbys)
 
 	scan = RelationGetIndexScan(r, nkeys, norderbys);
 
-	so = (BloomScanOpaque) palloc(sizeof(BloomScanOpaqueData));
+	so = (BloomScanOpaque) palloc_object(BloomScanOpaqueData);
 	initBloomState(&so->state, scan->indexRelation);
 	so->sign = NULL;
 
@@ -86,7 +86,7 @@ blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 		/* New search: have to calculate search signature */
 		ScanKey		skey = scan->keyData;
 
-		so->sign = palloc0(sizeof(BloomSignatureWord) * so->state.opts.bloomLength);
+		so->sign = palloc0_array(BloomSignatureWord, so->state.opts.bloomLength);
 
 		for (i = 0; i < scan->numberOfKeys; i++)
 		{
diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c
index 2c0e71eedc6..ba1465c257f 100644
--- a/contrib/bloom/blutils.c
+++ b/contrib/bloom/blutils.c
@@ -86,7 +86,7 @@ makeDefaultBloomOptions(void)
 	BloomOptions *opts;
 	int			i;
 
-	opts = (BloomOptions *) palloc0(sizeof(BloomOptions));
+	opts = palloc0_object(BloomOptions);
 	/* Convert DEFAULT_BLOOM_LENGTH from # of bits to # of words */
 	opts->bloomLength = (DEFAULT_BLOOM_LENGTH + SIGNWORDBITS - 1) / SIGNWORDBITS;
 	for (i = 0; i < INDEX_MAX_KEYS; i++)
diff --git a/contrib/bloom/blvacuum.c b/contrib/bloom/blvacuum.c
index 9e5f0574fad..e90a4bfb178 100644
--- a/contrib/bloom/blvacuum.c
+++ b/contrib/bloom/blvacuum.c
@@ -42,7 +42,7 @@ blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 	GenericXLogState *gxlogState;
 
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 
 	initBloomState(&state, index);
 
@@ -172,7 +172,7 @@ blvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 		return stats;
 
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 
 	/*
 	 * Iterate over the pages: insert deleted pages into FSM and collect
diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c
index 966b76e591b..afb8b3820af 100644
--- a/contrib/btree_gin/btree_gin.c
+++ b/contrib/btree_gin/btree_gin.c
@@ -52,7 +52,7 @@ gin_btree_extract_value(FunctionCallInfo fcinfo, bool is_varlena)
 {
 	Datum		datum = PG_GETARG_DATUM(0);
 	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
-	Datum	   *entries = (Datum *) palloc(sizeof(Datum));
+	Datum	   *entries = palloc_object(Datum);
 
 	/* Ensure that values stored in the index are not toasted */
 	if (is_varlena)
@@ -75,9 +75,9 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
 	StrategyNumber strategy = PG_GETARG_UINT16(2);
 	bool	  **partialmatch = (bool **) PG_GETARG_POINTER(3);
 	Pointer   **extra_data = (Pointer **) PG_GETARG_POINTER(4);
-	Datum	   *entries = (Datum *) palloc(sizeof(Datum));
-	QueryInfo  *data = (QueryInfo *) palloc(sizeof(QueryInfo));
-	bool	   *ptr_partialmatch = (bool *) palloc(sizeof(bool));
+	Datum	   *entries = palloc_object(Datum);
+	QueryInfo  *data = palloc_object(QueryInfo);
+	bool	   *ptr_partialmatch = palloc_object(bool);
 	int			btree_strat,
 				rhs_code;
 
@@ -140,7 +140,7 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
 	data->orig_datum = datum;
 	data->entry_datum = entries[0];
 	data->typecmp = cmp_fns[rhs_code];
-	*extra_data = (Pointer *) palloc(sizeof(Pointer));
+	*extra_data = palloc_object(Pointer);
 	**extra_data = (Pointer) data;
 
 	PG_RETURN_POINTER(entries);
@@ -579,7 +579,7 @@ GIN_SUPPORT(time, leftmostvalue_time, time_rhs_is_varlena, NULL, time_cmp_fns)
 static Datum
 leftmostvalue_timetz(void)
 {
-	TimeTzADT  *v = palloc(sizeof(TimeTzADT));
+	TimeTzADT  *v = palloc_object(TimeTzADT);
 
 	v->time = 0;
 	v->zone = -24 * 3600;		/* XXX is that true? */
@@ -639,7 +639,7 @@ GIN_SUPPORT(date, leftmostvalue_date, date_rhs_is_varlena, date_cvt_fns, date_cm
 static Datum
 leftmostvalue_interval(void)
 {
-	Interval   *v = palloc(sizeof(Interval));
+	Interval   *v = palloc_object(Interval);
 
 	INTERVAL_NOBEGIN(v);
 
@@ -657,7 +657,7 @@ GIN_SUPPORT(interval, leftmostvalue_interval, interval_rhs_is_varlena, NULL, int
 static Datum
 leftmostvalue_macaddr(void)
 {
-	macaddr    *v = palloc0(sizeof(macaddr));
+	macaddr    *v = palloc0_object(macaddr);
 
 	return MacaddrPGetDatum(v);
 }
@@ -673,7 +673,7 @@ GIN_SUPPORT(macaddr, leftmostvalue_macaddr, macaddr_rhs_is_varlena, NULL, macadd
 static Datum
 leftmostvalue_macaddr8(void)
 {
-	macaddr8   *v = palloc0(sizeof(macaddr8));
+	macaddr8   *v = palloc0_object(macaddr8);
 
 	return Macaddr8PGetDatum(v);
 }
@@ -910,7 +910,7 @@ leftmostvalue_uuid(void)
 	 * palloc0 will create the UUID with all zeroes:
 	 * "00000000-0000-0000-0000-000000000000"
 	 */
-	pg_uuid_t  *retval = (pg_uuid_t *) palloc0(sizeof(pg_uuid_t));
+	pg_uuid_t  *retval = palloc0_object(pg_uuid_t);
 
 	return UUIDPGetDatum(retval);
 }
diff --git a/contrib/btree_gist/btree_bool.c b/contrib/btree_gist/btree_bool.c
index 344f059c78f..59ad60da5be 100644
--- a/contrib/btree_gist/btree_bool.c
+++ b/contrib/btree_gist/btree_bool.c
@@ -128,7 +128,7 @@ Datum
 gbt_bool_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(boolKEY));
+	void	   *out = palloc_object(boolKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(boolKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_cash.c b/contrib/btree_gist/btree_cash.c
index 282d5c5731f..f84b35f5161 100644
--- a/contrib/btree_gist/btree_cash.c
+++ b/contrib/btree_gist/btree_cash.c
@@ -177,7 +177,7 @@ Datum
 gbt_cash_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(cashKEY));
+	void	   *out = palloc_object(cashKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(cashKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_date.c b/contrib/btree_gist/btree_date.c
index 1f1a3f32b56..8cbfbb19c5a 100644
--- a/contrib/btree_gist/btree_date.c
+++ b/contrib/btree_gist/btree_date.c
@@ -192,7 +192,7 @@ Datum
 gbt_date_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(dateKEY));
+	void	   *out = palloc_object(dateKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(dateKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_enum.c b/contrib/btree_gist/btree_enum.c
index 8f1ffff4696..600e8409e88 100644
--- a/contrib/btree_gist/btree_enum.c
+++ b/contrib/btree_gist/btree_enum.c
@@ -147,7 +147,7 @@ Datum
 gbt_enum_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(oidKEY));
+	void	   *out = palloc_object(oidKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_float4.c b/contrib/btree_gist/btree_float4.c
index d9c859835da..b98503b934f 100644
--- a/contrib/btree_gist/btree_float4.c
+++ b/contrib/btree_gist/btree_float4.c
@@ -171,7 +171,7 @@ Datum
 gbt_float4_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(float4KEY));
+	void	   *out = palloc_object(float4KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(float4KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_float8.c b/contrib/btree_gist/btree_float8.c
index 567beede178..c82f9f82b2d 100644
--- a/contrib/btree_gist/btree_float8.c
+++ b/contrib/btree_gist/btree_float8.c
@@ -179,7 +179,7 @@ Datum
 gbt_float8_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(float8KEY));
+	void	   *out = palloc_object(float8KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(float8KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_inet.c b/contrib/btree_gist/btree_inet.c
index 52bf3e2446e..fe8816ecb60 100644
--- a/contrib/btree_gist/btree_inet.c
+++ b/contrib/btree_gist/btree_inet.c
@@ -97,10 +97,10 @@ gbt_inet_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)
 	{
-		inetKEY    *r = (inetKEY *) palloc(sizeof(inetKEY));
+		inetKEY    *r = palloc_object(inetKEY);
 		bool		failure = false;
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		r->lower = convert_network_to_scalar(entry->key, INETOID, &failure);
 		Assert(!failure);
 		r->upper = r->lower;
@@ -145,7 +145,7 @@ Datum
 gbt_inet_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(inetKEY));
+	void	   *out = palloc_object(inetKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(inetKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_int2.c b/contrib/btree_gist/btree_int2.c
index faf456997bb..3e3b153fd09 100644
--- a/contrib/btree_gist/btree_int2.c
+++ b/contrib/btree_gist/btree_int2.c
@@ -176,7 +176,7 @@ Datum
 gbt_int2_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(int16KEY));
+	void	   *out = palloc_object(int16KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(int16KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_int4.c b/contrib/btree_gist/btree_int4.c
index 0bdb9e58c56..db4971439f1 100644
--- a/contrib/btree_gist/btree_int4.c
+++ b/contrib/btree_gist/btree_int4.c
@@ -174,7 +174,7 @@ Datum
 gbt_int4_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(int32KEY));
+	void	   *out = palloc_object(int32KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(int32KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_int8.c b/contrib/btree_gist/btree_int8.c
index a9a7b569278..5a51f2ddd01 100644
--- a/contrib/btree_gist/btree_int8.c
+++ b/contrib/btree_gist/btree_int8.c
@@ -176,7 +176,7 @@ Datum
 gbt_int8_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(int64KEY));
+	void	   *out = palloc_object(int64KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(int64KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c
index 19eefc60cde..774cad7befe 100644
--- a/contrib/btree_gist/btree_interval.c
+++ b/contrib/btree_gist/btree_interval.c
@@ -150,7 +150,7 @@ gbt_intv_compress(PG_FUNCTION_ARGS)
 	{
 		char	   *r = (char *) palloc(2 * INTERVALSIZE);
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 
 		if (entry->leafkey)
 		{
@@ -190,10 +190,10 @@ gbt_intv_decompress(PG_FUNCTION_ARGS)
 
 	if (INTERVALSIZE != sizeof(Interval))
 	{
-		intvKEY    *r = palloc(sizeof(intvKEY));
+		intvKEY    *r = palloc_object(intvKEY);
 		char	   *key = DatumGetPointer(entry->key);
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		memcpy(&r->lower, key, INTERVALSIZE);
 		memcpy(&r->upper, key + INTERVALSIZE, INTERVALSIZE);
 
@@ -250,7 +250,7 @@ Datum
 gbt_intv_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(intvKEY));
+	void	   *out = palloc_object(intvKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_macaddr.c b/contrib/btree_gist/btree_macaddr.c
index c444a709853..d8503b1366f 100644
--- a/contrib/btree_gist/btree_macaddr.c
+++ b/contrib/btree_gist/btree_macaddr.c
@@ -147,7 +147,7 @@ Datum
 gbt_macad_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc0(sizeof(macKEY));
+	void	   *out = palloc0_object(macKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(macKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_macaddr8.c b/contrib/btree_gist/btree_macaddr8.c
index 6d9837d90a3..4f0d0fb7140 100644
--- a/contrib/btree_gist/btree_macaddr8.c
+++ b/contrib/btree_gist/btree_macaddr8.c
@@ -145,7 +145,7 @@ Datum
 gbt_macad8_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc0(sizeof(mac8KEY));
+	void	   *out = palloc0_object(mac8KEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(mac8KEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_oid.c b/contrib/btree_gist/btree_oid.c
index b8f2f661076..76d7c55a308 100644
--- a/contrib/btree_gist/btree_oid.c
+++ b/contrib/btree_gist/btree_oid.c
@@ -176,7 +176,7 @@ Datum
 gbt_oid_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(oidKEY));
+	void	   *out = palloc_object(oidKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_time.c b/contrib/btree_gist/btree_time.c
index 9483846c473..8c456728820 100644
--- a/contrib/btree_gist/btree_time.c
+++ b/contrib/btree_gist/btree_time.c
@@ -162,11 +162,11 @@ gbt_timetz_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)
 	{
-		timeKEY    *r = (timeKEY *) palloc(sizeof(timeKEY));
+		timeKEY    *r = palloc_object(timeKEY);
 		TimeTzADT  *tz = DatumGetTimeTzADTP(entry->key);
 		TimeADT		tmp;
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 
 		/* We are using the time + zone only to compress */
 		tmp = tz->time + (tz->zone * INT64CONST(1000000));
@@ -256,7 +256,7 @@ Datum
 gbt_time_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(timeKEY));
+	void	   *out = palloc_object(timeKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c
index b7bbae2f4d6..b7c43c20b91 100644
--- a/contrib/btree_gist/btree_ts.c
+++ b/contrib/btree_gist/btree_ts.c
@@ -146,7 +146,7 @@ ts_dist(PG_FUNCTION_ARGS)
 
 	if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
 	{
-		Interval   *p = palloc(sizeof(Interval));
+		Interval   *p = palloc_object(Interval);
 
 		p->day = INT_MAX;
 		p->month = INT_MAX;
@@ -170,7 +170,7 @@ tstz_dist(PG_FUNCTION_ARGS)
 
 	if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
 	{
-		Interval   *p = palloc(sizeof(Interval));
+		Interval   *p = palloc_object(Interval);
 
 		p->day = INT_MAX;
 		p->month = INT_MAX;
@@ -212,13 +212,13 @@ gbt_tstz_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)
 	{
-		tsKEY	   *r = (tsKEY *) palloc(sizeof(tsKEY));
+		tsKEY	   *r = palloc_object(tsKEY);
 		TimestampTz ts = DatumGetTimestampTz(entry->key);
 		Timestamp	gmt;
 
 		gmt = tstz_to_ts_gmt(ts);
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		r->lower = r->upper = gmt;
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page,
@@ -325,7 +325,7 @@ Datum
 gbt_ts_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(tsKEY));
+	void	   *out = palloc_object(tsKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/btree_gist/btree_utils_num.c b/contrib/btree_gist/btree_utils_num.c
index 9ba97f96fbf..51c8836f27a 100644
--- a/contrib/btree_gist/btree_utils_num.c
+++ b/contrib/btree_gist/btree_utils_num.c
@@ -89,7 +89,7 @@ gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
 
 		memcpy(&r[0], leaf, tinfo->size);
 		memcpy(&r[tinfo->size], leaf, tinfo->size);
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
 					  entry->offset, false);
 	}
@@ -156,7 +156,7 @@ gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
 			datum = entry->key;
 	}
 
-	retval = palloc(sizeof(GISTENTRY));
+	retval = palloc_object(GISTENTRY);
 	gistentryinit(*retval, datum, entry->rel, entry->page, entry->offset,
 				  false);
 	return retval;
diff --git a/contrib/btree_gist/btree_utils_var.c b/contrib/btree_gist/btree_utils_var.c
index fb466e5aa32..2f69389ed69 100644
--- a/contrib/btree_gist/btree_utils_var.c
+++ b/contrib/btree_gist/btree_utils_var.c
@@ -40,7 +40,7 @@ gbt_var_decompress(PG_FUNCTION_ARGS)
 
 	if (key != (GBT_VARKEY *) DatumGetPointer(entry->key))
 	{
-		GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
@@ -289,7 +289,7 @@ gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo *tinfo)
 
 		r = gbt_var_key_from_datum(leaf);
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page,
 					  entry->offset, true);
@@ -309,7 +309,7 @@ gbt_var_fetch(PG_FUNCTION_ARGS)
 	GBT_VARKEY_R r = gbt_var_key_readable(key);
 	GISTENTRY  *retval;
 
-	retval = palloc(sizeof(GISTENTRY));
+	retval = palloc_object(GISTENTRY);
 	gistentryinit(*retval, PointerGetDatum(r.lower),
 				  entry->rel, entry->page,
 				  entry->offset, true);
@@ -476,7 +476,7 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
 	v->spl_nleft = 0;
 	v->spl_nright = 0;
 
-	sv = palloc(sizeof(bytea *) * (maxoff + 1));
+	sv = palloc_array(bytea *, (maxoff + 1));
 
 	/* Sort entries */
 
diff --git a/contrib/btree_gist/btree_uuid.c b/contrib/btree_gist/btree_uuid.c
index 07f304f39f1..d423aea15c1 100644
--- a/contrib/btree_gist/btree_uuid.c
+++ b/contrib/btree_gist/btree_uuid.c
@@ -108,7 +108,7 @@ gbt_uuid_compress(PG_FUNCTION_ARGS)
 		char	   *r = (char *) palloc(2 * UUID_LEN);
 		pg_uuid_t  *key = DatumGetUUIDP(entry->key);
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 
 		memcpy(r, key, UUID_LEN);
 		memcpy(r + UUID_LEN, key, UUID_LEN);
@@ -157,7 +157,7 @@ Datum
 gbt_uuid_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-	void	   *out = palloc(sizeof(uuidKEY));
+	void	   *out = palloc_object(uuidKEY);
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(uuidKEY);
 	PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c
index aa47e141f81..3600457cbc0 100644
--- a/contrib/cube/cube.c
+++ b/contrib/cube/cube.c
@@ -471,7 +471,7 @@ g_cube_decompress(PG_FUNCTION_ARGS)
 
 	if (key != DatumGetNDBOXP(entry->key))
 	{
-		GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
diff --git a/contrib/dict_int/dict_int.c b/contrib/dict_int/dict_int.c
index bdad52d2028..5d9523a1a63 100644
--- a/contrib/dict_int/dict_int.c
+++ b/contrib/dict_int/dict_int.c
@@ -38,7 +38,7 @@ dintdict_init(PG_FUNCTION_ARGS)
 	DictInt    *d;
 	ListCell   *l;
 
-	d = (DictInt *) palloc0(sizeof(DictInt));
+	d = palloc0_object(DictInt);
 	d->maxlen = 6;
 	d->rejectlong = false;
 	d->absval = false;
@@ -83,7 +83,7 @@ dintdict_lexize(PG_FUNCTION_ARGS)
 	char	   *in = (char *) PG_GETARG_POINTER(1);
 	int			len = PG_GETARG_INT32(2);
 	char	   *txt;
-	TSLexeme   *res = palloc0(sizeof(TSLexeme) * 2);
+	TSLexeme   *res = palloc0_array(TSLexeme, 2);
 
 	res[1].lexeme = NULL;
 
diff --git a/contrib/dict_xsyn/dict_xsyn.c b/contrib/dict_xsyn/dict_xsyn.c
index 1ec5285d6d1..bbb2fd850fd 100644
--- a/contrib/dict_xsyn/dict_xsyn.c
+++ b/contrib/dict_xsyn/dict_xsyn.c
@@ -109,9 +109,9 @@ read_dictionary(DictSyn *d, const char *filename)
 			{
 				d->len = (d->len > 0) ? 2 * d->len : 16;
 				if (d->syn)
-					d->syn = (Syn *) repalloc(d->syn, sizeof(Syn) * d->len);
+					d->syn = repalloc_array(d->syn, Syn, d->len);
 				else
-					d->syn = (Syn *) palloc(sizeof(Syn) * d->len);
+					d->syn = palloc_array(Syn, d->len);
 			}
 
 			/* Save first word only if we will match it */
@@ -150,7 +150,7 @@ dxsyn_init(PG_FUNCTION_ARGS)
 	ListCell   *l;
 	char	   *filename = NULL;
 
-	d = (DictSyn *) palloc0(sizeof(DictSyn));
+	d = palloc0_object(DictSyn);
 	d->len = 0;
 	d->syn = NULL;
 	d->matchorig = true;
@@ -235,7 +235,7 @@ dxsyn_lexize(PG_FUNCTION_ARGS)
 		char	   *end;
 		int			nsyns = 0;
 
-		res = palloc(sizeof(TSLexeme));
+		res = palloc_object(TSLexeme);
 
 		pos = value;
 		while ((syn = find_word(pos, &end)) != NULL)
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 70564a68b13..e9cda3c47d1 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -531,7 +531,7 @@ fileGetForeignRelSize(PlannerInfo *root,
 	 * we might as well get everything and not need to re-fetch it later in
 	 * planning.
 	 */
-	fdw_private = (FileFdwPlanState *) palloc(sizeof(FileFdwPlanState));
+	fdw_private = palloc_object(FileFdwPlanState);
 	fileGetOptions(foreigntableid,
 				   &fdw_private->filename,
 				   &fdw_private->is_program,
@@ -712,7 +712,7 @@ fileBeginForeignScan(ForeignScanState *node, int eflags)
 	 * Save state in node->fdw_state.  We must save enough information to call
 	 * BeginCopyFrom() again.
 	 */
-	festate = (FileFdwExecutionState *) palloc(sizeof(FileFdwExecutionState));
+	festate = palloc_object(FileFdwExecutionState);
 	festate->filename = filename;
 	festate->is_program = is_program;
 	festate->options = options;
diff --git a/contrib/hstore/hstore_gist.c b/contrib/hstore/hstore_gist.c
index 69515dc3d3f..36825ef867b 100644
--- a/contrib/hstore/hstore_gist.c
+++ b/contrib/hstore/hstore_gist.c
@@ -175,7 +175,7 @@ ghstore_compress(PG_FUNCTION_ARGS)
 			}
 		}
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset,
@@ -195,7 +195,7 @@ ghstore_compress(PG_FUNCTION_ARGS)
 
 		res = ghstore_alloc(true, siglen, NULL);
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset,
@@ -429,7 +429,7 @@ ghstore_picksplit(PG_FUNCTION_ARGS)
 
 	maxoff = OffsetNumberNext(maxoff);
 	/* sort before ... */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index 9c53877c4a5..6b01f27c5a4 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -221,7 +221,7 @@ parse_hstore(HSParser *state)
 	bool		escaped = false;
 
 	state->plen = 16;
-	state->pairs = (Pairs *) palloc(sizeof(Pairs) * state->plen);
+	state->pairs = palloc_array(Pairs, state->plen);
 	state->pcur = 0;
 	state->ptr = state->begin;
 	state->word = NULL;
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index 2b2c3f4029e..f45df86d60c 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -135,7 +135,7 @@ gettoken(WORKSTATE *state, int32 *val)
 static void
 pushquery(WORKSTATE *state, int32 type, int32 val)
 {
-	NODE	   *tmp = (NODE *) palloc(sizeof(NODE));
+	NODE	   *tmp = palloc_object(NODE);
 
 	tmp->type = type;
 	tmp->val = val;
@@ -346,7 +346,7 @@ gin_bool_consistent(QUERYTYPE *query, bool *check)
 	 * extraction code in ginint4_queryextract.
 	 */
 	gcv.first = items;
-	gcv.mapped_check = (bool *) palloc(sizeof(bool) * query->size);
+	gcv.mapped_check = palloc_array(bool, query->size);
 	for (i = 0; i < query->size; i++)
 	{
 		if (items[i].type == VAL)
@@ -613,7 +613,7 @@ infix(INFIX *in, bool first)
 
 		nrm.curpol = in->curpol;
 		nrm.buflen = 16;
-		nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+		nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 
 		/* get right operand */
 		infix(&nrm, false);
@@ -651,7 +651,7 @@ bqarr_out(PG_FUNCTION_ARGS)
 
 	nrm.curpol = GETQUERY(query) + query->size - 1;
 	nrm.buflen = 32;
-	nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+	nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 	*(nrm.cur) = '\0';
 	infix(&nrm, true);
 
diff --git a/contrib/intarray/_int_gin.c b/contrib/intarray/_int_gin.c
index b7958d8eca5..c60616c3f77 100644
--- a/contrib/intarray/_int_gin.c
+++ b/contrib/intarray/_int_gin.c
@@ -42,7 +42,7 @@ ginint4_queryextract(PG_FUNCTION_ARGS)
 		/*
 		 * Extract all the VAL items as things we want GIN to check for.
 		 */
-		res = (Datum *) palloc(sizeof(Datum) * query->size);
+		res = palloc_array(Datum, query->size);
 		*nentries = 0;
 
 		for (i = 0; i < query->size; i++)
@@ -65,7 +65,7 @@ ginint4_queryextract(PG_FUNCTION_ARGS)
 			int32	   *arr;
 			int32		i;
 
-			res = (Datum *) palloc(sizeof(Datum) * (*nentries));
+			res = palloc_array(Datum, *nentries);
 
 			arr = ARRPTR(query);
 			for (i = 0; i < *nentries; i++)
diff --git a/contrib/intarray/_int_gist.c b/contrib/intarray/_int_gist.c
index a09b7fa812c..90cf11c01a5 100644
--- a/contrib/intarray/_int_gist.c
+++ b/contrib/intarray/_int_gist.c
@@ -186,7 +186,7 @@ g_int_compress(PG_FUNCTION_ARGS)
 					 errmsg("input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead",
 							2 * num_ranges - 1, ARRNELEMS(r))));
 
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page, entry->offset, false);
 
@@ -276,7 +276,7 @@ g_int_compress(PG_FUNCTION_ARGS)
 					 errmsg("data is too sparse, recreate index using gist__intbig_ops opclass instead")));
 
 		r = resize_intArrayType(r, len);
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page, entry->offset, false);
 		PG_RETURN_POINTER(retval);
@@ -306,7 +306,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
 	{
 		if (in != (ArrayType *) DatumGetPointer(entry->key))
 		{
-			retval = palloc(sizeof(GISTENTRY));
+			retval = palloc_object(GISTENTRY);
 			gistentryinit(*retval, PointerGetDatum(in),
 						  entry->rel, entry->page, entry->offset, false);
 			PG_RETURN_POINTER(retval);
@@ -321,7 +321,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
 	{							/* not compressed value */
 		if (in != (ArrayType *) DatumGetPointer(entry->key))
 		{
-			retval = palloc(sizeof(GISTENTRY));
+			retval = palloc_object(GISTENTRY);
 			gistentryinit(*retval, PointerGetDatum(in),
 						  entry->rel, entry->page, entry->offset, false);
 
@@ -350,7 +350,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
 
 	if (in != (ArrayType *) DatumGetPointer(entry->key))
 		pfree(in);
-	retval = palloc(sizeof(GISTENTRY));
+	retval = palloc_object(GISTENTRY);
 	gistentryinit(*retval, PointerGetDatum(r),
 				  entry->rel, entry->page, entry->offset, false);
 
@@ -535,7 +535,7 @@ g_int_picksplit(PG_FUNCTION_ARGS)
 	/*
 	 * sort entries
 	 */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
 	{
 		costvector[i - 1].pos = i;
diff --git a/contrib/intarray/_intbig_gist.c b/contrib/intarray/_intbig_gist.c
index 9699fbf3b4f..0afa8a73b68 100644
--- a/contrib/intarray/_intbig_gist.c
+++ b/contrib/intarray/_intbig_gist.c
@@ -174,7 +174,7 @@ g_intbig_compress(PG_FUNCTION_ARGS)
 			ptr++;
 		}
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -195,7 +195,7 @@ g_intbig_compress(PG_FUNCTION_ARGS)
 		}
 
 		res = _intbig_alloc(true, siglen, sign);
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -385,7 +385,7 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 
 	maxoff = OffsetNumberNext(maxoff);
 	/* sort before ... */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/contrib/jsonb_plperl/jsonb_plperl.c b/contrib/jsonb_plperl/jsonb_plperl.c
index c02e2d41af1..a708d9fd82e 100644
--- a/contrib/jsonb_plperl/jsonb_plperl.c
+++ b/contrib/jsonb_plperl/jsonb_plperl.c
@@ -266,7 +266,7 @@ SV_to_JsonbValue(SV *in, JsonbParseState **jsonb_state, bool is_elem)
 	/* Push result into 'jsonb_state' unless it is a raw scalar. */
 	return *jsonb_state
 		? pushJsonbValue(jsonb_state, is_elem ? WJB_ELEM : WJB_VALUE, &out)
-		: memcpy(palloc(sizeof(JsonbValue)), &out, sizeof(JsonbValue));
+		: memcpy(palloc_object(JsonbValue), &out, sizeof(JsonbValue));
 }
 
 
diff --git a/contrib/jsonb_plpython/jsonb_plpython.c b/contrib/jsonb_plpython/jsonb_plpython.c
index 9383615abbf..2892e88c58b 100644
--- a/contrib/jsonb_plpython/jsonb_plpython.c
+++ b/contrib/jsonb_plpython/jsonb_plpython.c
@@ -419,7 +419,7 @@ PLyObject_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state, bool is_ele
 			return PLyMapping_ToJsonbValue(obj, jsonb_state);
 	}
 
-	out = palloc(sizeof(JsonbValue));
+	out = palloc_object(JsonbValue);
 
 	if (obj == Py_None)
 		out->type = jbvNull;
diff --git a/contrib/ltree/_ltree_gist.c b/contrib/ltree/_ltree_gist.c
index 30d516e60bc..ceb92a6304d 100644
--- a/contrib/ltree/_ltree_gist.c
+++ b/contrib/ltree/_ltree_gist.c
@@ -79,7 +79,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
 			item = NEXTVAL(item);
 		}
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -97,7 +97,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
 		}
 
 		key = ltree_gist_alloc(true, sign, siglen, NULL, NULL);
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -310,7 +310,7 @@ _ltree_picksplit(PG_FUNCTION_ARGS)
 
 	maxoff = OffsetNumberNext(maxoff);
 	/* sort before ... */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/contrib/ltree/_ltree_op.c b/contrib/ltree/_ltree_op.c
index b4a8097328d..4d54ad34bb6 100644
--- a/contrib/ltree/_ltree_op.c
+++ b/contrib/ltree/_ltree_op.c
@@ -307,7 +307,7 @@ _lca(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 				 errmsg("array must not contain nulls")));
 
-	a = (ltree **) palloc(sizeof(ltree *) * num);
+	a = palloc_array(ltree *, num);
 	while (num > 0)
 	{
 		num--;
diff --git a/contrib/ltree/ltree_gist.c b/contrib/ltree/ltree_gist.c
index 932f69bff2d..bb7f4634722 100644
--- a/contrib/ltree/ltree_gist.c
+++ b/contrib/ltree/ltree_gist.c
@@ -101,7 +101,7 @@ ltree_compress(PG_FUNCTION_ARGS)
 		ltree	   *val = DatumGetLtreeP(entry->key);
 		ltree_gist *key = ltree_gist_alloc(false, NULL, 0, val, 0);
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -117,7 +117,7 @@ ltree_decompress(PG_FUNCTION_ARGS)
 
 	if (PointerGetDatum(key) != entry->key)
 	{
-		GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
@@ -318,7 +318,7 @@ ltree_picksplit(PG_FUNCTION_ARGS)
 	v->spl_right = (OffsetNumber *) palloc(nbytes);
 	v->spl_nleft = 0;
 	v->spl_nright = 0;
-	array = (RIX *) palloc(sizeof(RIX) * (maxoff + 1));
+	array = palloc_array(RIX, maxoff + 1);
 
 	/* copy the data into RIXes, and sort the RIXes */
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
diff --git a/contrib/ltree/ltree_io.c b/contrib/ltree/ltree_io.c
index b54a15d6c68..59c4462df80 100644
--- a/contrib/ltree/ltree_io.c
+++ b/contrib/ltree/ltree_io.c
@@ -65,7 +65,7 @@ parse_ltree(const char *buf, struct Node *escontext)
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("number of ltree labels (%d) exceeds the maximum allowed (%d)",
 						num + 1, LTREE_MAX_LEVELS)));
-	list = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (num + 1));
+	list = lptr = palloc_array(nodeitem, num + 1);
 	ptr = buf;
 	while (*ptr)
 	{
@@ -318,14 +318,14 @@ parse_lquery(const char *buf, struct Node *escontext)
 			case LQPRS_WAITLEVEL:
 				if (ISLABEL(ptr))
 				{
-					GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
+					GETVAR(curqlevel) = lptr = palloc0_array(nodeitem, numOR + 1);
 					lptr->start = ptr;
 					state = LQPRS_WAITDELIM;
 					curqlevel->numvar = 1;
 				}
 				else if (t_iseq(ptr, '!'))
 				{
-					GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
+					GETVAR(curqlevel) = lptr = palloc0_array(nodeitem, numOR + 1);
 					lptr->start = ptr + 1;
 					lptr->wlen = -1;	/* compensate for counting ! below */
 					state = LQPRS_WAITDELIM;
diff --git a/contrib/ltree/ltree_op.c b/contrib/ltree/ltree_op.c
index e3a84db37ff..c1fc77fc804 100644
--- a/contrib/ltree/ltree_op.c
+++ b/contrib/ltree/ltree_op.c
@@ -566,7 +566,7 @@ lca(PG_FUNCTION_ARGS)
 	ltree	  **a,
 			   *res;
 
-	a = (ltree **) palloc(sizeof(ltree *) * fcinfo->nargs);
+	a = palloc_array(ltree *, fcinfo->nargs);
 	for (i = 0; i < fcinfo->nargs; i++)
 		a[i] = PG_GETARG_LTREE_P(i);
 	res = lca_inner(a, (int) fcinfo->nargs);
diff --git a/contrib/ltree/ltxtquery_io.c b/contrib/ltree/ltxtquery_io.c
index ec331607793..3a2aa223c3e 100644
--- a/contrib/ltree/ltxtquery_io.c
+++ b/contrib/ltree/ltxtquery_io.c
@@ -154,7 +154,7 @@ gettoken_query(QPRS_STATE *state, int32 *val, int32 *lenval, char **strval, uint
 static bool
 pushquery(QPRS_STATE *state, int32 type, int32 val, int32 distance, int32 lenval, uint16 flag)
 {
-	NODE	   *tmp = (NODE *) palloc(sizeof(NODE));
+	NODE	   *tmp = palloc_object(NODE);
 
 	tmp->type = type;
 	tmp->val = val;
@@ -543,7 +543,7 @@ infix(INFIX *in, bool first)
 		nrm.curpol = in->curpol;
 		nrm.op = in->op;
 		nrm.buflen = 16;
-		nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+		nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 
 		/* get right operand */
 		infix(&nrm, false);
@@ -582,7 +582,7 @@ ltxtq_out(PG_FUNCTION_ARGS)
 
 	nrm.curpol = GETQUERY(query);
 	nrm.buflen = 32;
-	nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+	nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 	*(nrm.cur) = '\0';
 	nrm.op = GETOPERAND(query);
 	infix(&nrm, true);
@@ -615,7 +615,7 @@ ltxtq_send(PG_FUNCTION_ARGS)
 
 	nrm.curpol = GETQUERY(query);
 	nrm.buflen = 32;
-	nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+	nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 	*(nrm.cur) = '\0';
 	nrm.op = GETOPERAND(query);
 	infix(&nrm, true);
diff --git a/contrib/pageinspect/brinfuncs.c b/contrib/pageinspect/brinfuncs.c
index 990c965aa92..c5cebcd280b 100644
--- a/contrib/pageinspect/brinfuncs.c
+++ b/contrib/pageinspect/brinfuncs.c
@@ -186,7 +186,7 @@ brin_page_items(PG_FUNCTION_ARGS)
 	 * Initialize output functions for all indexed datatypes; simplifies
 	 * calling them later.
 	 */
-	columns = palloc(sizeof(brin_column_state *) * RelationGetDescr(indexRel)->natts);
+	columns = palloc_array(brin_column_state *, RelationGetDescr(indexRel)->natts); 
 	for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 	{
 		Oid			output;
diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c
index 2e67c9adf5a..7ff6dc08934 100644
--- a/contrib/pageinspect/btreefuncs.c
+++ b/contrib/pageinspect/btreefuncs.c
@@ -379,7 +379,7 @@ bt_multi_page_stats(PG_FUNCTION_ARGS)
 		/* Save arguments for reuse */
 		mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
 
-		uargs = palloc(sizeof(ua_page_stats));
+		uargs = palloc_object(ua_page_stats);
 
 		uargs->relid = RelationGetRelid(rel);
 		uargs->blkno = blkno;
@@ -660,7 +660,7 @@ bt_page_items_internal(PG_FUNCTION_ARGS, enum pageinspect_version ext_version)
 		 */
 		mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
 
-		uargs = palloc(sizeof(ua_page_items));
+		uargs = palloc_object(ua_page_items);
 
 		uargs->page = palloc(BLCKSZ);
 		memcpy(uargs->page, BufferGetPage(buffer), BLCKSZ);
@@ -752,7 +752,7 @@ bt_page_items_bytea(PG_FUNCTION_ARGS)
 		fctx = SRF_FIRSTCALL_INIT();
 		mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
 
-		uargs = palloc(sizeof(ua_page_items));
+		uargs = palloc_object(ua_page_items);
 
 		uargs->page = get_page_from_raw(raw_page);
 
diff --git a/contrib/pageinspect/ginfuncs.c b/contrib/pageinspect/ginfuncs.c
index 09a90957081..f6168d8e895 100644
--- a/contrib/pageinspect/ginfuncs.c
+++ b/contrib/pageinspect/ginfuncs.c
@@ -222,7 +222,7 @@ gin_leafpage_items(PG_FUNCTION_ARGS)
 							   opaq->flags,
 							   (GIN_DATA | GIN_LEAF | GIN_COMPRESSED))));
 
-		inter_call_data = palloc(sizeof(gin_leafpage_items_state));
+		inter_call_data = palloc_object(gin_leafpage_items_state);
 
 		/* Build a tuple descriptor for our result type */
 		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
diff --git a/contrib/pageinspect/hashfuncs.c b/contrib/pageinspect/hashfuncs.c
index ca7f1f6e741..0e898889fa5 100644
--- a/contrib/pageinspect/hashfuncs.c
+++ b/contrib/pageinspect/hashfuncs.c
@@ -325,7 +325,7 @@ hash_page_items(PG_FUNCTION_ARGS)
 
 		page = verify_hash_page(raw_page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
 
-		uargs = palloc(sizeof(struct user_args));
+		uargs = palloc_object(struct user_args);
 
 		uargs->page = page;
 
diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c
index c13f07655c4..b38c4d159f6 100644
--- a/contrib/pageinspect/heapfuncs.c
+++ b/contrib/pageinspect/heapfuncs.c
@@ -154,7 +154,7 @@ heap_page_items(PG_FUNCTION_ARGS)
 		fctx = SRF_FIRSTCALL_INIT();
 		mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
 
-		inter_call_data = palloc(sizeof(heap_page_items_state));
+		inter_call_data = palloc_object(heap_page_items_state);
 
 		/* Build a tuple descriptor for our result type */
 		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
@@ -553,7 +553,7 @@ heap_tuple_infomask_flags(PG_FUNCTION_ARGS)
 	}
 
 	/* build set of raw flags */
-	flags = (Datum *) palloc0(sizeof(Datum) * bitcnt);
+	flags = palloc0_array(Datum, bitcnt); 
 
 	/* decode t_infomask */
 	if ((t_infomask & HEAP_HASNULL) != 0)
diff --git a/contrib/pg_overexplain/pg_overexplain.c b/contrib/pg_overexplain/pg_overexplain.c
index bd70b6d9d5e..fcdc17012da 100644
--- a/contrib/pg_overexplain/pg_overexplain.c
+++ b/contrib/pg_overexplain/pg_overexplain.c
@@ -95,7 +95,7 @@ overexplain_ensure_options(ExplainState *es)
 
 	if (options == NULL)
 	{
-		options = palloc0(sizeof(overexplain_options));
+		options = palloc0_object(overexplain_options);
 		SetExplainExtensionState(es, es_extension_id, options);
 	}
 
diff --git a/contrib/pg_trgm/trgm_gin.c b/contrib/pg_trgm/trgm_gin.c
index 29a52eac7af..34a91cf9789 100644
--- a/contrib/pg_trgm/trgm_gin.c
+++ b/contrib/pg_trgm/trgm_gin.c
@@ -51,7 +51,7 @@ gin_extract_value_trgm(PG_FUNCTION_ARGS)
 		int32		i;
 
 		*nentries = trglen;
-		entries = (Datum *) palloc(sizeof(Datum) * trglen);
+		entries = palloc_array(Datum, trglen);
 
 		ptr = GETARR(trg);
 		for (i = 0; i < trglen; i++)
@@ -123,7 +123,7 @@ gin_extract_query_trgm(PG_FUNCTION_ARGS)
 				 * Pointers, but we just put the same value in each element.
 				 */
 				trglen = ARRNELEM(trg);
-				*extra_data = (Pointer *) palloc(sizeof(Pointer) * trglen);
+				*extra_data = palloc_array(Pointer, trglen);
 				for (i = 0; i < trglen; i++)
 					(*extra_data)[i] = (Pointer) graph;
 			}
@@ -146,7 +146,7 @@ gin_extract_query_trgm(PG_FUNCTION_ARGS)
 
 	if (trglen > 0)
 	{
-		entries = (Datum *) palloc(sizeof(Datum) * trglen);
+		entries = palloc_array(Datum, trglen);
 		ptr = GETARR(trg);
 		for (i = 0; i < trglen; i++)
 		{
@@ -339,7 +339,7 @@ gin_trgm_triconsistent(PG_FUNCTION_ARGS)
 				 * function, promoting all GIN_MAYBE keys to GIN_TRUE will
 				 * give a conservative result.
 				 */
-				boolcheck = (bool *) palloc(sizeof(bool) * nkeys);
+				boolcheck = palloc_array(bool, nkeys);
 				for (i = 0; i < nkeys; i++)
 					boolcheck[i] = (check[i] != GIN_FALSE);
 				if (!trigramsMatchGraph((TrgmPackedGraph *) extra_data[0],
diff --git a/contrib/pg_trgm/trgm_gist.c b/contrib/pg_trgm/trgm_gist.c
index 5ba895217b0..5c7deb103a6 100644
--- a/contrib/pg_trgm/trgm_gist.c
+++ b/contrib/pg_trgm/trgm_gist.c
@@ -124,7 +124,7 @@ gtrgm_compress(PG_FUNCTION_ARGS)
 		text	   *val = DatumGetTextPP(entry->key);
 
 		res = generate_trgm(VARDATA_ANY(val), VARSIZE_ANY_EXHDR(val));
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -143,7 +143,7 @@ gtrgm_compress(PG_FUNCTION_ARGS)
 		}
 
 		res = gtrgm_alloc(true, siglen, sign);
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -163,7 +163,7 @@ gtrgm_decompress(PG_FUNCTION_ARGS)
 	if (key != (text *) DatumGetPointer(entry->key))
 	{
 		/* need to pass back the decompressed item */
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page, entry->offset, entry->leafkey);
 		PG_RETURN_POINTER(retval);
@@ -820,7 +820,7 @@ gtrgm_picksplit(PG_FUNCTION_ARGS)
 	SPLITCOST  *costvector;
 
 	/* cache the sign data for each existing item */
-	cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 1));
+	cache = palloc_array(CACHESIGN, maxoff + 1);
 	cache_sign = palloc(siglen * (maxoff + 1));
 
 	for (k = FirstOffsetNumber; k <= maxoff; k = OffsetNumberNext(k))
@@ -864,7 +864,7 @@ gtrgm_picksplit(PG_FUNCTION_ARGS)
 	union_r = GETSIGN(datum_r);
 
 	/* sort before ... */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/contrib/pg_trgm/trgm_regexp.c b/contrib/pg_trgm/trgm_regexp.c
index 149f9eb259c..1a76794c422 100644
--- a/contrib/pg_trgm/trgm_regexp.c
+++ b/contrib/pg_trgm/trgm_regexp.c
@@ -791,12 +791,11 @@ getColorInfo(regex_t *regex, TrgmNFA *trgmNFA)
 
 		colorInfo->expandable = true;
 		colorInfo->containsNonWord = false;
-		colorInfo->wordChars = (trgm_mb_char *)
-			palloc(sizeof(trgm_mb_char) * charsCount);
+		colorInfo->wordChars = palloc_array(trgm_mb_char, charsCount);
 		colorInfo->wordCharsCount = 0;
 
 		/* Extract all the chars in this color */
-		chars = (pg_wchar *) palloc(sizeof(pg_wchar) * charsCount);
+		chars = palloc_array(pg_wchar, charsCount);
 		pg_reg_getcharacters(regex, i, chars, charsCount);
 
 		/*
@@ -1063,7 +1062,7 @@ addKey(TrgmNFA *trgmNFA, TrgmState *state, TrgmStateKey *key)
 	 * original NFA.
 	 */
 	arcsCount = pg_reg_getnumoutarcs(trgmNFA->regex, key->nstate);
-	arcs = (regex_arc_t *) palloc(sizeof(regex_arc_t) * arcsCount);
+	arcs = palloc_array(regex_arc_t, arcsCount);
 	pg_reg_getoutarcs(trgmNFA->regex, key->nstate, arcs, arcsCount);
 
 	for (i = 0; i < arcsCount; i++)
@@ -1177,7 +1176,7 @@ addKey(TrgmNFA *trgmNFA, TrgmState *state, TrgmStateKey *key)
 static void
 addKeyToQueue(TrgmNFA *trgmNFA, TrgmStateKey *key)
 {
-	TrgmStateKey *keyCopy = (TrgmStateKey *) palloc(sizeof(TrgmStateKey));
+	TrgmStateKey *keyCopy = palloc_object(TrgmStateKey);
 
 	memcpy(keyCopy, key, sizeof(TrgmStateKey));
 	trgmNFA->keysQueue = lappend(trgmNFA->keysQueue, keyCopy);
@@ -1215,7 +1214,7 @@ addArcs(TrgmNFA *trgmNFA, TrgmState *state)
 		TrgmStateKey *key = (TrgmStateKey *) lfirst(cell);
 
 		arcsCount = pg_reg_getnumoutarcs(trgmNFA->regex, key->nstate);
-		arcs = (regex_arc_t *) palloc(sizeof(regex_arc_t) * arcsCount);
+		arcs = palloc_array(regex_arc_t, arcsCount);
 		pg_reg_getoutarcs(trgmNFA->regex, key->nstate, arcs, arcsCount);
 
 		for (i = 0; i < arcsCount; i++)
@@ -1311,7 +1310,7 @@ addArc(TrgmNFA *trgmNFA, TrgmState *state, TrgmStateKey *key,
 	}
 
 	/* Checks were successful, add new arc */
-	arc = (TrgmArc *) palloc(sizeof(TrgmArc));
+	arc = palloc_object(TrgmArc);
 	arc->target = getState(trgmNFA, destKey);
 	arc->ctrgm.colors[0] = key->prefix.colors[0];
 	arc->ctrgm.colors[1] = key->prefix.colors[1];
@@ -1467,7 +1466,7 @@ selectColorTrigrams(TrgmNFA *trgmNFA)
 	int			cnumber;
 
 	/* Collect color trigrams from all arcs */
-	colorTrgms = (ColorTrgmInfo *) palloc0(sizeof(ColorTrgmInfo) * arcsCount);
+	colorTrgms = palloc0_array(ColorTrgmInfo, arcsCount);
 	trgmNFA->colorTrgms = colorTrgms;
 
 	i = 0;
@@ -1479,7 +1478,7 @@ selectColorTrigrams(TrgmNFA *trgmNFA)
 		foreach(cell, state->arcs)
 		{
 			TrgmArc    *arc = (TrgmArc *) lfirst(cell);
-			TrgmArcInfo *arcInfo = (TrgmArcInfo *) palloc(sizeof(TrgmArcInfo));
+			TrgmArcInfo *arcInfo = palloc_object(TrgmArcInfo);
 			ColorTrgmInfo *trgmInfo = &colorTrgms[i];
 
 			arcInfo->source = state;
@@ -1964,8 +1963,7 @@ packGraph(TrgmNFA *trgmNFA, MemoryContext rcontext)
 	}
 
 	/* Collect array of all arcs */
-	arcs = (TrgmPackArcInfo *)
-		palloc(sizeof(TrgmPackArcInfo) * trgmNFA->arcsCount);
+	arcs = palloc_array(TrgmPackArcInfo, trgmNFA->arcsCount);
 	arcIndex = 0;
 	hash_seq_init(&scan_status, trgmNFA->states);
 	while ((state = (TrgmState *) hash_seq_search(&scan_status)) != NULL)
@@ -2147,7 +2145,7 @@ printSourceNFA(regex_t *regex, TrgmColorInfo *colors, int ncolors)
 		appendStringInfoString(&buf, ";\n");
 
 		arcsCount = pg_reg_getnumoutarcs(regex, state);
-		arcs = (regex_arc_t *) palloc(sizeof(regex_arc_t) * arcsCount);
+		arcs = palloc_array(regex_arc_t, arcsCount);
 		pg_reg_getoutarcs(regex, state, arcs, arcsCount);
 
 		for (i = 0; i < arcsCount; i++)
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index d79ef35006b..7046c1b5f8e 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -741,7 +741,7 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
 	 * number of entries allocated.  We'll repurpose these fields before
 	 * returning.
 	 */
-	items = palloc0(sizeof(corrupt_items));
+	items = palloc0_object(corrupt_items);
 	items->next = 0;
 	items->count = 64;
 	items->tids = palloc(items->count * sizeof(ItemPointerData));
diff --git a/contrib/pg_walinspect/pg_walinspect.c b/contrib/pg_walinspect/pg_walinspect.c
index 3c5e4a856a7..6945bac1306 100644
--- a/contrib/pg_walinspect/pg_walinspect.c
+++ b/contrib/pg_walinspect/pg_walinspect.c
@@ -109,8 +109,7 @@ InitXLogReaderState(XLogRecPtr lsn)
 				 errmsg("could not read WAL at LSN %X/%08X",
 						LSN_FORMAT_ARGS(lsn))));
 
-	private_data = (ReadLocalXLogPageNoWaitPrivate *)
-		palloc0(sizeof(ReadLocalXLogPageNoWaitPrivate));
+	private_data = palloc0_object(ReadLocalXLogPageNoWaitPrivate);
 
 	xlogreader = XLogReaderAllocate(wal_segment_size, NULL,
 									XL_ROUTINE(.page_read = &read_local_xlog_page_no_wait,
@@ -310,7 +309,7 @@ GetWALBlockInfo(FunctionCallInfo fcinfo, XLogReaderState *record,
 			/* Construct and save block_fpi_info */
 			bitcnt = pg_popcount((const char *) &blk->bimg_info,
 								 sizeof(uint8));
-			flags = (Datum *) palloc0(sizeof(Datum) * bitcnt);
+			flags = palloc0_array(Datum, bitcnt);
 			if ((blk->bimg_info & BKPIMAGE_HAS_HOLE) != 0)
 				flags[cnt++] = CStringGetTextDatum("HAS_HOLE");
 			if (blk->apply_image)
diff --git a/contrib/pgcrypto/mbuf.c b/contrib/pgcrypto/mbuf.c
index 8dfc1b39d48..6a23ad99706 100644
--- a/contrib/pgcrypto/mbuf.c
+++ b/contrib/pgcrypto/mbuf.c
@@ -115,7 +115,7 @@ mbuf_create(int len)
 	if (!len)
 		len = 8192;
 
-	mbuf = palloc(sizeof *mbuf);
+	mbuf = palloc_object(MBuf);
 	mbuf->data = palloc(len);
 	mbuf->buf_end = mbuf->data + len;
 	mbuf->data_end = mbuf->data;
@@ -132,7 +132,7 @@ mbuf_create_from_data(uint8 *data, int len)
 {
 	MBuf	   *mbuf;
 
-	mbuf = palloc(sizeof *mbuf);
+	mbuf = palloc_object(MBuf);
 	mbuf->data = data;
 	mbuf->buf_end = mbuf->data + len;
 	mbuf->data_end = mbuf->data + len;
@@ -206,7 +206,7 @@ pullf_create(PullFilter **pf_p, const PullFilterOps *op, void *init_arg, PullFil
 		res = 0;
 	}
 
-	pf = palloc0(sizeof(*pf));
+	pf = palloc0_object(PullFilter);
 	pf->buflen = res;
 	pf->op = op;
 	pf->priv = priv;
@@ -372,7 +372,7 @@ pushf_create(PushFilter **mp_p, const PushFilterOps *op, void *init_arg, PushFil
 		res = 0;
 	}
 
-	mp = palloc0(sizeof(*mp));
+	mp = palloc0_object(PushFilter);
 	mp->block_size = res;
 	mp->op = op;
 	mp->priv = priv;
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index f179e80c842..d3c12e7fda3 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -197,7 +197,7 @@ px_find_digest(const char *name, PX_MD **res)
 	ResourceOwnerRememberOSSLDigest(digest->owner, digest);
 
 	/* The PX_MD object is allocated in the current memory context. */
-	h = palloc(sizeof(*h));
+	h = palloc_object(PX_MD);
 	h->result_size = digest_result_size;
 	h->block_size = digest_block_size;
 	h->reset = digest_reset;
@@ -813,7 +813,7 @@ px_find_cipher(const char *name, PX_Cipher **res)
 		od->evp_ciph = i->ciph->cipher_func();
 
 	/* The PX_Cipher is allocated in current memory context */
-	c = palloc(sizeof(*c));
+	c = palloc_object(PX_Cipher);
 	c->block_size = gen_ossl_block_size;
 	c->key_size = gen_ossl_key_size;
 	c->iv_size = gen_ossl_iv_size;
diff --git a/contrib/pgcrypto/pgp-cfb.c b/contrib/pgcrypto/pgp-cfb.c
index de41e825b0c..d8f1afc3aba 100644
--- a/contrib/pgcrypto/pgp-cfb.c
+++ b/contrib/pgcrypto/pgp-cfb.c
@@ -67,7 +67,7 @@ pgp_cfb_create(PGP_CFB **ctx_p, int algo, const uint8 *key, int key_len,
 		return res;
 	}
 
-	ctx = palloc0(sizeof(*ctx));
+	ctx = palloc0_object(PGP_CFB);
 	ctx->ciph = ciph;
 	ctx->block_size = px_cipher_block_size(ciph);
 	ctx->resync = resync;
diff --git a/contrib/pgcrypto/pgp-compress.c b/contrib/pgcrypto/pgp-compress.c
index 961cf21e748..caa80ecdb45 100644
--- a/contrib/pgcrypto/pgp-compress.c
+++ b/contrib/pgcrypto/pgp-compress.c
@@ -80,7 +80,7 @@ compress_init(PushFilter *next, void *init_arg, void **priv_p)
 	/*
 	 * init
 	 */
-	st = palloc0(sizeof(*st));
+	st = palloc0_object(struct ZipStat);
 	st->buf_len = ZIP_OUT_BUF;
 	st->stream.zalloc = z_alloc;
 	st->stream.zfree = z_free;
@@ -211,7 +211,7 @@ decompress_init(void **priv_p, void *arg, PullFilter *src)
 		&& ctx->compress_algo != PGP_COMPR_ZIP)
 		return PXE_PGP_UNSUPPORTED_COMPR;
 
-	dec = palloc0(sizeof(*dec));
+	dec = palloc0_object(struct DecomprData);
 	dec->buf_len = ZIP_OUT_BUF;
 	*priv_p = dec;
 
diff --git a/contrib/pgcrypto/pgp-decrypt.c b/contrib/pgcrypto/pgp-decrypt.c
index e1ea5b3e58d..52ca7840c6d 100644
--- a/contrib/pgcrypto/pgp-decrypt.c
+++ b/contrib/pgcrypto/pgp-decrypt.c
@@ -224,7 +224,7 @@ pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
 					  int pkttype, PGP_Context *ctx)
 {
 	int			res;
-	struct PktData *pkt = palloc(sizeof(*pkt));
+	struct PktData *pkt = palloc_object(struct PktData);
 
 	pkt->type = pkttype;
 	pkt->len = len;
@@ -448,7 +448,7 @@ mdcbuf_init(void **priv_p, void *arg, PullFilter *src)
 	PGP_Context *ctx = arg;
 	struct MDCBufData *st;
 
-	st = palloc0(sizeof(*st));
+	st = palloc0_object(struct MDCBufData);
 	st->buflen = sizeof(st->buf);
 	st->ctx = ctx;
 	*priv_p = st;
diff --git a/contrib/pgcrypto/pgp-encrypt.c b/contrib/pgcrypto/pgp-encrypt.c
index f7467c9b1cb..2c059804706 100644
--- a/contrib/pgcrypto/pgp-encrypt.c
+++ b/contrib/pgcrypto/pgp-encrypt.c
@@ -178,7 +178,7 @@ encrypt_init(PushFilter *next, void *init_arg, void **priv_p)
 	if (res < 0)
 		return res;
 
-	st = palloc0(sizeof(*st));
+	st = palloc0_object(struct EncStat);
 	st->ciph = ciph;
 
 	*priv_p = st;
@@ -240,7 +240,7 @@ pkt_stream_init(PushFilter *next, void *init_arg, void **priv_p)
 {
 	struct PktStreamStat *st;
 
-	st = palloc(sizeof(*st));
+	st = palloc_object(struct PktStreamStat);
 	st->final_done = 0;
 	st->pkt_block = 1 << STREAM_BLOCK_SHIFT;
 	*priv_p = st;
diff --git a/contrib/pgcrypto/pgp-pgsql.c b/contrib/pgcrypto/pgp-pgsql.c
index 7c9f4c7b39b..8cfb1f60f08 100644
--- a/contrib/pgcrypto/pgp-pgsql.c
+++ b/contrib/pgcrypto/pgp-pgsql.c
@@ -782,8 +782,8 @@ parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
 				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 				 errmsg("mismatched array dimensions")));
 
-	keys = (char **) palloc(sizeof(char *) * key_count);
-	values = (char **) palloc(sizeof(char *) * val_count);
+	keys = (char **) palloc_array(char *, key_count);
+	values = (char **) palloc_array(char *, val_count);
 
 	for (i = 0; i < key_count; i++)
 	{
@@ -937,7 +937,7 @@ pgp_armor_headers(PG_FUNCTION_ARGS)
 		attinmeta = TupleDescGetAttInMetadata(tupdesc);
 		funcctx->attinmeta = attinmeta;
 
-		state = (pgp_armor_headers_state *) palloc(sizeof(pgp_armor_headers_state));
+		state = palloc_object(pgp_armor_headers_state);
 
 		res = pgp_extract_armor_headers((uint8 *) VARDATA_ANY(data),
 										VARSIZE_ANY_EXHDR(data),
diff --git a/contrib/pgcrypto/pgp-pubkey.c b/contrib/pgcrypto/pgp-pubkey.c
index 9a6561caf9d..6f118865917 100644
--- a/contrib/pgcrypto/pgp-pubkey.c
+++ b/contrib/pgcrypto/pgp-pubkey.c
@@ -39,7 +39,7 @@ pgp_key_alloc(PGP_PubKey **pk_p)
 {
 	PGP_PubKey *pk;
 
-	pk = palloc0(sizeof(*pk));
+	pk = palloc0_object(PGP_PubKey);
 	*pk_p = pk;
 	return 0;
 }
diff --git a/contrib/pgcrypto/px-hmac.c b/contrib/pgcrypto/px-hmac.c
index 99174d26551..68e5cff6d6a 100644
--- a/contrib/pgcrypto/px-hmac.c
+++ b/contrib/pgcrypto/px-hmac.c
@@ -157,7 +157,7 @@ px_find_hmac(const char *name, PX_HMAC **res)
 		return PXE_HASH_UNUSABLE_FOR_HMAC;
 	}
 
-	h = palloc(sizeof(*h));
+	h = palloc_object(PX_HMAC);
 	h->p.ipad = palloc(bs);
 	h->p.opad = palloc(bs);
 	h->md = md;
diff --git a/contrib/pgcrypto/px.c b/contrib/pgcrypto/px.c
index d35ccca7774..4d668d4e496 100644
--- a/contrib/pgcrypto/px.c
+++ b/contrib/pgcrypto/px.c
@@ -291,7 +291,7 @@ px_find_combo(const char *name, PX_Combo **res)
 
 	PX_Combo   *cx;
 
-	cx = palloc0(sizeof(*cx));
+	cx = palloc0_object(PX_Combo);
 	buf = pstrdup(name);
 
 	err = parse_cipher_name(buf, &s_cipher, &s_pad);
diff --git a/contrib/seg/seg.c b/contrib/seg/seg.c
index b5de2a5e1be..2d3a048c73e 100644
--- a/contrib/seg/seg.c
+++ b/contrib/seg/seg.c
@@ -107,7 +107,7 @@ Datum
 seg_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
-	SEG		   *result = palloc(sizeof(SEG));
+	SEG		   *result = palloc_object(SEG);
 	yyscan_t	scanner;
 
 	seg_scanner_init(str, &scanner);
@@ -370,7 +370,7 @@ gseg_picksplit(PG_FUNCTION_ARGS)
 	/*
 	 * Emit segments to the left output page, and compute its bounding box.
 	 */
-	seg_l = (SEG *) palloc(sizeof(SEG));
+	seg_l = palloc_object(SEG);
 	memcpy(seg_l, sort_items[0].data, sizeof(SEG));
 	*left++ = sort_items[0].index;
 	v->spl_nleft++;
@@ -388,7 +388,7 @@ gseg_picksplit(PG_FUNCTION_ARGS)
 	/*
 	 * Likewise for the right page.
 	 */
-	seg_r = (SEG *) palloc(sizeof(SEG));
+	seg_r = palloc_object(SEG);
 	memcpy(seg_r, sort_items[firstright].data, sizeof(SEG));
 	*right++ = sort_items[firstright].index;
 	v->spl_nright++;
@@ -632,7 +632,7 @@ seg_union(PG_FUNCTION_ARGS)
 	SEG		   *b = PG_GETARG_SEG_P(1);
 	SEG		   *n;
 
-	n = (SEG *) palloc(sizeof(*n));
+	n = palloc_object(SEG);
 
 	/* take max of upper endpoints */
 	if (a->upper > b->upper)
@@ -672,7 +672,7 @@ seg_inter(PG_FUNCTION_ARGS)
 	SEG		   *b = PG_GETARG_SEG_P(1);
 	SEG		   *n;
 
-	n = (SEG *) palloc(sizeof(*n));
+	n = palloc_object(SEG);
 
 	/* take min of upper endpoints */
 	if (a->upper < b->upper)
diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c
index a37d89a3f1c..931cd08bdad 100644
--- a/contrib/sepgsql/label.c
+++ b/contrib/sepgsql/label.c
@@ -145,7 +145,7 @@ sepgsql_set_client_label(const char *new_label)
 	 */
 	oldcxt = MemoryContextSwitchTo(CurTransactionContext);
 
-	plabel = palloc0(sizeof(pending_label));
+	plabel = palloc0_object(pending_label);
 	plabel->subid = GetCurrentSubTransactionId();
 	if (new_label)
 		plabel->label = pstrdup(new_label);
@@ -326,7 +326,7 @@ sepgsql_fmgr_hook(FmgrHookEventType event,
 				MemoryContext oldcxt;
 
 				oldcxt = MemoryContextSwitchTo(flinfo->fn_mcxt);
-				stack = palloc(sizeof(*stack));
+				stack = palloc_object(sepgsql_proc_stack);
 				stack->old_label = NULL;
 				stack->new_label = sepgsql_avc_trusted_proc(flinfo->fn_oid);
 				stack->next_private = 0;
diff --git a/contrib/sepgsql/uavc.c b/contrib/sepgsql/uavc.c
index d9ccbc38bc5..5e57971bb4d 100644
--- a/contrib/sepgsql/uavc.c
+++ b/contrib/sepgsql/uavc.c
@@ -257,7 +257,7 @@ sepgsql_avc_compute(const char *scontext, const char *tcontext, uint16 tclass)
 	 */
 	oldctx = MemoryContextSwitchTo(avc_mem_cxt);
 
-	cache = palloc0(sizeof(avc_cache));
+	cache = palloc0_object(avc_cache);
 
 	cache->hash = hash;
 	cache->scontext = pstrdup(scontext);
diff --git a/contrib/spi/refint.c b/contrib/spi/refint.c
index 89898cad7b0..fbbd558ca1e 100644
--- a/contrib/spi/refint.c
+++ b/contrib/spi/refint.c
@@ -651,7 +651,7 @@ find_plan(char *ident, EPlan **eplan, int *nplans)
 	}
 	else
 	{
-		newp = *eplan = (EPlan *) palloc(sizeof(EPlan));
+		newp = *eplan = palloc_object(EPlan);
 		(*nplans) = i = 0;
 	}
 
diff --git a/contrib/sslinfo/sslinfo.c b/contrib/sslinfo/sslinfo.c
index da702011193..2b9eb90b093 100644
--- a/contrib/sslinfo/sslinfo.c
+++ b/contrib/sslinfo/sslinfo.c
@@ -374,7 +374,7 @@ ssl_extension_info(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* Create a user function context for cross-call persistence */
-		fctx = (SSLExtensionInfoContext *) palloc(sizeof(SSLExtensionInfoContext));
+		fctx = palloc_object(SSLExtensionInfoContext);
 
 		/* Construct tuple descriptor */
 		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index 74afdc0977f..c40fd36dc96 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -207,7 +207,7 @@ normal_rand(PG_FUNCTION_ARGS)
 		funcctx->max_calls = num_tuples;
 
 		/* allocate memory for user context */
-		fctx = (normal_rand_fctx *) palloc(sizeof(normal_rand_fctx));
+		fctx = palloc_object(normal_rand_fctx);
 
 		/*
 		 * Use fctx to keep track of upper and lower bounds from call to call.
@@ -766,7 +766,7 @@ load_categories_hash(char *cats_sql, MemoryContext per_query_ctx)
 
 			SPIcontext = MemoryContextSwitchTo(per_query_ctx);
 
-			catdesc = (crosstab_cat_desc *) palloc(sizeof(crosstab_cat_desc));
+			catdesc = palloc_object(crosstab_cat_desc);
 			catdesc->catname = catname;
 			catdesc->attidx = i;
 
diff --git a/contrib/test_decoding/test_decoding.c b/contrib/test_decoding/test_decoding.c
index 36e77c69e1c..47094f86f5f 100644
--- a/contrib/test_decoding/test_decoding.c
+++ b/contrib/test_decoding/test_decoding.c
@@ -163,7 +163,7 @@ pg_decode_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 	TestDecodingData *data;
 	bool		enable_streaming = false;
 
-	data = palloc0(sizeof(TestDecodingData));
+	data = palloc0_object(TestDecodingData);
 	data->context = AllocSetContextCreate(ctx->context,
 										  "text conversion context",
 										  ALLOCSET_DEFAULT_SIZES);
diff --git a/contrib/tsm_system_rows/tsm_system_rows.c b/contrib/tsm_system_rows/tsm_system_rows.c
index f401efa2131..ef145fa6747 100644
--- a/contrib/tsm_system_rows/tsm_system_rows.c
+++ b/contrib/tsm_system_rows/tsm_system_rows.c
@@ -163,7 +163,7 @@ system_rows_samplescangetsamplesize(PlannerInfo *root,
 static void
 system_rows_initsamplescan(SampleScanState *node, int eflags)
 {
-	node->tsm_state = palloc0(sizeof(SystemRowsSamplerData));
+	node->tsm_state = palloc0_object(SystemRowsSamplerData);
 	/* Note the above leaves tsm_state->step equal to zero */
 }
 
diff --git a/contrib/tsm_system_time/tsm_system_time.c b/contrib/tsm_system_time/tsm_system_time.c
index c9c71d8c3af..1041258ea1a 100644
--- a/contrib/tsm_system_time/tsm_system_time.c
+++ b/contrib/tsm_system_time/tsm_system_time.c
@@ -179,7 +179,7 @@ system_time_samplescangetsamplesize(PlannerInfo *root,
 static void
 system_time_initsamplescan(SampleScanState *node, int eflags)
 {
-	node->tsm_state = palloc0(sizeof(SystemTimeSamplerData));
+	node->tsm_state = palloc0_object(SystemTimeSamplerData);
 	/* Note the above leaves tsm_state->step equal to zero */
 }
 
diff --git a/contrib/unaccent/unaccent.c b/contrib/unaccent/unaccent.c
index 336ba31047a..68251660887 100644
--- a/contrib/unaccent/unaccent.c
+++ b/contrib/unaccent/unaccent.c
@@ -60,7 +60,7 @@ placeChar(TrieChar *node, const unsigned char *str, int lenstr,
 	TrieChar   *curnode;
 
 	if (!node)
-		node = (TrieChar *) palloc0(sizeof(TrieChar) * 256);
+		node = palloc0_array(TrieChar, 256);
 
 	Assert(lenstr > 0);			/* else str[0] doesn't exist */
 
@@ -239,7 +239,7 @@ initTrie(const char *filename)
 				if (trgquoted && state > 0)
 				{
 					/* Ignore first and end quotes */
-					trgstore = (char *) palloc(sizeof(char) * (trglen - 2));
+					trgstore = palloc_array(char, trglen - 2);
 					trgstorelen = 0;
 					for (int i = 1; i < trglen - 1; i++)
 					{
@@ -252,7 +252,7 @@ initTrie(const char *filename)
 				}
 				else
 				{
-					trgstore = (char *) palloc(sizeof(char) * trglen);
+					trgstore = palloc_array(char, trglen);
 					trgstorelen = trglen;
 					memcpy(trgstore, trg, trgstorelen);
 				}
@@ -421,7 +421,7 @@ unaccent_lexize(PG_FUNCTION_ARGS)
 	/* return a result only if we made at least one substitution */
 	if (buf.data != NULL)
 	{
-		res = (TSLexeme *) palloc0(sizeof(TSLexeme) * 2);
+		res = palloc0_array(TSLexeme, 2);
 		res->lexeme = buf.data;
 		res->flags = TSL_FILTER;
 	}
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 4ac291c8251..662d7d02f27 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -485,8 +485,7 @@ pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
 	xmlXPathCompExprPtr comppath;
-	xpath_workspace *workspace = (xpath_workspace *)
-		palloc0(sizeof(xpath_workspace));
+	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c
index 36578b82e4d..2be87bec0cd 100644
--- a/contrib/xml2/xslt_proc.c
+++ b/contrib/xml2/xslt_proc.c
@@ -69,7 +69,7 @@ xslt_process(PG_FUNCTION_ARGS)
 	else
 	{
 		/* No parameters */
-		params = (const char **) palloc(sizeof(char *));
+		params = palloc_object(const char *);
 		params[0] = NULL;
 	}
 
diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml
index ee86e170055..5cbea8c3d55 100644
--- a/doc/src/sgml/gist.sgml
+++ b/doc/src/sgml/gist.sgml
@@ -506,11 +506,11 @@ my_compress(PG_FUNCTION_ARGS)
     if (entry-&gt;leafkey)
     {
         /* replace entry-&gt;key with a compressed version */
-        compressed_data_type *compressed_data = palloc(sizeof(compressed_data_type));
+        compressed_data_type *compressed_data = palloc_object(compressed_data_type);
 
         /* fill *compressed_data from entry-&gt;key ... */
 
-        retval = palloc(sizeof(GISTENTRY));
+        retval = palloc_object(GISTENTRY);
         gistentryinit(*retval, PointerGetDatum(compressed_data),
                       entry-&gt;rel, entry-&gt;page, entry-&gt;offset, FALSE);
     }
@@ -921,8 +921,8 @@ my_fetch(PG_FUNCTION_ARGS)
     fetched_data_type *fetched_data;
     GISTENTRY  *retval;
 
-    retval = palloc(sizeof(GISTENTRY));
-    fetched_data = palloc(sizeof(fetched_data_type));
+    retval = palloc_object(GISTENTRY);
+    fetched_data = palloc_object(fetched_data_type);
 
     /*
      * Convert 'fetched_data' into the a Datum of the original datatype.
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 537ee6fa254..2dc98df29c4 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -2491,7 +2491,7 @@ makepoint(PG_FUNCTION_ARGS)
     /* Here, the pass-by-reference nature of Point is not hidden. */
     Point     *pointx = PG_GETARG_POINT_P(0);
     Point     *pointy = PG_GETARG_POINT_P(1);
-    Point     *new_point = (Point *) palloc(sizeof(Point));
+    Point     *new_point = palloc_object(Point);
 
     new_point->x = pointx->x;
     new_point->y = pointy->y;
diff --git a/doc/src/sgml/xtypes.sgml b/doc/src/sgml/xtypes.sgml
index e67e5bdf4c4..df56d1c3ace 100644
--- a/doc/src/sgml/xtypes.sgml
+++ b/doc/src/sgml/xtypes.sgml
@@ -89,7 +89,7 @@ complex_in(PG_FUNCTION_ARGS)
                  errmsg("invalid input syntax for type %s: \"%s\"",
                         "complex", str)));
 
-    result = (Complex *) palloc(sizeof(Complex));
+    result = palloc_object(Complex);
     result->x = x;
     result->y = y;
     PG_RETURN_POINTER(result);
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index cb3331921cb..26cb75058d1 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -318,7 +318,7 @@ initialize_brin_insertstate(Relation idxRel, IndexInfo *indexInfo)
 	MemoryContext oldcxt;
 
 	oldcxt = MemoryContextSwitchTo(indexInfo->ii_Context);
-	bistate = palloc0(sizeof(BrinInsertState));
+	bistate = palloc0_object(BrinInsertState);
 	bistate->bis_desc = brin_build_desc(idxRel);
 	bistate->bis_rmAccess = brinRevmapInitialize(idxRel,
 												 &bistate->bis_pages_per_range);
@@ -1185,7 +1185,7 @@ brinbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	{
 		SortCoordinate coordinate;
 
-		coordinate = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
+		coordinate = palloc0_object(SortCoordinateData);
 		coordinate->isWorker = false;
 		coordinate->nParticipants =
 			state->bs_leader->nparticipanttuplesorts;
@@ -2384,7 +2384,7 @@ _brin_begin_parallel(BrinBuildState *buildstate, Relation heap, Relation index,
 	Size		estsort;
 	BrinShared *brinshared;
 	Sharedsort *sharedsort;
-	BrinLeader *brinleader = (BrinLeader *) palloc0(sizeof(BrinLeader));
+	BrinLeader *brinleader = palloc0_object(BrinLeader);
 	WalUsage   *walusage;
 	BufferUsage *bufferusage;
 	bool		leaderparticipates = true;
@@ -2828,7 +2828,7 @@ _brin_parallel_scan_and_build(BrinBuildState *state,
 	IndexInfo  *indexInfo;
 
 	/* Initialize local tuplesort coordination state */
-	coordinate = palloc0(sizeof(SortCoordinateData));
+	coordinate = palloc0_object(SortCoordinateData);
 	coordinate->isWorker = true;
 	coordinate->nParticipants = -1;
 	coordinate->sharedsort = sharedsort;
diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c
index f8a11444d66..0298a9da8ba 100644
--- a/src/backend/access/brin/brin_minmax_multi.c
+++ b/src/backend/access/brin/brin_minmax_multi.c
@@ -1340,7 +1340,7 @@ build_distances(FmgrInfo *distanceFn, Oid colloid,
 		return NULL;
 
 	ndistances = (neranges - 1);
-	distances = (DistanceValue *) palloc0(sizeof(DistanceValue) * ndistances);
+	distances = palloc0_array(DistanceValue, ndistances);
 
 	/*
 	 * Walk through the ranges once and compute the distance between the
@@ -1504,7 +1504,7 @@ reduce_expanded_ranges(ExpandedRange *eranges, int neranges,
 
 	/* allocate space for the boundary values */
 	nvalues = 0;
-	values = (Datum *) palloc(sizeof(Datum) * max_values);
+	values = palloc_array(Datum, max_values);
 
 	/* add the global min/max values, from the first/last range */
 	values[nvalues++] = eranges[0].minval;
diff --git a/src/backend/access/brin/brin_revmap.c b/src/backend/access/brin/brin_revmap.c
index 4e380ecc710..644f9889a8a 100644
--- a/src/backend/access/brin/brin_revmap.c
+++ b/src/backend/access/brin/brin_revmap.c
@@ -79,7 +79,7 @@ brinRevmapInitialize(Relation idxrel, BlockNumber *pagesPerRange)
 	page = BufferGetPage(meta);
 	metadata = (BrinMetaPageData *) PageGetContents(page);
 
-	revmap = palloc(sizeof(BrinRevmap));
+	revmap = palloc_object(BrinRevmap);
 	revmap->rm_irel = idxrel;
 	revmap->rm_pagesPerRange = metadata->pagesPerRange;
 	revmap->rm_lastRevmapPage = metadata->lastRevmapPage;
diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c
index 861f397e6db..4796d94da8d 100644
--- a/src/backend/access/brin/brin_tuple.c
+++ b/src/backend/access/brin/brin_tuple.c
@@ -119,13 +119,13 @@ brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno, BrinMemTuple *tuple,
 
 	Assert(brdesc->bd_totalstored > 0);
 
-	values = (Datum *) palloc(sizeof(Datum) * brdesc->bd_totalstored);
-	nulls = (bool *) palloc0(sizeof(bool) * brdesc->bd_totalstored);
+	values = palloc_array(Datum, brdesc->bd_totalstored);
+	nulls = palloc0_array(bool, brdesc->bd_totalstored);
 	phony_nullbitmap = (bits8 *)
-		palloc(sizeof(bits8) * BITMAPLEN(brdesc->bd_totalstored));
+		palloc_array(bits8, BITMAPLEN(brdesc->bd_totalstored));
 
 #ifdef TOAST_INDEX_HACK
-	untoasted_values = (Datum *) palloc(sizeof(Datum) * brdesc->bd_totalstored);
+	untoasted_values = palloc_array(Datum, brdesc->bd_totalstored);
 #endif
 
 	/*
@@ -488,9 +488,9 @@ brin_new_memtuple(BrinDesc *brdesc)
 						sizeof(BrinValues) * brdesc->bd_tupdesc->natts);
 	dtup = palloc0(basesize + sizeof(Datum) * brdesc->bd_totalstored);
 
-	dtup->bt_values = palloc(sizeof(Datum) * brdesc->bd_totalstored);
-	dtup->bt_allnulls = palloc(sizeof(bool) * brdesc->bd_tupdesc->natts);
-	dtup->bt_hasnulls = palloc(sizeof(bool) * brdesc->bd_tupdesc->natts);
+	dtup->bt_values = palloc_array(Datum, brdesc->bd_totalstored); 
+	dtup->bt_allnulls = palloc_array(bool, brdesc->bd_tupdesc->natts);
+	dtup->bt_hasnulls = palloc_array(bool, brdesc->bd_tupdesc->natts);
 
 	dtup->bt_empty_range = true;
 
diff --git a/src/backend/access/common/attmap.c b/src/backend/access/common/attmap.c
index 4901ebecef7..4cfa9ee78f9 100644
--- a/src/backend/access/common/attmap.c
+++ b/src/backend/access/common/attmap.c
@@ -41,9 +41,9 @@ make_attrmap(int maplen)
 {
 	AttrMap    *res;
 
-	res = (AttrMap *) palloc0(sizeof(AttrMap));
+	res = palloc0_object(AttrMap);
 	res->maplen = maplen;
-	res->attnums = (AttrNumber *) palloc0(sizeof(AttrNumber) * maplen);
+	res->attnums = palloc0_array(AttrNumber, maplen);
 	return res;
 }
 
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 74a52d87067..6944f70c435 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -1230,8 +1230,8 @@ heap_modify_tuple(HeapTuple tuple,
 	 * O(N^2) if there are many non-replaced columns, so it seems better to
 	 * err on the side of linear cost.
 	 */
-	values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
-	isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
+	values = palloc_array(Datum, numberOfAttributes);
+	isnull = palloc_array(bool, numberOfAttributes);
 
 	heap_deform_tuple(tuple, tupleDesc, values, isnull);
 
@@ -1292,8 +1292,8 @@ heap_modify_tuple_by_cols(HeapTuple tuple,
 	 * allocate and fill values and isnull arrays from the tuple, then replace
 	 * selected columns from the input arrays.
 	 */
-	values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
-	isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
+	values = palloc_array(Datum, numberOfAttributes);
+	isnull = palloc_array(bool, numberOfAttributes);
 
 	heap_deform_tuple(tuple, tupleDesc, values, isnull);
 
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index 9f05e1d15bd..45e77a27f42 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -71,7 +71,7 @@ typedef struct
 DestReceiver *
 printtup_create_DR(CommandDest dest)
 {
-	DR_printtup *self = (DR_printtup *) palloc0(sizeof(DR_printtup));
+	DR_printtup *self = palloc0_object(DR_printtup);
 
 	self->pub.receiveSlot = printtup;	/* might get changed later */
 	self->pub.rStartup = printtup_startup;
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 9e288dfecbf..31926d8a368 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -776,7 +776,7 @@ register_reloptions_validator(local_relopts *relopts, relopts_validator validato
 static void
 add_local_reloption(local_relopts *relopts, relopt_gen *newoption, int offset)
 {
-	local_relopt *opt = palloc(sizeof(*opt));
+	local_relopt *opt = palloc_object(local_relopt);
 
 	Assert(offset < relopts->relopt_struct_size);
 
@@ -1570,7 +1570,7 @@ static relopt_value *
 parseLocalRelOptions(local_relopts *relopts, Datum options, bool validate)
 {
 	int			nopts = list_length(relopts->options);
-	relopt_value *values = palloc(sizeof(*values) * nopts);
+	relopt_value *values = palloc_array(relopt_value, nopts);
 	ListCell   *lc;
 	int			i = 0;
 
@@ -1991,7 +1991,7 @@ void *
 build_local_reloptions(local_relopts *relopts, Datum options, bool validate)
 {
 	int			noptions = list_length(relopts->options);
-	relopt_parse_elt *elems = palloc(sizeof(*elems) * noptions);
+	relopt_parse_elt *elems = palloc_array(relopt_parse_elt, noptions);
 	relopt_value *vals;
 	void	   *opts;
 	int			i = 0;
diff --git a/src/backend/access/common/tidstore.c b/src/backend/access/common/tidstore.c
index fb807d9fe59..6fae41e7b6d 100644
--- a/src/backend/access/common/tidstore.c
+++ b/src/backend/access/common/tidstore.c
@@ -166,7 +166,7 @@ TidStoreCreateLocal(size_t max_bytes, bool insert_only)
 	size_t		minContextSize = ALLOCSET_DEFAULT_MINSIZE;
 	size_t		maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
 
-	ts = palloc0(sizeof(TidStore));
+	ts = palloc0_object(TidStore);
 
 	/* choose the maxBlockSize to be no larger than 1/16 of max_bytes */
 	while (16 * maxBlockSize > max_bytes)
@@ -212,7 +212,7 @@ TidStoreCreateShared(size_t max_bytes, int tranche_id)
 	size_t		dsa_init_size = DSA_DEFAULT_INIT_SEGMENT_SIZE;
 	size_t		dsa_max_size = DSA_MAX_SEGMENT_SIZE;
 
-	ts = palloc0(sizeof(TidStore));
+	ts = palloc0_object(TidStore);
 
 	/*
 	 * Choose the initial and maximum DSA segment sizes to be no longer than
@@ -250,7 +250,7 @@ TidStoreAttach(dsa_handle area_handle, dsa_pointer handle)
 	Assert(DsaPointerIsValid(handle));
 
 	/* create per-backend state */
-	ts = palloc0(sizeof(TidStore));
+	ts = palloc0_object(TidStore);
 
 	area = dsa_attach(area_handle);
 
@@ -472,7 +472,7 @@ TidStoreBeginIterate(TidStore *ts)
 {
 	TidStoreIter *iter;
 
-	iter = palloc0(sizeof(TidStoreIter));
+	iter = palloc0_object(TidStoreIter);
 	iter->ts = ts;
 
 	if (TidStoreIsShared(ts))
diff --git a/src/backend/access/common/toast_internals.c b/src/backend/access/common/toast_internals.c
index 63b848473f8..d06af82de15 100644
--- a/src/backend/access/common/toast_internals.c
+++ b/src/backend/access/common/toast_internals.c
@@ -568,7 +568,7 @@ toast_open_indexes(Relation toastrel,
 	*num_indexes = list_length(indexlist);
 
 	/* Open all the index relations */
-	*toastidxs = (Relation *) palloc(*num_indexes * sizeof(Relation));
+	*toastidxs = palloc_array(Relation, *num_indexes);
 	foreach(lc, indexlist)
 		(*toastidxs)[i++] = index_open(lfirst_oid(lc), lock);
 
diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c
index 1df0c2d2f98..99c197e361f 100644
--- a/src/backend/access/common/tupconvert.c
+++ b/src/backend/access/common/tupconvert.c
@@ -75,17 +75,17 @@ convert_tuples_by_position(TupleDesc indesc,
 	}
 
 	/* Prepare the map structure */
-	map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap));
+	map = palloc_object(TupleConversionMap);
 	map->indesc = indesc;
 	map->outdesc = outdesc;
 	map->attrMap = attrMap;
 	/* preallocate workspace for Datum arrays */
 	n = outdesc->natts + 1;		/* +1 for NULL */
-	map->outvalues = (Datum *) palloc(n * sizeof(Datum));
-	map->outisnull = (bool *) palloc(n * sizeof(bool));
+	map->outvalues = palloc_array(Datum, n);
+	map->outisnull = palloc_array(bool, n);
 	n = indesc->natts + 1;		/* +1 for NULL */
-	map->invalues = (Datum *) palloc(n * sizeof(Datum));
-	map->inisnull = (bool *) palloc(n * sizeof(bool));
+	map->invalues = palloc_array(Datum, n);
+	map->inisnull = palloc_array(bool, n);
 	map->invalues[0] = (Datum) 0;	/* set up the NULL entry */
 	map->inisnull[0] = true;
 
@@ -132,16 +132,16 @@ convert_tuples_by_name_attrmap(TupleDesc indesc,
 	Assert(attrMap != NULL);
 
 	/* Prepare the map structure */
-	map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap));
+	map = palloc_object(TupleConversionMap);
 	map->indesc = indesc;
 	map->outdesc = outdesc;
 	map->attrMap = attrMap;
 	/* preallocate workspace for Datum arrays */
-	map->outvalues = (Datum *) palloc(n * sizeof(Datum));
-	map->outisnull = (bool *) palloc(n * sizeof(bool));
+	map->outvalues = palloc_array(Datum, n);
+	map->outisnull = palloc_array(bool, n);
 	n = indesc->natts + 1;		/* +1 for NULL */
-	map->invalues = (Datum *) palloc(n * sizeof(Datum));
-	map->inisnull = (bool *) palloc(n * sizeof(bool));
+	map->invalues = palloc_array(Datum, n);
+	map->inisnull = palloc_array(bool, n);
 	map->invalues[0] = (Datum) 0;	/* set up the NULL entry */
 	map->inisnull[0] = true;
 
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index d715c345dd8..bcd1ddcc68b 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -361,7 +361,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
 	/* Copy the TupleConstr data structure, if any */
 	if (constr)
 	{
-		TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
+		TupleConstr *cpy = palloc0_object(TupleConstr);
 
 		cpy->has_not_null = constr->has_not_null;
 		cpy->has_generated_stored = constr->has_generated_stored;
diff --git a/src/backend/access/gin/ginbtree.c b/src/backend/access/gin/ginbtree.c
index 644d484ea53..47f881ae596 100644
--- a/src/backend/access/gin/ginbtree.c
+++ b/src/backend/access/gin/ginbtree.c
@@ -85,7 +85,7 @@ ginFindLeafPage(GinBtree btree, bool searchMode,
 {
 	GinBtreeStack *stack;
 
-	stack = (GinBtreeStack *) palloc(sizeof(GinBtreeStack));
+	stack = palloc_object(GinBtreeStack);
 	stack->blkno = btree->rootBlkno;
 	stack->buffer = ReadBuffer(btree->index, btree->rootBlkno);
 	stack->parent = NULL;
@@ -152,7 +152,7 @@ ginFindLeafPage(GinBtree btree, bool searchMode,
 		}
 		else
 		{
-			GinBtreeStack *ptr = (GinBtreeStack *) palloc(sizeof(GinBtreeStack));
+			GinBtreeStack *ptr = palloc_object(GinBtreeStack);
 
 			ptr->parent = stack;
 			stack = ptr;
@@ -246,7 +246,7 @@ ginFindParents(GinBtree btree, GinBtreeStack *stack)
 	blkno = root->blkno;
 	buffer = root->buffer;
 
-	ptr = (GinBtreeStack *) palloc(sizeof(GinBtreeStack));
+	ptr = palloc_object(GinBtreeStack);
 
 	for (;;)
 	{
diff --git a/src/backend/access/gin/ginbulk.c b/src/backend/access/gin/ginbulk.c
index 302cb2092a9..f73ee7b1fa4 100644
--- a/src/backend/access/gin/ginbulk.c
+++ b/src/backend/access/gin/ginbulk.c
@@ -93,7 +93,7 @@ ginAllocEntryAccumulator(void *arg)
 	 */
 	if (accum->entryallocator == NULL || accum->eas_used >= DEF_NENTRY)
 	{
-		accum->entryallocator = palloc(sizeof(GinEntryAccumulator) * DEF_NENTRY);
+		accum->entryallocator = palloc_array(GinEntryAccumulator, DEF_NENTRY);
 		accum->allocatedMemory += GetMemoryChunkSpace(accum->entryallocator);
 		accum->eas_used = 0;
 	}
@@ -177,8 +177,7 @@ ginInsertBAEntry(BuildAccumulator *accum,
 		ea->maxcount = DEF_NPTR;
 		ea->count = 1;
 		ea->shouldSort = false;
-		ea->list =
-			(ItemPointerData *) palloc(sizeof(ItemPointerData) * DEF_NPTR);
+		ea->list = palloc_array(ItemPointerData, DEF_NPTR);
 		ea->list[0] = *heapptr;
 		accum->allocatedMemory += GetMemoryChunkSpace(ea->list);
 	}
diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c
index ab19a854cd7..636407c4b93 100644
--- a/src/backend/access/gin/gindatapage.c
+++ b/src/backend/access/gin/gindatapage.c
@@ -1332,7 +1332,7 @@ dataSplitPageInternal(GinBtree btree, Buffer origbuf,
 static void *
 dataPrepareDownlink(GinBtree btree, Buffer lbuf)
 {
-	PostingItem *pitem = palloc(sizeof(PostingItem));
+	PostingItem *pitem = palloc_object(PostingItem);
 	Page		lpage = BufferGetPage(lbuf);
 
 	PostingItemSetBlockNumber(pitem, BufferGetBlockNumber(lbuf));
@@ -1374,7 +1374,7 @@ disassembleLeaf(Page page)
 	Pointer		segbegin;
 	Pointer		segend;
 
-	leaf = palloc0(sizeof(disassembledLeaf));
+	leaf = palloc0_object(disassembledLeaf);
 	dlist_init(&leaf->segments);
 
 	if (GinPageIsCompressed(page))
@@ -1387,7 +1387,7 @@ disassembleLeaf(Page page)
 		segend = segbegin + GinDataLeafPageGetPostingListSize(page);
 		while ((Pointer) seg < segend)
 		{
-			leafSegmentInfo *seginfo = palloc(sizeof(leafSegmentInfo));
+			leafSegmentInfo *seginfo = palloc_object(leafSegmentInfo);
 
 			seginfo->action = GIN_SEGMENT_UNMODIFIED;
 			seginfo->seg = seg;
@@ -1414,7 +1414,7 @@ disassembleLeaf(Page page)
 
 		if (nuncompressed > 0)
 		{
-			seginfo = palloc(sizeof(leafSegmentInfo));
+			seginfo = palloc_object(leafSegmentInfo);
 
 			seginfo->action = GIN_SEGMENT_REPLACE;
 			seginfo->seg = NULL;
@@ -1455,7 +1455,7 @@ addItemsToLeaf(disassembledLeaf *leaf, ItemPointer newItems, int nNewItems)
 	 */
 	if (dlist_is_empty(&leaf->segments))
 	{
-		newseg = palloc(sizeof(leafSegmentInfo));
+		newseg = palloc_object(leafSegmentInfo);
 		newseg->seg = NULL;
 		newseg->items = newItems;
 		newseg->nitems = nNewItems;
@@ -1512,7 +1512,7 @@ addItemsToLeaf(disassembledLeaf *leaf, ItemPointer newItems, int nNewItems)
 			cur->seg != NULL &&
 			SizeOfGinPostingList(cur->seg) >= GinPostingListSegmentTargetSize)
 		{
-			newseg = palloc(sizeof(leafSegmentInfo));
+			newseg = palloc_object(leafSegmentInfo);
 			newseg->seg = NULL;
 			newseg->items = nextnew;
 			newseg->nitems = nthis;
@@ -1629,7 +1629,7 @@ leafRepackItems(disassembledLeaf *leaf, ItemPointer remaining)
 					if (seginfo->action != GIN_SEGMENT_INSERT)
 						seginfo->action = GIN_SEGMENT_REPLACE;
 
-					nextseg = palloc(sizeof(leafSegmentInfo));
+					nextseg = palloc_object(leafSegmentInfo);
 					nextseg->action = GIN_SEGMENT_INSERT;
 					nextseg->seg = NULL;
 					nextseg->items = &seginfo->items[npacked];
diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c
index c0592367700..63413afa00b 100644
--- a/src/backend/access/gin/ginentrypage.c
+++ b/src/backend/access/gin/ginentrypage.c
@@ -183,7 +183,7 @@ ginReadTuple(GinState *ginstate, OffsetNumber attnum, IndexTuple itup,
 	}
 	else
 	{
-		ipd = (ItemPointer) palloc(sizeof(ItemPointerData) * nipd);
+		ipd = palloc_array(ItemPointerData, nipd);
 		memcpy(ipd, ptr, sizeof(ItemPointerData) * nipd);
 	}
 	*nitems = nipd;
@@ -708,7 +708,7 @@ entryPrepareDownlink(GinBtree btree, Buffer lbuf)
 
 	itup = getRightMostTuple(lpage);
 
-	insertData = palloc(sizeof(GinBtreeEntryInsertData));
+	insertData = palloc_object(GinBtreeEntryInsertData);
 	insertData->entry = GinFormInteriorTuple(itup, lpage, lblkno);
 	insertData->isDelete = false;
 
diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 0d4108d05a3..b3e2e9d5f6e 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -552,7 +552,7 @@ startScanKey(GinState *ginstate, GinScanOpaque so, GinScanKey key)
 	{
 		MemoryContextSwitchTo(so->tempCtx);
 
-		entryIndexes = (int *) palloc(sizeof(int) * key->nentries);
+		entryIndexes = palloc_array(int, key->nentries);
 		for (i = 0; i < key->nentries; i++)
 			entryIndexes[i] = i;
 		qsort_arg(entryIndexes, key->nentries, sizeof(int),
@@ -1873,7 +1873,7 @@ scanPendingInsert(IndexScanDesc scan, TIDBitmap *tbm, int64 *ntids)
 	LockBuffer(pos.pendingBuffer, GIN_SHARE);
 	pos.firstOffset = FirstOffsetNumber;
 	UnlockReleaseBuffer(metabuffer);
-	pos.hasMatchKey = palloc(sizeof(bool) * so->nkeys);
+	pos.hasMatchKey = palloc_array(bool, so->nkeys);
 
 	/*
 	 * loop for each heap row. scanGetCandidate returns full row or row's
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index f87c60a230c..df30dcc0228 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -707,7 +707,7 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	{
 		SortCoordinate coordinate;
 
-		coordinate = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
+		coordinate = palloc0_object(SortCoordinateData);
 		coordinate->isWorker = false;
 		coordinate->nParticipants =
 			state->bs_leader->nparticipanttuplesorts;
@@ -791,7 +791,7 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	/*
 	 * Return statistics
 	 */
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 
 	result->heap_tuples = reltuples;
 	result->index_tuples = buildstate.indtuples;
@@ -867,7 +867,7 @@ gininsert(Relation index, Datum *values, bool *isnull,
 	if (ginstate == NULL)
 	{
 		oldCtx = MemoryContextSwitchTo(indexInfo->ii_Context);
-		ginstate = (GinState *) palloc(sizeof(GinState));
+		ginstate = palloc_object(GinState);
 		initGinState(ginstate, index);
 		indexInfo->ii_AmCache = ginstate;
 		MemoryContextSwitchTo(oldCtx);
@@ -934,7 +934,7 @@ _gin_begin_parallel(GinBuildState *buildstate, Relation heap, Relation index,
 	Size		estsort;
 	GinBuildShared *ginshared;
 	Sharedsort *sharedsort;
-	GinLeader  *ginleader = (GinLeader *) palloc0(sizeof(GinLeader));
+	GinLeader  *ginleader = palloc0_object(GinLeader);
 	WalUsage   *walusage;
 	BufferUsage *bufferusage;
 	bool		leaderparticipates = true;
@@ -1259,7 +1259,7 @@ AssertCheckGinBuffer(GinBuffer *buffer)
 static GinBuffer *
 GinBufferInit(Relation index)
 {
-	GinBuffer  *buffer = palloc0(sizeof(GinBuffer));
+	GinBuffer  *buffer = palloc0_object(GinBuffer);
 	int			i,
 				nKeys;
 	TupleDesc	desc = RelationGetDescr(index);
@@ -1273,7 +1273,7 @@ GinBufferInit(Relation index)
 
 	nKeys = IndexRelationGetNumberOfKeyAttributes(index);
 
-	buffer->ssup = palloc0(sizeof(SortSupportData) * nKeys);
+	buffer->ssup = palloc0_array(SortSupportData, nKeys);
 
 	/*
 	 * Lookup ordering operator for the index key data type, and initialize
@@ -2030,7 +2030,7 @@ _gin_parallel_scan_and_build(GinBuildState *state,
 	IndexInfo  *indexInfo;
 
 	/* Initialize local tuplesort coordination state */
-	coordinate = palloc0(sizeof(SortCoordinateData));
+	coordinate = palloc0_object(SortCoordinateData);
 	coordinate->isWorker = true;
 	coordinate->nParticipants = -1;
 	coordinate->sharedsort = sharedsort;
@@ -2279,7 +2279,7 @@ _gin_build_tuple(OffsetNumber attrnum, unsigned char category,
 	while (ncompressed < nitems)
 	{
 		int			cnt;
-		GinSegmentInfo *seginfo = palloc(sizeof(GinSegmentInfo));
+		GinSegmentInfo *seginfo = palloc_object(GinSegmentInfo);
 
 		seginfo->seg = ginCompressPostingList(&items[ncompressed],
 											  (nitems - ncompressed),
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 26081693383..2ca635909f9 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -33,7 +33,7 @@ ginbeginscan(Relation rel, int nkeys, int norderbys)
 	scan = RelationGetIndexScan(rel, nkeys, norderbys);
 
 	/* allocate private workspace */
-	so = (GinScanOpaque) palloc(sizeof(GinScanOpaqueData));
+	so = (GinScanOpaque) palloc_object(GinScanOpaqueData);
 	so->keys = NULL;
 	so->nkeys = 0;
 	so->tempCtx = AllocSetContextCreate(CurrentMemoryContext,
@@ -98,7 +98,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	}
 
 	/* Nope, create a new entry */
-	scanEntry = (GinScanEntry) palloc(sizeof(GinScanEntryData));
+	scanEntry = palloc_object(GinScanEntryData);
 	scanEntry->queryKey = queryKey;
 	scanEntry->queryCategory = queryCategory;
 	scanEntry->isPartialMatch = isPartialMatch;
@@ -123,8 +123,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
 	if (so->totalentries >= so->allocentries)
 	{
 		so->allocentries *= 2;
-		so->entries = (GinScanEntry *)
-			repalloc(so->entries, so->allocentries * sizeof(GinScanEntry));
+		so->entries = repalloc_array(so->entries, GinScanEntry, so->allocentries);
 	}
 	so->entries[so->totalentries++] = scanEntry;
 
@@ -170,10 +169,8 @@ ginFillScanKey(GinScanOpaque so, OffsetNumber attnum,
 	key->nuserentries = nQueryValues;
 
 	/* Allocate one extra array slot for possible "hidden" entry */
-	key->scanEntry = (GinScanEntry *) palloc(sizeof(GinScanEntry) *
-											 (nQueryValues + 1));
-	key->entryRes = (GinTernaryValue *) palloc0(sizeof(GinTernaryValue) *
-												(nQueryValues + 1));
+	key->scanEntry = palloc_array(GinScanEntry, nQueryValues + 1);
+	key->entryRes = palloc0_array(GinTernaryValue, nQueryValues + 1);
 
 	key->query = query;
 	key->queryValues = queryValues;
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index 78f7b7a2495..605f80aad39 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -500,9 +500,9 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 	if (isNull)
 	{
 		*nentries = 1;
-		entries = (Datum *) palloc(sizeof(Datum));
+		entries = palloc_object(Datum);
 		entries[0] = (Datum) 0;
-		*categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
+		*categories = palloc_object(GinNullCategory);
 		(*categories)[0] = GIN_CAT_NULL_ITEM;
 		return entries;
 	}
@@ -522,9 +522,9 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 	if (entries == NULL || *nentries <= 0)
 	{
 		*nentries = 1;
-		entries = (Datum *) palloc(sizeof(Datum));
+		entries = palloc_object(Datum);
 		entries[0] = (Datum) 0;
-		*categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
+		*categories = palloc_object(GinNullCategory);
 		(*categories)[0] = GIN_CAT_EMPTY_ITEM;
 		return entries;
 	}
@@ -548,7 +548,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 		keyEntryData *keydata;
 		cmpEntriesArg arg;
 
-		keydata = (keyEntryData *) palloc(*nentries * sizeof(keyEntryData));
+		keydata = palloc_array(keyEntryData, *nentries);
 		for (i = 0; i < *nentries; i++)
 		{
 			keydata[i].datum = entries[i];
diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c
index 2237efa50bb..d7baf7c847c 100644
--- a/src/backend/access/gin/ginvacuum.c
+++ b/src/backend/access/gin/ginvacuum.c
@@ -65,7 +65,7 @@ ginVacuumItemPointers(GinVacuumState *gvs, ItemPointerData *items,
 				 * First TID to be deleted: allocate memory to hold the
 				 * remaining items.
 				 */
-				tmpitems = palloc(sizeof(ItemPointerData) * nitem);
+				tmpitems = palloc_array(ItemPointerData, nitem);
 				memcpy(tmpitems, items, sizeof(ItemPointerData) * i);
 			}
 		}
@@ -260,7 +260,7 @@ ginScanToDelete(GinVacuumState *gvs, BlockNumber blkno, bool isRoot,
 	{
 		if (!parent->child)
 		{
-			me = (DataPageDeleteStack *) palloc0(sizeof(DataPageDeleteStack));
+			me = palloc0_object(DataPageDeleteStack);
 			me->parent = parent;
 			parent->child = me;
 			me->leftBuffer = InvalidBuffer;
@@ -584,7 +584,7 @@ ginbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 	if (stats == NULL)
 	{
 		/* Yes, so initialize stats to zeroes */
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 
 		/*
 		 * and cleanup any pending inserts
@@ -714,7 +714,7 @@ ginvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 	 */
 	if (stats == NULL)
 	{
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 		initGinState(&ginstate, index);
 		ginInsertCleanup(&ginstate, !AmAutoVacuumWorkerProcess(),
 						 false, true, stats);
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 3fb1a1285c5..c26d8538f05 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -43,7 +43,7 @@ static void gistprunepage(Relation rel, Page page, Buffer buffer,
 
 
 #define ROTATEDIST(d) do { \
-	SplitPageLayout *tmp = (SplitPageLayout *) palloc0(sizeof(SplitPageLayout)); \
+	SplitPageLayout *tmp = palloc0_object(SplitPageLayout); \
 	tmp->block.blkno = InvalidBlockNumber;	\
 	tmp->buffer = InvalidBuffer;	\
 	tmp->next = (d); \
@@ -392,7 +392,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 			/* Prepare a vector of all the downlinks */
 			for (ptr = dist; ptr; ptr = ptr->next)
 				ndownlinks++;
-			downlinks = palloc(sizeof(IndexTuple) * ndownlinks);
+			downlinks = palloc_array(IndexTuple, ndownlinks);
 			for (i = 0, ptr = dist; ptr; ptr = ptr->next)
 				downlinks[i++] = ptr->itup;
 
@@ -410,7 +410,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 			/* Prepare split-info to be returned to caller */
 			for (ptr = dist; ptr; ptr = ptr->next)
 			{
-				GISTPageSplitInfo *si = palloc(sizeof(GISTPageSplitInfo));
+				GISTPageSplitInfo *si = palloc_object(GISTPageSplitInfo);
 
 				si->buf = ptr->buffer;
 				si->downlink = ptr->itup;
@@ -823,7 +823,7 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace,
 			xlocked = false;
 
 			/* descend to the chosen child */
-			item = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));
+			item = palloc0_object(GISTInsertStack);
 			item->blkno = childblkno;
 			item->parent = stack;
 			item->downlinkoffnum = downlinkoffnum;
@@ -923,7 +923,7 @@ gistFindPath(Relation r, BlockNumber child, OffsetNumber *downlinkoffnum)
 			   *ptr;
 	BlockNumber blkno;
 
-	top = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));
+	top = palloc0_object(GISTInsertStack);
 	top->blkno = GIST_ROOT_BLKNO;
 	top->downlinkoffnum = InvalidOffsetNumber;
 
@@ -975,7 +975,7 @@ gistFindPath(Relation r, BlockNumber child, OffsetNumber *downlinkoffnum)
 			 * leaf pages, and we assume that there can't be any non-leaf
 			 * pages behind leaf pages.
 			 */
-			ptr = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));
+			ptr = palloc0_object(GISTInsertStack);
 			ptr->blkno = GistPageGetOpaque(page)->rightlink;
 			ptr->downlinkoffnum = InvalidOffsetNumber;
 			ptr->parent = top->parent;
@@ -1000,7 +1000,7 @@ gistFindPath(Relation r, BlockNumber child, OffsetNumber *downlinkoffnum)
 			else
 			{
 				/* Append this child to the list of pages to visit later */
-				ptr = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack));
+				ptr = palloc0_object(GISTInsertStack);
 				ptr->blkno = blkno;
 				ptr->downlinkoffnum = i;
 				ptr->parent = top;
@@ -1218,7 +1218,7 @@ gistfixsplit(GISTInsertState *state, GISTSTATE *giststate)
 	 */
 	for (;;)
 	{
-		GISTPageSplitInfo *si = palloc(sizeof(GISTPageSplitInfo));
+		GISTPageSplitInfo *si = palloc_object(GISTPageSplitInfo);
 		IndexTuple	downlink;
 
 		page = BufferGetPage(buf);
@@ -1482,8 +1482,8 @@ gistSplit(Relation r,
 	gistSplitByKey(r, page, itup, len, giststate, &v, 0);
 
 	/* form left and right vector */
-	lvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (len + 1));
-	rvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (len + 1));
+	lvectup = palloc_array(IndexTuple, len + 1);
+	rvectup = palloc_array(IndexTuple, len + 1);
 
 	for (i = 0; i < v.splitVector.spl_nleft; i++)
 		lvectup[i] = itup[v.splitVector.spl_left[i] - 1];
@@ -1552,7 +1552,7 @@ initGISTstate(Relation index)
 	oldCxt = MemoryContextSwitchTo(scanCxt);
 
 	/* Create and fill in the GISTSTATE */
-	giststate = (GISTSTATE *) palloc(sizeof(GISTSTATE));
+	giststate = palloc_object(GISTSTATE);
 
 	giststate->scanCxt = scanCxt;
 	giststate->tempCxt = scanCxt;	/* caller must change this if needed */
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index be0fd5b753d..b9fa196149d 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -346,7 +346,7 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	/*
 	 * Return statistics
 	 */
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 
 	result->heap_tuples = reltuples;
 	result->index_tuples = (double) buildstate.indtuples;
@@ -409,7 +409,7 @@ gist_indexsortbuild(GISTBuildState *state)
 	state->bulkstate = smgr_bulk_start_rel(state->indexrel, MAIN_FORKNUM);
 
 	/* Allocate a temporary buffer for the first leaf page batch. */
-	levelstate = palloc0(sizeof(GistSortedBuildLevelState));
+	levelstate = palloc0_object(GistSortedBuildLevelState);
 	levelstate->pages[0] = palloc(BLCKSZ);
 	levelstate->parent = NULL;
 	gistinitpage(levelstate->pages[0], F_LEAF);
@@ -526,7 +526,7 @@ gist_indexsortbuild_levelstate_flush(GISTBuildState *state,
 	else
 	{
 		/* Create split layout from single page */
-		dist = (SplitPageLayout *) palloc0(sizeof(SplitPageLayout));
+		dist = palloc0_object(SplitPageLayout);
 		union_tuple = gistunion(state->indexrel, itvec, vect_len,
 								state->giststate);
 		dist->itup = union_tuple;
@@ -597,7 +597,7 @@ gist_indexsortbuild_levelstate_flush(GISTBuildState *state,
 		parent = levelstate->parent;
 		if (parent == NULL)
 		{
-			parent = palloc0(sizeof(GistSortedBuildLevelState));
+			parent = palloc0_object(GistSortedBuildLevelState);
 			parent->pages[0] = palloc(BLCKSZ);
 			parent->parent = NULL;
 			gistinitpage(parent->pages[0], 0);
@@ -1154,7 +1154,7 @@ gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer, int level,
 
 		/* Create an array of all the downlink tuples */
 		ndownlinks = list_length(splitinfo);
-		downlinks = (IndexTuple *) palloc(sizeof(IndexTuple) * ndownlinks);
+		downlinks = palloc_array(IndexTuple, ndownlinks);
 		i = 0;
 		foreach(lc, splitinfo)
 		{
diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c
index 0707254d18e..d49b920760a 100644
--- a/src/backend/access/gist/gistbuildbuffers.c
+++ b/src/backend/access/gist/gistbuildbuffers.c
@@ -46,7 +46,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
 	GISTBuildBuffers *gfbb;
 	HASHCTL		hashCtl;
 
-	gfbb = palloc(sizeof(GISTBuildBuffers));
+	gfbb = palloc_object(GISTBuildBuffers);
 	gfbb->pagesPerBuffer = pagesPerBuffer;
 	gfbb->levelStep = levelStep;
 
@@ -60,7 +60,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
 	/* Initialize free page management. */
 	gfbb->nFreeBlocks = 0;
 	gfbb->freeBlocksLen = 32;
-	gfbb->freeBlocks = (long *) palloc(gfbb->freeBlocksLen * sizeof(long));
+	gfbb->freeBlocks = palloc_array(long, gfbb->freeBlocksLen);
 
 	/*
 	 * Current memory context will be used for all in-memory data structures
@@ -87,8 +87,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
 	 * buffers are inserted here when they are created.
 	 */
 	gfbb->buffersOnLevelsLen = 1;
-	gfbb->buffersOnLevels = (List **) palloc(sizeof(List *) *
-											 gfbb->buffersOnLevelsLen);
+	gfbb->buffersOnLevels = (List **) palloc_array(List *, gfbb->buffersOnLevelsLen);
 	gfbb->buffersOnLevels[0] = NIL;
 
 	/*
@@ -96,8 +95,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
 	 * into main memory.
 	 */
 	gfbb->loadedBuffersLen = 32;
-	gfbb->loadedBuffers = (GISTNodeBuffer **) palloc(gfbb->loadedBuffersLen *
-													 sizeof(GISTNodeBuffer *));
+	gfbb->loadedBuffers = (GISTNodeBuffer **) palloc_array(GISTNodeBuffer *, gfbb->loadedBuffersLen);
 	gfbb->loadedBuffersCount = 0;
 
 	gfbb->rootlevel = maxLevel;
@@ -582,9 +580,7 @@ gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb, GISTSTATE *giststate,
 	 * Allocate memory for information about relocation buffers.
 	 */
 	splitPagesCount = list_length(splitinfo);
-	relocationBuffersInfos =
-		(RelocationBufferInfo *) palloc(sizeof(RelocationBufferInfo) *
-										splitPagesCount);
+	relocationBuffersInfos = palloc_array(RelocationBufferInfo, splitPagesCount);
 
 	/*
 	 * Fill relocation buffers information for node buffers of pages produced
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index f2ec6cbe2e5..9ac06504be1 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -171,7 +171,7 @@ gist_box_union(PG_FUNCTION_ARGS)
 			   *pageunion;
 
 	numranges = entryvec->n;
-	pageunion = (BOX *) palloc(sizeof(BOX));
+	pageunion = palloc_object(BOX);
 	cur = DatumGetBoxP(entryvec->vector[0].key);
 	memcpy(pageunion, cur, sizeof(BOX));
 
@@ -237,7 +237,7 @@ fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
 			v->spl_left[v->spl_nleft] = i;
 			if (unionL == NULL)
 			{
-				unionL = (BOX *) palloc(sizeof(BOX));
+				unionL = palloc_object(BOX);
 				*unionL = *cur;
 			}
 			else
@@ -250,7 +250,7 @@ fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
 			v->spl_right[v->spl_nright] = i;
 			if (unionR == NULL)
 			{
-				unionR = (BOX *) palloc(sizeof(BOX));
+				unionR = palloc_object(BOX);
 				*unionR = *cur;
 			}
 			else
@@ -698,8 +698,8 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
 	v->spl_nright = 0;
 
 	/* Allocate bounding boxes of left and right groups */
-	leftBox = palloc0(sizeof(BOX));
-	rightBox = palloc0(sizeof(BOX));
+	leftBox = palloc0_object(BOX);
+	rightBox = palloc0_object(BOX);
 
 	/*
 	 * Allocate an array for "common entries" - entries which can be placed to
@@ -1042,10 +1042,10 @@ gist_poly_compress(PG_FUNCTION_ARGS)
 		POLYGON    *in = DatumGetPolygonP(entry->key);
 		BOX		   *r;
 
-		r = (BOX *) palloc(sizeof(BOX));
+		r = palloc_object(BOX);
 		memcpy(r, &(in->boundbox), sizeof(BOX));
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -1107,13 +1107,13 @@ gist_circle_compress(PG_FUNCTION_ARGS)
 		CIRCLE	   *in = DatumGetCircleP(entry->key);
 		BOX		   *r;
 
-		r = (BOX *) palloc(sizeof(BOX));
+		r = palloc_object(BOX);
 		r->high.x = float8_pl(in->center.x, in->radius);
 		r->low.x = float8_mi(in->center.x, in->radius);
 		r->high.y = float8_pl(in->center.y, in->radius);
 		r->low.y = float8_mi(in->center.y, in->radius);
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -1171,9 +1171,9 @@ gist_point_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)			/* Point, actually */
 	{
-		BOX		   *box = palloc(sizeof(BOX));
+		BOX		   *box = palloc_object(BOX);
 		Point	   *point = DatumGetPointP(entry->key);
-		GISTENTRY  *retval = palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		box->high = box->low = *point;
 
@@ -1200,9 +1200,9 @@ gist_point_fetch(PG_FUNCTION_ARGS)
 	Point	   *r;
 	GISTENTRY  *retval;
 
-	retval = palloc(sizeof(GISTENTRY));
+	retval = palloc_object(GISTENTRY);
 
-	r = (Point *) palloc(sizeof(Point));
+	r = palloc_object(Point);
 	r->x = in->high.x;
 	r->y = in->high.y;
 	gistentryinit(*retval, PointerGetDatum(r),
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 700fa959d03..01b8ff0b6fa 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -90,7 +90,7 @@ gistbeginscan(Relation r, int nkeys, int norderbys)
 	oldCxt = MemoryContextSwitchTo(giststate->scanCxt);
 
 	/* initialize opaque data */
-	so = (GISTScanOpaque) palloc0(sizeof(GISTScanOpaqueData));
+	so = palloc0_object(GISTScanOpaqueData);
 	so->giststate = giststate;
 	giststate->tempCxt = createTempGistContext();
 	so->queue = NULL;
@@ -101,8 +101,8 @@ gistbeginscan(Relation r, int nkeys, int norderbys)
 	so->qual_ok = true;			/* in case there are zero keys */
 	if (scan->numberOfOrderBys > 0)
 	{
-		scan->xs_orderbyvals = palloc0(sizeof(Datum) * scan->numberOfOrderBys);
-		scan->xs_orderbynulls = palloc(sizeof(bool) * scan->numberOfOrderBys);
+		scan->xs_orderbyvals = palloc0_array(Datum, scan->numberOfOrderBys);
+		scan->xs_orderbynulls = palloc_array(bool, scan->numberOfOrderBys);
 		memset(scan->xs_orderbynulls, true, sizeof(bool) * scan->numberOfOrderBys);
 	}
 
diff --git a/src/backend/access/gist/gistsplit.c b/src/backend/access/gist/gistsplit.c
index 49838ceb07b..5b3c67dbf3a 100644
--- a/src/backend/access/gist/gistsplit.c
+++ b/src/backend/access/gist/gistsplit.c
@@ -51,7 +51,7 @@ gistunionsubkeyvec(GISTSTATE *giststate, IndexTuple *itvec,
 	int			i,
 				cleanedLen = 0;
 
-	cleanedItVec = (IndexTuple *) palloc(sizeof(IndexTuple) * gsvp->len);
+	cleanedItVec = palloc_array(IndexTuple, gsvp->len);
 
 	for (i = 0; i < gsvp->len; i++)
 	{
@@ -501,7 +501,7 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
 		 * Locate don't-care tuples, if any.  If there are none, the split is
 		 * optimal, so just fall out and return false.
 		 */
-		v->spl_dontcare = (bool *) palloc0(sizeof(bool) * (entryvec->n + 1));
+		v->spl_dontcare = palloc0_array(bool, entryvec->n + 1);
 
 		NumDontCare = findDontCares(r, giststate, entryvec->vector, v, attno);
 
@@ -738,9 +738,9 @@ gistSplitByKey(Relation r, Page page, IndexTuple *itup, int len,
 				 * call will overwrite that with its own result.
 				 */
 				backupSplit = v->splitVector;
-				backupSplit.spl_left = (OffsetNumber *) palloc(sizeof(OffsetNumber) * len);
+				backupSplit.spl_left = palloc_array(OffsetNumber, len);
 				memcpy(backupSplit.spl_left, v->splitVector.spl_left, sizeof(OffsetNumber) * v->splitVector.spl_nleft);
-				backupSplit.spl_right = (OffsetNumber *) palloc(sizeof(OffsetNumber) * len);
+				backupSplit.spl_right = palloc_array(OffsetNumber, len);	
 				memcpy(backupSplit.spl_right, v->splitVector.spl_right, sizeof(OffsetNumber) * v->splitVector.spl_nright);
 
 				/* Recursively decide how to split the don't-care tuples */
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 75272827837..a346a85adcb 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -100,7 +100,7 @@ gistextractpage(Page page, int *len /* out */ )
 
 	maxoff = PageGetMaxOffsetNumber(page);
 	*len = maxoff;
-	itvec = palloc(sizeof(IndexTuple) * maxoff);
+	itvec = palloc_array(IndexTuple, maxoff);
 	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
 		itvec[i - FirstOffsetNumber] = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));
 
@@ -113,7 +113,7 @@ gistextractpage(Page page, int *len /* out */ )
 IndexTuple *
 gistjoinvector(IndexTuple *itvec, int *len, IndexTuple *additvec, int addlen)
 {
-	itvec = (IndexTuple *) repalloc(itvec, sizeof(IndexTuple) * ((*len) + addlen));
+	itvec = repalloc_array(itvec, IndexTuple, (*len) + addlen);
 	memmove(&itvec[*len], additvec, sizeof(IndexTuple) * addlen);
 	*len += addlen;
 	return itvec;
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index b925eda2b9b..7591ad4da1a 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -61,7 +61,7 @@ gistbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 {
 	/* allocate stats if first time through, else re-use existing struct */
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 
 	gistvacuumscan(info, stats, callback, callback_state);
 
@@ -85,7 +85,7 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 	 */
 	if (stats == NULL)
 	{
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 		gistvacuumscan(info, stats, NULL, NULL);
 	}
 
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 53061c819fb..e388252afdc 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -193,7 +193,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	/*
 	 * Return statistics
 	 */
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 
 	result->heap_tuples = reltuples;
 	result->index_tuples = buildstate.indtuples;
@@ -318,8 +318,7 @@ hashgettuple(IndexScanDesc scan, ScanDirection dir)
 			 * entries.
 			 */
 			if (so->killedItems == NULL)
-				so->killedItems = (int *)
-					palloc(MaxIndexTuplesPerPage * sizeof(int));
+				so->killedItems = palloc_array(int, MaxIndexTuplesPerPage);
 
 			if (so->numKilled < MaxIndexTuplesPerPage)
 				so->killedItems[so->numKilled++] = so->currPos.itemIndex;
@@ -381,7 +380,7 @@ hashbeginscan(Relation rel, int nkeys, int norderbys)
 
 	scan = RelationGetIndexScan(rel, nkeys, norderbys);
 
-	so = (HashScanOpaque) palloc(sizeof(HashScanOpaqueData));
+	so = (HashScanOpaque) palloc_object(HashScanOpaqueData);
 	HashScanPosInvalidate(so->currPos);
 	so->hashso_bucket_buf = InvalidBuffer;
 	so->hashso_split_bucket_buf = InvalidBuffer;
@@ -633,7 +632,7 @@ loop_top:
 
 	/* return statistics */
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 	stats->estimated_count = false;
 	stats->num_index_tuples = num_index_tuples;
 	stats->tuples_removed += tuples_removed;
diff --git a/src/backend/access/hash/hashsort.c b/src/backend/access/hash/hashsort.c
index 92ae3cf53f5..0fd41f4f4ca 100644
--- a/src/backend/access/hash/hashsort.c
+++ b/src/backend/access/hash/hashsort.c
@@ -59,7 +59,7 @@ struct HSpool
 HSpool *
 _h_spoolinit(Relation heap, Relation index, uint32 num_buckets)
 {
-	HSpool	   *hspool = (HSpool *) palloc0(sizeof(HSpool));
+	HSpool	   *hspool = palloc0_object(HSpool);
 
 	hspool->index = index;
 
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4d382a04338..225f9829f22 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1133,7 +1133,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	 */
 	if (flags & SO_TYPE_BITMAPSCAN)
 	{
-		BitmapHeapScanDesc bscan = palloc(sizeof(BitmapHeapScanDescData));
+		BitmapHeapScanDesc bscan = palloc_object(BitmapHeapScanDescData);
 
 		/*
 		 * Bitmap Heap scans do not have any fields that a normal Heap Scan
@@ -1142,7 +1142,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 		scan = (HeapScanDesc) bscan;
 	}
 	else
-		scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData));
+		scan = (HeapScanDesc) palloc_object(HeapScanDescData);
 
 	scan->rs_base.rs_rd = relation;
 	scan->rs_base.rs_snapshot = snapshot;
@@ -1201,7 +1201,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	 * when doing a parallel scan.
 	 */
 	if (parallel_scan != NULL)
-		scan->rs_parallelworkerdata = palloc(sizeof(ParallelBlockTableScanWorkerData));
+		scan->rs_parallelworkerdata = palloc_object(ParallelBlockTableScanWorkerData);
 	else
 		scan->rs_parallelworkerdata = NULL;
 
@@ -1210,7 +1210,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	 * initscan() and we don't want to allocate memory again
 	 */
 	if (nkeys > 0)
-		scan->rs_base.rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
+		scan->rs_base.rs_key = palloc_array(ScanKeyData, nkeys);
 	else
 		scan->rs_base.rs_key = NULL;
 
@@ -2037,7 +2037,7 @@ GetBulkInsertState(void)
 {
 	BulkInsertState bistate;
 
-	bistate = (BulkInsertState) palloc(sizeof(BulkInsertStateData));
+	bistate = (BulkInsertState) palloc_object(BulkInsertStateData);
 	bistate->strategy = GetAccessStrategy(BAS_BULKWRITE);
 	bistate->current_buf = InvalidBuffer;
 	bistate->next_free = InvalidBlockNumber;
@@ -6895,7 +6895,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
 	 * even member XIDs >= OldestXmin often won't be kept by second pass.
 	 */
 	nnewmembers = 0;
-	newmembers = palloc(sizeof(MultiXactMember) * nmembers);
+	newmembers = palloc_array(MultiXactMember, nmembers);
 	has_lockers = false;
 	update_xid = InvalidTransactionId;
 	update_committed = false;
@@ -8711,7 +8711,7 @@ bottomup_sort_and_shrink(TM_IndexDeleteOp *delstate)
 	Assert(delstate->ndeltids > 0);
 
 	/* Calculate per-heap-block count of TIDs */
-	blockgroups = palloc(sizeof(IndexDeleteCounts) * delstate->ndeltids);
+	blockgroups = palloc_array(IndexDeleteCounts, delstate->ndeltids);
 	for (int i = 0; i < delstate->ndeltids; i++)
 	{
 		TM_IndexDelete *ideltid = &delstate->deltids[i];
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index bcbac844bb6..dd4fe6bf62f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -81,7 +81,7 @@ heapam_slot_callbacks(Relation relation)
 static IndexFetchTableData *
 heapam_index_fetch_begin(Relation rel)
 {
-	IndexFetchHeapData *hscan = palloc0(sizeof(IndexFetchHeapData));
+	IndexFetchHeapData *hscan = palloc0_object(IndexFetchHeapData);
 
 	hscan->xs_base.rel = rel;
 	hscan->xs_cbuf = InvalidBuffer;
@@ -717,8 +717,8 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 
 	/* Preallocate values/isnull arrays */
 	natts = newTupDesc->natts;
-	values = (Datum *) palloc(natts * sizeof(Datum));
-	isnull = (bool *) palloc(natts * sizeof(bool));
+	values = palloc_array(Datum, natts);
+	isnull = palloc_array(bool, natts);
 
 	/* Initialize the rewrite operation */
 	rwstate = begin_heap_rewrite(OldHeap, NewHeap, OldestXmin, *xid_cutoff,
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 66ab48f0fe0..7ce3c5e2685 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -249,7 +249,7 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm
 	old_cxt = MemoryContextSwitchTo(rw_cxt);
 
 	/* Create and fill in the state struct */
-	state = palloc0(sizeof(RewriteStateData));
+	state = palloc0_object(RewriteStateData);
 
 	state->rs_old_rel = old_heap;
 	state->rs_new_rel = new_heap;
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 65bb0568a86..91e0b8c8a71 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -677,7 +677,7 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	 * of each rel.  It's convenient for code in lazy_scan_heap to always use
 	 * these temp copies.
 	 */
-	vacrel = (LVRelState *) palloc0(sizeof(LVRelState));
+	vacrel = palloc0_object(LVRelState);
 	vacrel->dbname = get_database_name(MyDatabaseId);
 	vacrel->relnamespace = get_namespace_name(RelationGetNamespace(rel));
 	vacrel->relname = pstrdup(RelationGetRelationName(rel));
@@ -697,7 +697,7 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	if (instrument && vacrel->nindexes > 0)
 	{
 		/* Copy index names used by instrumentation (not error reporting) */
-		indnames = palloc(sizeof(char *) * vacrel->nindexes);
+		indnames = palloc_array(char *, vacrel->nindexes);
 		for (int i = 0; i < vacrel->nindexes; i++)
 			indnames[i] = pstrdup(RelationGetRelationName(vacrel->indrels[i]));
 	}
@@ -3567,7 +3567,7 @@ dead_items_alloc(LVRelState *vacrel, int nworkers)
 	 * locally.
 	 */
 
-	dead_items_info = (VacDeadItemsInfo *) palloc(sizeof(VacDeadItemsInfo));
+	dead_items_info = palloc_object(VacDeadItemsInfo);
 	dead_items_info->max_bytes = vac_work_mem * (Size) 1024;
 	dead_items_info->num_items = 0;
 	vacrel->dead_items_info = dead_items_info;
diff --git a/src/backend/access/index/amvalidate.c b/src/backend/access/index/amvalidate.c
index 4cf237019ad..8d7e7171bd7 100644
--- a/src/backend/access/index/amvalidate.c
+++ b/src/backend/access/index/amvalidate.c
@@ -118,7 +118,7 @@ identify_opfamily_groups(CatCList *oprlist, CatCList *proclist)
 		}
 
 		/* Time for a new group */
-		thisgroup = (OpFamilyOpFuncGroup *) palloc(sizeof(OpFamilyOpFuncGroup));
+		thisgroup = palloc_object(OpFamilyOpFuncGroup);
 		if (oprform &&
 			(!procform ||
 			 (oprform->amoplefttype < procform->amproclefttype ||
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index 0cb27af1310..1e9eadb723e 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -81,7 +81,7 @@ RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
 {
 	IndexScanDesc scan;
 
-	scan = (IndexScanDesc) palloc(sizeof(IndexScanDescData));
+	scan = (IndexScanDesc) palloc_object(IndexScanDescData);
 
 	scan->heapRelation = NULL;	/* may be set later */
 	scan->xs_heapfetch = NULL;
@@ -94,11 +94,11 @@ RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
 	 * We allocate key workspace here, but it won't get filled until amrescan.
 	 */
 	if (nkeys > 0)
-		scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
+		scan->keyData = palloc_array(ScanKeyData, nkeys); 
 	else
 		scan->keyData = NULL;
 	if (norderbys > 0)
-		scan->orderByData = (ScanKey) palloc(sizeof(ScanKeyData) * norderbys);
+		scan->orderByData = palloc_array(ScanKeyData, norderbys);
 	else
 		scan->orderByData = NULL;
 
@@ -310,8 +310,8 @@ index_compute_xid_horizon_for_tuples(Relation irel,
 	delstate.bottomup = false;
 	delstate.bottomupfreespace = 0;
 	delstate.ndeltids = 0;
-	delstate.deltids = palloc(nitems * sizeof(TM_IndexDelete));
-	delstate.status = palloc(nitems * sizeof(TM_IndexStatus));
+	delstate.deltids = palloc_array(TM_IndexDelete, nitems);
+	delstate.status = palloc_array(TM_IndexStatus, nitems);
 
 	/* identify what the index tuples about to be deleted point to */
 	for (int i = 0; i < nitems; i++)
@@ -401,7 +401,7 @@ systable_beginscan(Relation heapRelation,
 	else
 		irel = NULL;
 
-	sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData));
+	sysscan = (SysScanDesc) palloc_object(SysScanDescData);
 
 	sysscan->heap_rel = heapRelation;
 	sysscan->irel = irel;
@@ -667,7 +667,7 @@ systable_beginscan_ordered(Relation heapRelation,
 		elog(WARNING, "using index \"%s\" despite IgnoreSystemIndexes",
 			 RelationGetRelationName(indexRelation));
 
-	sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData));
+	sysscan = (SysScanDesc) palloc_object(SysScanDescData);
 
 	sysscan->heap_rel = heapRelation;
 	sysscan->irel = indexRelation;
diff --git a/src/backend/access/nbtree/nbtdedup.c b/src/backend/access/nbtree/nbtdedup.c
index a746de45dd3..ec07ea3d123 100644
--- a/src/backend/access/nbtree/nbtdedup.c
+++ b/src/backend/access/nbtree/nbtdedup.c
@@ -82,7 +82,7 @@ _bt_dedup_pass(Relation rel, Buffer buf, IndexTuple newitem, Size newitemsz,
 	 * That ought to leave us with a good split point when pages full of
 	 * duplicates can be split several times.
 	 */
-	state = (BTDedupState) palloc(sizeof(BTDedupStateData));
+	state = (BTDedupState) palloc_object(BTDedupStateData);
 	state->deduplicate = true;
 	state->nmaxitems = 0;
 	state->maxpostingsize = Min(BTMaxItemSize / 2, INDEX_SIZE_MASK);
@@ -321,7 +321,7 @@ _bt_bottomupdel_pass(Relation rel, Buffer buf, Relation heapRel,
 	newitemsz += sizeof(ItemIdData);
 
 	/* Initialize deduplication state */
-	state = (BTDedupState) palloc(sizeof(BTDedupStateData));
+	state = (BTDedupState) palloc_object(BTDedupStateData);
 	state->deduplicate = true;
 	state->nmaxitems = 0;
 	state->maxpostingsize = BLCKSZ; /* We're not really deduplicating */
@@ -355,8 +355,8 @@ _bt_bottomupdel_pass(Relation rel, Buffer buf, Relation heapRel,
 	delstate.bottomup = true;
 	delstate.bottomupfreespace = Max(BLCKSZ / 16, newitemsz);
 	delstate.ndeltids = 0;
-	delstate.deltids = palloc(MaxTIDsPerBTreePage * sizeof(TM_IndexDelete));
-	delstate.status = palloc(MaxTIDsPerBTreePage * sizeof(TM_IndexStatus));
+	delstate.deltids = palloc_array(TM_IndexDelete, MaxTIDsPerBTreePage);
+	delstate.status = palloc_array(TM_IndexStatus, MaxTIDsPerBTreePage);
 
 	minoff = P_FIRSTDATAKEY(opaque);
 	maxoff = PageGetMaxOffsetNumber(page);
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 3a4b791f2ab..031eb76ba8c 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -2963,7 +2963,7 @@ _bt_deadblocks(Page page, OffsetNumber *deletable, int ndeletable,
 	 */
 	spacentids = ndeletable + 1;
 	ntids = 0;
-	tidblocks = (BlockNumber *) palloc(sizeof(BlockNumber) * spacentids);
+	tidblocks = palloc_array(BlockNumber, spacentids);
 
 	/*
 	 * First add the table block for the incoming newitem.  This is the one
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index a8d56fe5a7c..cfb07b2bca9 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -2982,7 +2982,7 @@ _bt_pendingfsm_init(Relation rel, BTVacState *vstate, bool cleanuponly)
 	vstate->maxbufsize = (int) maxbufsize;
 
 	/* Allocate buffer, indicate that there are currently 0 pending pages */
-	vstate->pendingpages = palloc(sizeof(BTPendingFSM) * vstate->bufsize);
+	vstate->pendingpages = palloc_array(BTPendingFSM, vstate->bufsize);
 	vstate->npendingpages = 0;
 }
 
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index fdff960c130..c87e4cfa42f 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -260,8 +260,7 @@ btgettuple(IndexScanDesc scan, ScanDirection dir)
 				 * just forget any excess entries.
 				 */
 				if (so->killedItems == NULL)
-					so->killedItems = (int *)
-						palloc(MaxTIDsPerBTreePage * sizeof(int));
+					so->killedItems = palloc_array(int, MaxTIDsPerBTreePage);
 				if (so->numKilled < MaxTIDsPerBTreePage)
 					so->killedItems[so->numKilled++] = so->currPos.itemIndex;
 			}
@@ -345,7 +344,7 @@ btbeginscan(Relation rel, int nkeys, int norderbys)
 	scan = RelationGetIndexScan(rel, nkeys, norderbys);
 
 	/* allocate private workspace */
-	so = (BTScanOpaque) palloc(sizeof(BTScanOpaqueData));
+	so = (BTScanOpaque) palloc_object(BTScanOpaqueData);
 	BTScanPosInvalidate(so->currPos);
 	BTScanPosInvalidate(so->markPos);
 	if (scan->numberOfKeys > 0)
@@ -1070,7 +1069,7 @@ btbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 
 	/* allocate stats if first time through, else re-use existing struct */
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 
 	/* Establish the vacuum cycle ID to use for this scan */
 	/* The ENSURE stuff ensures we clean up shared memory on failure */
@@ -1131,7 +1130,7 @@ btvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 		 * We handle the problem by making num_index_tuples an estimate in
 		 * cleanup-only case.
 		 */
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 		btvacuumscan(info, stats, NULL, NULL, 0);
 		stats->estimated_count = true;
 	}
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index 0605356ec9f..2b34e7eecfc 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -169,7 +169,7 @@ _bt_search(Relation rel, Relation heaprel, BTScanInsert key, Buffer *bufP,
 		 * page one level down, it usually ends up inserting a new pivot
 		 * tuple/downlink immediately after the location recorded here.
 		 */
-		new_stack = (BTStack) palloc(sizeof(BTStackData));
+		new_stack = (BTStack) palloc_object(BTStackData);
 		new_stack->bts_blkno = BufferGetBlockNumber(*bufP);
 		new_stack->bts_offset = offnum;
 		new_stack->bts_parent = stack_in;
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 454adaee7dc..bf70bf209a5 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -335,7 +335,7 @@ btbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	if (buildstate.btleader)
 		_bt_end_parallel(buildstate.btleader);
 
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 
 	result->heap_tuples = reltuples;
 	result->index_tuples = buildstate.indtuples;
@@ -366,7 +366,7 @@ static double
 _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
 					IndexInfo *indexInfo)
 {
-	BTSpool    *btspool = (BTSpool *) palloc0(sizeof(BTSpool));
+	BTSpool    *btspool = palloc0_object(BTSpool);
 	SortCoordinate coordinate = NULL;
 	double		reltuples = 0;
 
@@ -399,7 +399,7 @@ _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
 	 */
 	if (buildstate->btleader)
 	{
-		coordinate = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
+		coordinate = (SortCoordinate) palloc0_object(SortCoordinateData);
 		coordinate->isWorker = false;
 		coordinate->nParticipants =
 			buildstate->btleader->nparticipanttuplesorts;
@@ -440,7 +440,7 @@ _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
 	 */
 	if (indexInfo->ii_Unique)
 	{
-		BTSpool    *btspool2 = (BTSpool *) palloc0(sizeof(BTSpool));
+		BTSpool    *btspool2 = palloc0_object(BTSpool);
 		SortCoordinate coordinate2 = NULL;
 
 		/* Initialize secondary spool */
@@ -457,7 +457,7 @@ _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
 			 * tuplesort_begin_index_btree() about the basic high level
 			 * coordination of a parallel sort.
 			 */
-			coordinate2 = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
+			coordinate2 = (SortCoordinate) palloc0_object(SortCoordinateData);
 			coordinate2->isWorker = false;
 			coordinate2->nParticipants =
 				buildstate->btleader->nparticipanttuplesorts;
@@ -648,7 +648,7 @@ _bt_blwritepage(BTWriteState *wstate, BulkWriteBuffer buf, BlockNumber blkno)
 static BTPageState *
 _bt_pagestate(BTWriteState *wstate, uint32 level)
 {
-	BTPageState *state = (BTPageState *) palloc0(sizeof(BTPageState));
+	BTPageState *state = palloc0_object(BTPageState);
 
 	/* create initial page for level */
 	state->btps_buf = _bt_blnewpage(wstate, level);
@@ -1002,7 +1002,7 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, IndexTuple itup,
 	if (last_off == P_HIKEY)
 	{
 		Assert(state->btps_lowkey == NULL);
-		state->btps_lowkey = palloc0(sizeof(IndexTupleData));
+		state->btps_lowkey = palloc0_object(IndexTupleData);
 		state->btps_lowkey->t_info = sizeof(IndexTupleData);
 		BTreeTupleSetNAtts(state->btps_lowkey, 0, false);
 	}
@@ -1164,7 +1164,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
 		itup2 = tuplesort_getindextuple(btspool2->sortstate, true);
 
 		/* Prepare SortSupport data for each column */
-		sortKeys = (SortSupport) palloc0(keysz * sizeof(SortSupportData));
+		sortKeys = (SortSupport) palloc0_array(SortSupportData, keysz);
 
 		for (i = 0; i < keysz; i++)
 		{
@@ -1266,7 +1266,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
 		/* merge is unnecessary, deduplicate into posting lists */
 		BTDedupState dstate;
 
-		dstate = (BTDedupState) palloc(sizeof(BTDedupStateData));
+		dstate = (BTDedupState) palloc_object(BTDedupStateData);
 		dstate->deduplicate = true; /* unused */
 		dstate->nmaxitems = 0;	/* unused */
 		dstate->maxpostingsize = 0; /* set later */
@@ -1404,7 +1404,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
 	Sharedsort *sharedsort;
 	Sharedsort *sharedsort2;
 	BTSpool    *btspool = buildstate->spool;
-	BTLeader   *btleader = (BTLeader *) palloc0(sizeof(BTLeader));
+	BTLeader   *btleader = palloc0_object(BTLeader);
 	WalUsage   *walusage;
 	BufferUsage *bufferusage;
 	bool		leaderparticipates = true;
@@ -1693,7 +1693,7 @@ _bt_leader_participate_as_worker(BTBuildState *buildstate)
 	int			sortmem;
 
 	/* Allocate memory and initialize private spool */
-	leaderworker = (BTSpool *) palloc0(sizeof(BTSpool));
+	leaderworker = palloc0_object(BTSpool);
 	leaderworker->heap = buildstate->spool->heap;
 	leaderworker->index = buildstate->spool->index;
 	leaderworker->isunique = buildstate->spool->isunique;
@@ -1705,7 +1705,7 @@ _bt_leader_participate_as_worker(BTBuildState *buildstate)
 	else
 	{
 		/* Allocate memory for worker's own private secondary spool */
-		leaderworker2 = (BTSpool *) palloc0(sizeof(BTSpool));
+		leaderworker2 = palloc0_object(BTSpool);
 
 		/* Initialize worker's own secondary spool */
 		leaderworker2->heap = leaderworker->heap;
@@ -1796,7 +1796,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
 	indexRel = index_open(btshared->indexrelid, indexLockmode);
 
 	/* Initialize worker's own spool */
-	btspool = (BTSpool *) palloc0(sizeof(BTSpool));
+	btspool = palloc0_object(BTSpool);
 	btspool->heap = heapRel;
 	btspool->index = indexRel;
 	btspool->isunique = btshared->isunique;
@@ -1813,7 +1813,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
 	else
 	{
 		/* Allocate memory for worker's own private secondary spool */
-		btspool2 = (BTSpool *) palloc0(sizeof(BTSpool));
+		btspool2 = palloc0_object(BTSpool);
 
 		/* Initialize worker's own secondary spool */
 		btspool2->heap = btspool->heap;
@@ -1874,7 +1874,7 @@ _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2,
 	IndexInfo  *indexInfo;
 
 	/* Initialize local tuplesort coordination state */
-	coordinate = palloc0(sizeof(SortCoordinateData));
+	coordinate = palloc0_object(SortCoordinateData);
 	coordinate->isWorker = true;
 	coordinate->nParticipants = -1;
 	coordinate->sharedsort = sharedsort;
@@ -1901,7 +1901,7 @@ _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2,
 		 * worker).  Worker processes are generally permitted to allocate
 		 * work_mem independently.
 		 */
-		coordinate2 = palloc0(sizeof(SortCoordinateData));
+		coordinate2 = palloc0_object(SortCoordinateData);
 		coordinate2->isWorker = true;
 		coordinate2->nParticipants = -1;
 		coordinate2->sharedsort = sharedsort2;
diff --git a/src/backend/access/nbtree/nbtsplitloc.c b/src/backend/access/nbtree/nbtsplitloc.c
index f0082f88c76..651ab013025 100644
--- a/src/backend/access/nbtree/nbtsplitloc.c
+++ b/src/backend/access/nbtree/nbtsplitloc.c
@@ -197,7 +197,7 @@ _bt_findsplitloc(Relation rel,
 	 * between tuples will be legal).
 	 */
 	state.maxsplits = maxoff;
-	state.splits = palloc(sizeof(SplitPoint) * state.maxsplits);
+	state.splits = palloc_array(SplitPoint, state.maxsplits);
 	state.nsplits = 0;
 
 	/*
diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c
index d4a26de06a3..dbe67c166fd 100644
--- a/src/backend/access/nbtree/nbtxlog.c
+++ b/src/backend/access/nbtree/nbtxlog.c
@@ -469,7 +469,7 @@ btree_xlog_dedup(XLogReaderState *record)
 		BTDedupInterval *intervals;
 		Page		newpage;
 
-		state = (BTDedupState) palloc(sizeof(BTDedupStateData));
+		state = palloc_object(BTDedupStateData);
 		state->deduplicate = true;	/* unused */
 		state->nmaxitems = 0;	/* unused */
 		/* Conservatively use larger maxpostingsize than primary */
diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c
index 4eadb518776..1e1e61d2044 100644
--- a/src/backend/access/spgist/spgdoinsert.c
+++ b/src/backend/access/spgist/spgdoinsert.c
@@ -89,7 +89,7 @@ addNode(SpGistState *state, SpGistInnerTuple tuple, Datum label, int offset)
 	else if (offset > tuple->nNodes)
 		elog(ERROR, "invalid offset for adding node to SPGiST inner tuple");
 
-	nodes = palloc(sizeof(SpGistNodeTuple) * (tuple->nNodes + 1));
+	nodes = palloc_array(SpGistNodeTuple, tuple->nNodes + 1);
 	SGITITERATE(tuple, i, node)
 	{
 		if (i < offset)
@@ -409,8 +409,8 @@ moveLeafs(Relation index, SpGistState *state,
 
 	/* Locate the tuples to be moved, and count up the space needed */
 	i = PageGetMaxOffsetNumber(current->page);
-	toDelete = (OffsetNumber *) palloc(sizeof(OffsetNumber) * i);
-	toInsert = (OffsetNumber *) palloc(sizeof(OffsetNumber) * (i + 1));
+	toDelete = palloc_array(OffsetNumber, i);
+	toInsert = palloc_array(OffsetNumber, i + 1);
 
 	size = newLeafTuple->size + sizeof(ItemIdData);
 
@@ -634,7 +634,7 @@ checkAllTheSame(spgPickSplitIn *in, spgPickSplitOut *out, bool tooBig,
 	{
 		Datum		theLabel = out->nodeLabels[theNode];
 
-		out->nodeLabels = (Datum *) palloc(sizeof(Datum) * out->nNodes);
+		out->nodeLabels = palloc_array(Datum, out->nNodes);
 		for (i = 0; i < out->nNodes; i++)
 			out->nodeLabels[i] = theLabel;
 	}
@@ -717,12 +717,12 @@ doPickSplit(Relation index, SpGistState *state,
 	 */
 	max = PageGetMaxOffsetNumber(current->page);
 	n = max + 1;
-	in.datums = (Datum *) palloc(sizeof(Datum) * n);
-	toDelete = (OffsetNumber *) palloc(sizeof(OffsetNumber) * n);
-	toInsert = (OffsetNumber *) palloc(sizeof(OffsetNumber) * n);
-	oldLeafs = (SpGistLeafTuple *) palloc(sizeof(SpGistLeafTuple) * n);
-	newLeafs = (SpGistLeafTuple *) palloc(sizeof(SpGistLeafTuple) * n);
-	leafPageSelect = (uint8 *) palloc(sizeof(uint8) * n);
+	in.datums = palloc_array(Datum, n);
+	toDelete = palloc_array(OffsetNumber, n);
+	toInsert = palloc_array(OffsetNumber, n);
+	oldLeafs = palloc_array(SpGistLeafTuple, n);
+	newLeafs = palloc_array(SpGistLeafTuple, n);
+	leafPageSelect = palloc_array(uint8, n);
 
 	STORE_STATE(state, xlrec.stateSrc);
 
@@ -858,7 +858,7 @@ doPickSplit(Relation index, SpGistState *state,
 		out.hasPrefix = false;
 		out.nNodes = 1;
 		out.nodeLabels = NULL;
-		out.mapTuplesToNodes = palloc0(sizeof(int) * in.nTuples);
+		out.mapTuplesToNodes = palloc0_array(int, in.nTuples);
 
 		/*
 		 * Form new leaf tuples and count up the total space needed.
@@ -914,8 +914,8 @@ doPickSplit(Relation index, SpGistState *state,
 	 * out.nNodes with a value larger than the number of tuples on the input
 	 * page, we can't allocate these arrays before here.
 	 */
-	nodes = (SpGistNodeTuple *) palloc(sizeof(SpGistNodeTuple) * out.nNodes);
-	leafSizes = (int *) palloc0(sizeof(int) * out.nNodes);
+	nodes = palloc_array(SpGistNodeTuple, out.nNodes);
+	leafSizes = palloc0_array(int, out.nNodes);
 
 	/*
 	 * Form nodes of inner tuple and inner tuple itself
@@ -1054,7 +1054,7 @@ doPickSplit(Relation index, SpGistState *state,
 		 * do so, even if totalLeafSizes is less than the available space,
 		 * because we can't split a group across pages.
 		 */
-		nodePageSelect = (uint8 *) palloc(sizeof(uint8) * out.nNodes);
+		nodePageSelect = palloc_array(uint8, out.nNodes);
 
 		curspace = currentFreeSpace;
 		newspace = PageGetExactFreeSpace(BufferGetPage(newLeafBuffer));
@@ -1740,8 +1740,7 @@ spgSplitNodeAction(Relation index, SpGistState *state,
 	 * Construct new prefix tuple with requested number of nodes.  We'll fill
 	 * in the childNodeN'th node's downlink below.
 	 */
-	nodes = (SpGistNodeTuple *) palloc(sizeof(SpGistNodeTuple) *
-									   out->result.splitTuple.prefixNNodes);
+	nodes = palloc_array(SpGistNodeTuple, out->result.splitTuple.prefixNNodes);
 
 	for (i = 0; i < out->result.splitTuple.prefixNNodes; i++)
 	{
@@ -1769,7 +1768,7 @@ spgSplitNodeAction(Relation index, SpGistState *state,
 	 * same node datums, but with the prefix specified by the picksplit
 	 * function.
 	 */
-	nodes = palloc(sizeof(SpGistNodeTuple) * innerTuple->nNodes);
+	nodes = palloc_array(SpGistNodeTuple, innerTuple->nNodes);
 	SGITITERATE(innerTuple, i, node)
 	{
 		nodes[i] = node;
diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c
index 6a61e093fa0..dda99755f66 100644
--- a/src/backend/access/spgist/spginsert.c
+++ b/src/backend/access/spgist/spginsert.c
@@ -140,7 +140,7 @@ spgbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 						  true);
 	}
 
-	result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
+	result = palloc0_object(IndexBuildResult);
 	result->heap_tuples = reltuples;
 	result->index_tuples = buildstate.indtuples;
 
diff --git a/src/backend/access/spgist/spgkdtreeproc.c b/src/backend/access/spgist/spgkdtreeproc.c
index d6989759e5f..f0167d6ffa6 100644
--- a/src/backend/access/spgist/spgkdtreeproc.c
+++ b/src/backend/access/spgist/spgkdtreeproc.c
@@ -114,7 +114,7 @@ spg_kd_picksplit(PG_FUNCTION_ARGS)
 	SortedPoint *sorted;
 	double		coord;
 
-	sorted = palloc(sizeof(*sorted) * in->nTuples);
+	sorted = palloc_array(SortedPoint, in->nTuples);
 	for (i = 0; i < in->nTuples; i++)
 	{
 		sorted[i].p = DatumGetPointP(in->datums[i]);
@@ -132,8 +132,8 @@ spg_kd_picksplit(PG_FUNCTION_ARGS)
 	out->nNodes = 2;
 	out->nodeLabels = NULL;		/* we don't need node labels */
 
-	out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	/*
 	 * Note: points that have coordinates exactly equal to coord may get
@@ -259,7 +259,7 @@ spg_kd_inner_consistent(PG_FUNCTION_ARGS)
 	if (!which)
 		PG_RETURN_VOID();
 
-	out->nodeNumbers = (int *) palloc(sizeof(int) * 2);
+	out->nodeNumbers = palloc_array(int, 2);
 
 	/*
 	 * When ordering scan keys are specified, we've to calculate distance for
@@ -273,8 +273,8 @@ spg_kd_inner_consistent(PG_FUNCTION_ARGS)
 		BOX			infArea;
 		BOX		   *area;
 
-		out->distances = (double **) palloc(sizeof(double *) * in->nNodes);
-		out->traversalValues = (void **) palloc(sizeof(void *) * in->nNodes);
+		out->distances = palloc_array(double *, in->nNodes);
+		out->traversalValues = palloc_array(void *, in->nNodes);
 
 		if (in->level == 0)
 		{
@@ -335,7 +335,7 @@ spg_kd_inner_consistent(PG_FUNCTION_ARGS)
 	}
 
 	/* Set up level increments, too */
-	out->levelAdds = (int *) palloc(sizeof(int) * 2);
+	out->levelAdds = palloc_array(int, 2);
 	out->levelAdds[0] = 1;
 	out->levelAdds[1] = 1;
 
diff --git a/src/backend/access/spgist/spgproc.c b/src/backend/access/spgist/spgproc.c
index 722c17ce2e5..e169c60a463 100644
--- a/src/backend/access/spgist/spgproc.c
+++ b/src/backend/access/spgist/spgproc.c
@@ -64,7 +64,7 @@ spg_key_orderbys_distances(Datum key, bool isLeaf,
 						   ScanKey orderbys, int norderbys)
 {
 	int			sk_num;
-	double	   *distances = (double *) palloc(norderbys * sizeof(double)),
+	double	   *distances = palloc_array(double, norderbys),
 			   *distance = distances;
 
 	for (sk_num = 0; sk_num < norderbys; ++sk_num, ++orderbys, ++distance)
@@ -81,7 +81,7 @@ spg_key_orderbys_distances(Datum key, bool isLeaf,
 BOX *
 box_copy(BOX *orig)
 {
-	BOX		   *result = palloc(sizeof(BOX));
+	BOX		   *result = palloc_object(BOX);
 
 	*result = *orig;
 	return result;
diff --git a/src/backend/access/spgist/spgquadtreeproc.c b/src/backend/access/spgist/spgquadtreeproc.c
index 3e8cfa1709a..75ffb09ca5a 100644
--- a/src/backend/access/spgist/spgquadtreeproc.c
+++ b/src/backend/access/spgist/spgquadtreeproc.c
@@ -82,7 +82,7 @@ getQuadrant(Point *centroid, Point *tst)
 static BOX *
 getQuadrantArea(BOX *bbox, Point *centroid, int quadrant)
 {
-	BOX		   *result = (BOX *) palloc(sizeof(BOX));
+	BOX		   *result = palloc_object(BOX);
 
 	switch (quadrant)
 	{
@@ -177,11 +177,11 @@ spg_quad_picksplit(PG_FUNCTION_ARGS)
 	/* Use the median values of x and y as the centroid point */
 	Point	  **sorted;
 
-	sorted = palloc(sizeof(*sorted) * in->nTuples);
+	sorted = palloc_array(Point *, in->nTuples);
 	for (i = 0; i < in->nTuples; i++)
 		sorted[i] = DatumGetPointP(in->datums[i]);
 
-	centroid = palloc(sizeof(*centroid));
+	centroid = palloc_object(Point);
 
 	qsort(sorted, in->nTuples, sizeof(*sorted), x_cmp);
 	centroid->x = sorted[in->nTuples >> 1]->x;
@@ -189,7 +189,7 @@ spg_quad_picksplit(PG_FUNCTION_ARGS)
 	centroid->y = sorted[in->nTuples >> 1]->y;
 #else
 	/* Use the average values of x and y as the centroid point */
-	centroid = palloc0(sizeof(*centroid));
+	centroid = palloc0_object(Point);
 
 	for (i = 0; i < in->nTuples; i++)
 	{
@@ -207,8 +207,8 @@ spg_quad_picksplit(PG_FUNCTION_ARGS)
 	out->nNodes = 4;
 	out->nodeLabels = NULL;		/* we don't need node labels */
 
-	out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	for (i = 0; i < in->nTuples; i++)
 	{
@@ -246,8 +246,8 @@ spg_quad_inner_consistent(PG_FUNCTION_ARGS)
 	 */
 	if (in->norderbys > 0)
 	{
-		out->distances = (double **) palloc(sizeof(double *) * in->nNodes);
-		out->traversalValues = (void **) palloc(sizeof(void *) * in->nNodes);
+		out->distances = palloc_array(double *, in->nNodes);
+		out->traversalValues = palloc_array(void *, in->nNodes);
 
 		if (in->level == 0)
 		{
@@ -270,7 +270,7 @@ spg_quad_inner_consistent(PG_FUNCTION_ARGS)
 	{
 		/* Report that all nodes should be visited */
 		out->nNodes = in->nNodes;
-		out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
+		out->nodeNumbers = palloc_array(int, in->nNodes);
 		for (i = 0; i < in->nNodes; i++)
 		{
 			out->nodeNumbers[i] = i;
@@ -368,12 +368,12 @@ spg_quad_inner_consistent(PG_FUNCTION_ARGS)
 			break;				/* no need to consider remaining conditions */
 	}
 
-	out->levelAdds = palloc(sizeof(int) * 4);
+	out->levelAdds = palloc_array(int, 4);
 	for (i = 0; i < 4; ++i)
 		out->levelAdds[i] = 1;
 
 	/* We must descend into the quadrant(s) identified by which */
-	out->nodeNumbers = (int *) palloc(sizeof(int) * 4);
+	out->nodeNumbers = palloc_array(int, 4);
 	out->nNodes = 0;
 
 	for (i = 1; i <= 4; i++)
diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c
index 25893050c58..05b3799e0e2 100644
--- a/src/backend/access/spgist/spgscan.c
+++ b/src/backend/access/spgist/spgscan.c
@@ -309,9 +309,9 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
 
 	scan = RelationGetIndexScan(rel, keysz, orderbysz);
 
-	so = (SpGistScanOpaque) palloc0(sizeof(SpGistScanOpaqueData));
+	so = palloc0_object(SpGistScanOpaqueData);
 	if (keysz > 0)
-		so->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * keysz);
+		so->keyData = palloc_array(ScanKeyData, keysz);
 	else
 		so->keyData = NULL;
 	initSpGistState(&so->state, scan->indexRelation);
@@ -336,16 +336,12 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
 	if (scan->numberOfOrderBys > 0)
 	{
 		/* This will be filled in spgrescan, but allocate the space here */
-		so->orderByTypes = (Oid *)
-			palloc(sizeof(Oid) * scan->numberOfOrderBys);
-		so->nonNullOrderByOffsets = (int *)
-			palloc(sizeof(int) * scan->numberOfOrderBys);
+		so->orderByTypes = palloc_array(Oid, scan->numberOfOrderBys);
+		so->nonNullOrderByOffsets = palloc_array(int, scan->numberOfOrderBys);
 
 		/* These arrays have constant contents, so we can fill them now */
-		so->zeroDistances = (double *)
-			palloc(sizeof(double) * scan->numberOfOrderBys);
-		so->infDistances = (double *)
-			palloc(sizeof(double) * scan->numberOfOrderBys);
+		so->zeroDistances = palloc_array(double, scan->numberOfOrderBys);
+		so->infDistances = palloc_array(double, scan->numberOfOrderBys);
 
 		for (i = 0; i < scan->numberOfOrderBys; i++)
 		{
@@ -353,10 +349,8 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
 			so->infDistances[i] = get_float8_infinity();
 		}
 
-		scan->xs_orderbyvals = (Datum *)
-			palloc0(sizeof(Datum) * scan->numberOfOrderBys);
-		scan->xs_orderbynulls = (bool *)
-			palloc(sizeof(bool) * scan->numberOfOrderBys);
+		scan->xs_orderbyvals = palloc0_array(Datum, scan->numberOfOrderBys);
+		scan->xs_orderbynulls = palloc_array(bool, scan->numberOfOrderBys);
 		memset(scan->xs_orderbynulls, true,
 			   sizeof(bool) * scan->numberOfOrderBys);
 	}
@@ -690,7 +684,7 @@ spgInnerTest(SpGistScanOpaque so, SpGistSearchItem *item,
 	{
 		/* force all children to be visited */
 		out.nNodes = nNodes;
-		out.nodeNumbers = (int *) palloc(sizeof(int) * nNodes);
+		out.nodeNumbers = palloc_array(int, nNodes);
 		for (i = 0; i < nNodes; i++)
 			out.nodeNumbers[i] = i;
 	}
@@ -703,7 +697,7 @@ spgInnerTest(SpGistScanOpaque so, SpGistSearchItem *item,
 	{
 		/* collect node pointers */
 		SpGistNodeTuple node;
-		SpGistNodeTuple *nodes = (SpGistNodeTuple *) palloc(sizeof(SpGistNodeTuple) * nNodes);
+		SpGistNodeTuple *nodes = palloc_array(SpGistNodeTuple, nNodes);
 
 		SGITITERATE(innerTuple, i, node)
 		{
@@ -972,8 +966,7 @@ storeGettuple(SpGistScanOpaque so, ItemPointer heapPtr,
 			so->distances[so->nPtrs] = NULL;
 		else
 		{
-			IndexOrderByDistance *distances =
-				palloc(sizeof(distances[0]) * so->numberOfOrderBys);
+			IndexOrderByDistance *distances = palloc_array(IndexOrderByDistance, so->numberOfOrderBys);
 			int			i;
 
 			for (i = 0; i < so->numberOfOrderBys; i++)
diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c
index 91f4ab260c2..09be7ffe47e 100644
--- a/src/backend/access/spgist/spgtextproc.c
+++ b/src/backend/access/spgist/spgtextproc.c
@@ -230,8 +230,7 @@ spg_text_choose(PG_FUNCTION_ARGS)
 					formTextDatum(prefixStr, commonLen);
 			}
 			out->result.splitTuple.prefixNNodes = 1;
-			out->result.splitTuple.prefixNodeLabels =
-				(Datum *) palloc(sizeof(Datum));
+			out->result.splitTuple.prefixNodeLabels = palloc_object(Datum);
 			out->result.splitTuple.prefixNodeLabels[0] =
 				Int16GetDatum(*(unsigned char *) (prefixStr + commonLen));
 
@@ -303,7 +302,7 @@ spg_text_choose(PG_FUNCTION_ARGS)
 		out->result.splitTuple.prefixHasPrefix = in->hasPrefix;
 		out->result.splitTuple.prefixPrefixDatum = in->prefixDatum;
 		out->result.splitTuple.prefixNNodes = 1;
-		out->result.splitTuple.prefixNodeLabels = (Datum *) palloc(sizeof(Datum));
+		out->result.splitTuple.prefixNodeLabels = palloc_object(Datum);
 		out->result.splitTuple.prefixNodeLabels[0] = Int16GetDatum(-2);
 		out->result.splitTuple.childNodeN = 0;
 		out->result.splitTuple.postfixHasPrefix = false;
@@ -371,7 +370,7 @@ spg_text_picksplit(PG_FUNCTION_ARGS)
 	}
 
 	/* Extract the node label (first non-common byte) from each value */
-	nodes = (spgNodePtr *) palloc(sizeof(spgNodePtr) * in->nTuples);
+	nodes = palloc_array(spgNodePtr, in->nTuples);
 
 	for (i = 0; i < in->nTuples; i++)
 	{
@@ -394,9 +393,9 @@ spg_text_picksplit(PG_FUNCTION_ARGS)
 
 	/* And emit results */
 	out->nNodes = 0;
-	out->nodeLabels = (Datum *) palloc(sizeof(Datum) * in->nTuples);
-	out->mapTuplesToNodes = (int *) palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = (Datum *) palloc(sizeof(Datum) * in->nTuples);
+	out->nodeLabels = palloc_array(Datum, in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	for (i = 0; i < in->nTuples; i++)
 	{
@@ -476,9 +475,9 @@ spg_text_inner_consistent(PG_FUNCTION_ARGS)
 	 * and see if it's consistent with the query.  If so, emit an entry into
 	 * the output arrays.
 	 */
-	out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
-	out->levelAdds = (int *) palloc(sizeof(int) * in->nNodes);
-	out->reconstructedValues = (Datum *) palloc(sizeof(Datum) * in->nNodes);
+	out->nodeNumbers = palloc_array(int, in->nNodes);
+	out->levelAdds = palloc_array(int, in->nNodes);
+	out->reconstructedValues = palloc_array(Datum, in->nNodes);
 	out->nNodes = 0;
 
 	for (i = 0; i < in->nNodes; i++)
diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c
index 87c31da71a5..a60ec85e8be 100644
--- a/src/backend/access/spgist/spgutils.c
+++ b/src/backend/access/spgist/spgutils.c
@@ -1177,7 +1177,7 @@ spgExtractNodeLabels(SpGistState *state, SpGistInnerTuple innerTuple)
 	}
 	else
 	{
-		nodeLabels = (Datum *) palloc(sizeof(Datum) * innerTuple->nNodes);
+		nodeLabels = palloc_array(Datum, innerTuple->nNodes);
 		SGITITERATE(innerTuple, i, node)
 		{
 			if (IndexTupleHasNulls(node))
diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c
index 71ef2e5036f..cb5671c1a4e 100644
--- a/src/backend/access/spgist/spgvacuum.c
+++ b/src/backend/access/spgist/spgvacuum.c
@@ -76,7 +76,7 @@ spgAddPendingTID(spgBulkDeleteState *bds, const ItemPointerData *tid)
 		listLink = &pitem->next;
 	}
 	/* not there, so append new entry */
-	pitem = (spgVacPendingItem *) palloc(sizeof(spgVacPendingItem));
+	pitem = palloc_object(spgVacPendingItem);
 	pitem->tid = *tid;
 	pitem->done = false;
 	pitem->next = NULL;
@@ -954,7 +954,7 @@ spgbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 
 	/* allocate stats if first time through, else re-use existing struct */
 	if (stats == NULL)
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 	bds.info = info;
 	bds.stats = stats;
 	bds.callback = callback;
@@ -994,7 +994,7 @@ spgvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 	 */
 	if (stats == NULL)
 	{
-		stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+		stats = palloc0_object(IndexBulkDeleteResult);
 		bds.info = info;
 		bds.stats = stats;
 		bds.callback = dummy_callback;
diff --git a/src/backend/access/spgist/spgxlog.c b/src/backend/access/spgist/spgxlog.c
index b7110302b98..f635be0698f 100644
--- a/src/backend/access/spgist/spgxlog.c
+++ b/src/backend/access/spgist/spgxlog.c
@@ -901,7 +901,7 @@ spgRedoVacuumRedirect(XLogReaderState *record)
 			int			max = PageGetMaxOffsetNumber(page);
 			OffsetNumber *toDelete;
 
-			toDelete = palloc(sizeof(OffsetNumber) * max);
+			toDelete = palloc_array(OffsetNumber, max);
 
 			for (i = xldata->firstPlaceholder; i <= max; i++)
 				toDelete[i - xldata->firstPlaceholder] = i;
diff --git a/src/backend/access/tablesample/bernoulli.c b/src/backend/access/tablesample/bernoulli.c
index 5e1c5d2b723..cce603d1b7f 100644
--- a/src/backend/access/tablesample/bernoulli.c
+++ b/src/backend/access/tablesample/bernoulli.c
@@ -126,7 +126,7 @@ bernoulli_samplescangetsamplesize(PlannerInfo *root,
 static void
 bernoulli_initsamplescan(SampleScanState *node, int eflags)
 {
-	node->tsm_state = palloc0(sizeof(BernoulliSamplerData));
+	node->tsm_state = palloc0_object(BernoulliSamplerData);
 }
 
 /*
diff --git a/src/backend/access/tablesample/system.c b/src/backend/access/tablesample/system.c
index 8db813b89fc..c6740dbdd1b 100644
--- a/src/backend/access/tablesample/system.c
+++ b/src/backend/access/tablesample/system.c
@@ -129,7 +129,7 @@ system_samplescangetsamplesize(PlannerInfo *root,
 static void
 system_initsamplescan(SampleScanState *node, int eflags)
 {
-	node->tsm_state = palloc0(sizeof(SystemSamplerData));
+	node->tsm_state = palloc0_object(SystemSamplerData);
 }
 
 /*
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 9d5f130af7e..9d56e886e28 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -549,8 +549,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
 	 * Note we have the same race condition here as above: j could be 0 at the
 	 * end of the loop.
 	 */
-	newMembers = (MultiXactMember *)
-		palloc(sizeof(MultiXactMember) * (nmembers + 1));
+	newMembers = palloc_array(MultiXactMember, nmembers + 1); 
 
 	for (i = 0, j = 0; i < nmembers; i++)
 	{
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index 94db1ec3012..8428103eba4 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -186,7 +186,7 @@ CreateParallelContext(const char *library_name, const char *function_name,
 	oldcontext = MemoryContextSwitchTo(TopTransactionContext);
 
 	/* Initialize a new ParallelContext. */
-	pcxt = palloc0(sizeof(ParallelContext));
+	pcxt = palloc0_object(ParallelContext);
 	pcxt->subid = GetCurrentSubTransactionId();
 	pcxt->nworkers = nworkers;
 	pcxt->nworkers_to_launch = nworkers;
@@ -453,7 +453,7 @@ InitializeParallelDSM(ParallelContext *pcxt)
 					   clientconninfospace);
 
 		/* Allocate space for worker information. */
-		pcxt->worker = palloc0(sizeof(ParallelWorkerInfo) * pcxt->nworkers);
+		pcxt->worker = palloc0_array(ParallelWorkerInfo, pcxt->nworkers);
 
 		/*
 		 * Establish error queues in dynamic shared memory.
@@ -648,8 +648,7 @@ LaunchParallelWorkers(ParallelContext *pcxt)
 	 */
 	if (pcxt->nworkers_launched > 0)
 	{
-		pcxt->known_attached_workers =
-			palloc0(sizeof(bool) * pcxt->nworkers_launched);
+		pcxt->known_attached_workers = palloc0_array(bool, pcxt->nworkers_launched);
 		pcxt->nknown_attached_workers = 0;
 	}
 
diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index ec3e323ec0c..b8af25e82d1 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -87,7 +87,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 	/* Timeline 1 does not have a history file, so no need to check */
 	if (targetTLI == 1)
 	{
-		entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
+		entry = palloc_object(TimeLineHistoryEntry);
 		entry->tli = targetTLI;
 		entry->begin = entry->end = InvalidXLogRecPtr;
 		return list_make1(entry);
@@ -110,7 +110,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 					(errcode_for_file_access(),
 					 errmsg("could not open file \"%s\": %m", path)));
 		/* Not there, so assume no parents */
-		entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
+		entry = palloc_object(TimeLineHistoryEntry);
 		entry->tli = targetTLI;
 		entry->begin = entry->end = InvalidXLogRecPtr;
 		return list_make1(entry);
@@ -175,7 +175,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 
 		lasttli = tli;
 
-		entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
+		entry = palloc_object(TimeLineHistoryEntry);
 		entry->tli = tli;
 		entry->begin = prevend;
 		entry->end = ((uint64) (switchpoint_hi)) << 32 | (uint64) switchpoint_lo;
@@ -198,7 +198,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 	 * Create one more entry for the "tip" of the timeline, which has no entry
 	 * in the history file.
 	 */
-	entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
+	entry = palloc_object(TimeLineHistoryEntry);
 	entry->tli = targetTLI;
 	entry->begin = prevend;
 	entry->end = InvalidXLogRecPtr;
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index da282b71b41..ec4e3628bd5 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -684,7 +684,7 @@ GetPreparedTransactionList(GlobalTransaction *gxacts)
 	}
 
 	num = TwoPhaseState->numPrepXacts;
-	array = (GlobalTransaction) palloc(sizeof(GlobalTransactionData) * num);
+	array = palloc_array(GlobalTransactionData, num);
 	*gxacts = array;
 	for (i = 0; i < num; i++)
 		memcpy(array + i, TwoPhaseState->prepXacts[i],
@@ -750,7 +750,7 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
 		 * Collect all the 2PC status information that we will format and send
 		 * out as a result set.
 		 */
-		status = (Working_State *) palloc(sizeof(Working_State));
+		status = palloc_object(Working_State);
 		funcctx->user_fctx = status;
 
 		status->ngxacts = GetPreparedTransactionList(&status->array);
@@ -1027,7 +1027,7 @@ save_state_data(const void *data, uint32 len)
 
 	if (padlen > records.bytes_free)
 	{
-		records.tail->next = palloc0(sizeof(StateFileChunk));
+		records.tail->next = palloc0_object(StateFileChunk);
 		records.tail = records.tail->next;
 		records.tail->len = 0;
 		records.tail->next = NULL;
@@ -1062,7 +1062,7 @@ StartPrepare(GlobalTransaction gxact)
 	SharedInvalidationMessage *invalmsgs;
 
 	/* Initialize linked list */
-	records.head = palloc0(sizeof(StateFileChunk));
+	records.head = palloc0_object(StateFileChunk);
 	records.head->len = 0;
 	records.head->next = NULL;
 
@@ -1453,7 +1453,7 @@ XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len)
 	if (len != NULL)
 		*len = XLogRecGetDataLen(xlogreader);
 
-	*buf = palloc(sizeof(char) * XLogRecGetDataLen(xlogreader));
+	*buf = palloc_array(char, XLogRecGetDataLen(xlogreader));
 	memcpy(*buf, XLogRecGetData(xlogreader), sizeof(char) * XLogRecGetDataLen(xlogreader));
 
 	XLogReaderFree(xlogreader);
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 092e197eba3..025dd0be5fc 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -664,7 +664,7 @@ AssignTransactionId(TransactionState s)
 		TransactionState *parents;
 		size_t		parentOffset = 0;
 
-		parents = palloc(sizeof(TransactionState) * s->nestingLevel);
+		parents = palloc_array(TransactionState, s->nestingLevel);
 		while (p != NULL && !FullTransactionIdIsValid(p->fullTransactionId))
 		{
 			parents[parentOffset++] = p;
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 22d0a2e8c3a..e81f43f5256 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4902,7 +4902,7 @@ void
 LocalProcessControlFile(bool reset)
 {
 	Assert(reset || ControlFile == NULL);
-	ControlFile = palloc(sizeof(ControlFileData));
+	ControlFile = palloc_object(ControlFileData);
 	ReadControlFile();
 }
 
@@ -9135,7 +9135,7 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
 				continue;
 			}
 
-			ti = palloc(sizeof(tablespaceinfo));
+			ti = palloc_object(tablespaceinfo);
 			ti->oid = tsoid;
 			ti->path = pstrdup(linkpath);
 			ti->rpath = relpath;
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index a50345f9bf7..339cb75c3ad 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -90,7 +90,7 @@ pg_backup_start(PG_FUNCTION_ARGS)
 	}
 
 	oldcontext = MemoryContextSwitchTo(backupcontext);
-	backup_state = (BackupState *) palloc0(sizeof(BackupState));
+	backup_state = palloc0_object(BackupState);
 	tablespace_map = makeStringInfo();
 	MemoryContextSwitchTo(oldcontext);
 
diff --git a/src/backend/access/transam/xlogprefetcher.c b/src/backend/access/transam/xlogprefetcher.c
index ed3aacabc98..ccc29192c5a 100644
--- a/src/backend/access/transam/xlogprefetcher.c
+++ b/src/backend/access/transam/xlogprefetcher.c
@@ -364,7 +364,7 @@ XLogPrefetcherAllocate(XLogReaderState *reader)
 	XLogPrefetcher *prefetcher;
 	HASHCTL		ctl;
 
-	prefetcher = palloc0(sizeof(XLogPrefetcher));
+	prefetcher = palloc0_object(XLogPrefetcher);
 	prefetcher->reader = reader;
 
 	ctl.keysize = sizeof(RelFileLocator);
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 21b8f179ba0..2e03bc1cdf2 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -559,7 +559,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 	 * Set the WAL reading processor now, as it will be needed when reading
 	 * the checkpoint record required (backup_label or not).
 	 */
-	private = palloc0(sizeof(XLogPageReadPrivate));
+	private = palloc0_object(XLogPageReadPrivate);
 	xlogreader =
 		XLogReaderAllocate(wal_segment_size, NULL,
 						   XL_ROUTINE(.page_read = &XLogPageRead,
@@ -1416,7 +1416,7 @@ read_tablespace_map(List **tablespaces)
 						 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
 			str[n++] = '\0';
 
-			ti = palloc0(sizeof(tablespaceinfo));
+			ti = palloc0_object(tablespaceinfo);
 			errno = 0;
 			ti->oid = strtoul(str, &endp, 10);
 			if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
@@ -1467,7 +1467,7 @@ read_tablespace_map(List **tablespaces)
 EndOfWalRecoveryInfo *
 FinishWalRecovery(void)
 {
-	EndOfWalRecoveryInfo *result = palloc(sizeof(EndOfWalRecoveryInfo));
+	EndOfWalRecoveryInfo *result = palloc_object(EndOfWalRecoveryInfo);
 	XLogRecPtr	lastRec;
 	TimeLineID	lastRecTLI;
 	XLogRecPtr	endOfLog;
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index ce2a3e42146..db55c0c5bd2 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -574,7 +574,7 @@ CreateFakeRelcacheEntry(RelFileLocator rlocator)
 	Relation	rel;
 
 	/* Allocate the Relation struct and all related space in one block. */
-	fakeentry = palloc0(sizeof(FakeRelCacheEntryData));
+	fakeentry = palloc0_object(FakeRelCacheEntryData);
 	rel = (Relation) fakeentry;
 
 	rel->rd_rel = &fakeentry->pgc;
diff --git a/src/backend/backup/basebackup.c b/src/backend/backup/basebackup.c
index 2be4e069816..1f7b42da009 100644
--- a/src/backend/backup/basebackup.c
+++ b/src/backend/backup/basebackup.c
@@ -262,7 +262,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink,
 	total_checksum_failures = 0;
 
 	/* Allocate backup related variables. */
-	backup_state = (BackupState *) palloc0(sizeof(BackupState));
+	backup_state = palloc0_object(BackupState);
 	initStringInfo(&tablespace_map);
 
 	basebackup_progress_wait_checkpoint();
@@ -289,7 +289,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink,
 			PrepareForIncrementalBackup(ib, backup_state);
 
 		/* Add a node for the base directory at the end */
-		newti = palloc0(sizeof(tablespaceinfo));
+		newti = palloc0_object(tablespaceinfo);
 		newti->size = -1;
 		state.tablespaces = lappend(state.tablespaces, newti);
 
@@ -1206,7 +1206,7 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
 	 * But we don't need it at all if this is not an incremental backup.
 	 */
 	if (ib != NULL)
-		relative_block_numbers = palloc(sizeof(BlockNumber) * RELSEG_SIZE);
+		relative_block_numbers = palloc_array(BlockNumber, RELSEG_SIZE);
 
 	/*
 	 * Determine if the current path is a database directory that can contain
diff --git a/src/backend/backup/basebackup_copy.c b/src/backend/backup/basebackup_copy.c
index eb45d3bcb66..8bb8d3939fe 100644
--- a/src/backend/backup/basebackup_copy.c
+++ b/src/backend/backup/basebackup_copy.c
@@ -107,7 +107,7 @@ static const bbsink_ops bbsink_copystream_ops = {
 bbsink *
 bbsink_copystream_new(bool send_to_client)
 {
-	bbsink_copystream *sink = palloc0(sizeof(bbsink_copystream));
+	bbsink_copystream *sink = palloc0_object(bbsink_copystream);
 
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_copystream_ops;
 	sink->send_to_client = send_to_client;
diff --git a/src/backend/backup/basebackup_gzip.c b/src/backend/backup/basebackup_gzip.c
index c4cbb5f5276..aaad834291a 100644
--- a/src/backend/backup/basebackup_gzip.c
+++ b/src/backend/backup/basebackup_gzip.c
@@ -76,7 +76,7 @@ bbsink_gzip_new(bbsink *next, pg_compress_specification *compress)
 	Assert((compresslevel >= 1 && compresslevel <= 9) ||
 		   compresslevel == Z_DEFAULT_COMPRESSION);
 
-	sink = palloc0(sizeof(bbsink_gzip));
+	sink = palloc0_object(bbsink_gzip);
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_gzip_ops;
 	sink->base.bbs_next = next;
 	sink->compresslevel = compresslevel;
diff --git a/src/backend/backup/basebackup_incremental.c b/src/backend/backup/basebackup_incremental.c
index 852ab577045..7678e4f6ec3 100644
--- a/src/backend/backup/basebackup_incremental.c
+++ b/src/backend/backup/basebackup_incremental.c
@@ -157,7 +157,7 @@ CreateIncrementalBackupInfo(MemoryContext mcxt)
 
 	oldcontext = MemoryContextSwitchTo(mcxt);
 
-	ib = palloc0(sizeof(IncrementalBackupInfo));
+	ib = palloc0_object(IncrementalBackupInfo);
 	ib->mcxt = mcxt;
 	initStringInfo(&ib->buf);
 
@@ -169,7 +169,7 @@ CreateIncrementalBackupInfo(MemoryContext mcxt)
 	 */
 	ib->manifest_files = backup_file_create(mcxt, 10000, NULL);
 
-	context = palloc0(sizeof(JsonManifestParseContext));
+	context = palloc0_object(JsonManifestParseContext);
 	/* Parse the manifest. */
 	context->private_data = ib;
 	context->version_cb = manifest_process_version;
@@ -993,7 +993,7 @@ manifest_process_wal_range(JsonManifestParseContext *context,
 						   XLogRecPtr end_lsn)
 {
 	IncrementalBackupInfo *ib = context->private_data;
-	backup_wal_range *range = palloc(sizeof(backup_wal_range));
+	backup_wal_range *range = palloc_object(backup_wal_range);
 
 	range->tli = tli;
 	range->start_lsn = start_lsn;
diff --git a/src/backend/backup/basebackup_lz4.c b/src/backend/backup/basebackup_lz4.c
index c5ceccb846f..bd5704520fb 100644
--- a/src/backend/backup/basebackup_lz4.c
+++ b/src/backend/backup/basebackup_lz4.c
@@ -75,7 +75,7 @@ bbsink_lz4_new(bbsink *next, pg_compress_specification *compress)
 	compresslevel = compress->level;
 	Assert(compresslevel >= 0 && compresslevel <= 12);
 
-	sink = palloc0(sizeof(bbsink_lz4));
+	sink = palloc0_object(bbsink_lz4);
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_lz4_ops;
 	sink->base.bbs_next = next;
 	sink->compresslevel = compresslevel;
diff --git a/src/backend/backup/basebackup_progress.c b/src/backend/backup/basebackup_progress.c
index dac20593622..d783c9f5738 100644
--- a/src/backend/backup/basebackup_progress.c
+++ b/src/backend/backup/basebackup_progress.c
@@ -62,7 +62,7 @@ bbsink_progress_new(bbsink *next, bool estimate_backup_size, bool incremental)
 
 	Assert(next != NULL);
 
-	sink = palloc0(sizeof(bbsink));
+	sink = palloc0_object(bbsink);
 	*((const bbsink_ops **) &sink->bbs_ops) = &bbsink_progress_ops;
 	sink->bbs_next = next;
 
diff --git a/src/backend/backup/basebackup_server.c b/src/backend/backup/basebackup_server.c
index f5c0c61640a..7510ec06f5e 100644
--- a/src/backend/backup/basebackup_server.c
+++ b/src/backend/backup/basebackup_server.c
@@ -59,7 +59,7 @@ static const bbsink_ops bbsink_server_ops = {
 bbsink *
 bbsink_server_new(bbsink *next, char *pathname)
 {
-	bbsink_server *sink = palloc0(sizeof(bbsink_server));
+	bbsink_server *sink = palloc0_object(bbsink_server);
 
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_server_ops;
 	sink->pathname = pathname;
diff --git a/src/backend/backup/basebackup_target.c b/src/backend/backup/basebackup_target.c
index 84b1309d3bd..8b74828aed6 100644
--- a/src/backend/backup/basebackup_target.c
+++ b/src/backend/backup/basebackup_target.c
@@ -96,7 +96,7 @@ BaseBackupAddTarget(char *name,
 	 * name into a newly-allocated chunk of memory.
 	 */
 	oldcontext = MemoryContextSwitchTo(TopMemoryContext);
-	newtype = palloc(sizeof(BaseBackupTargetType));
+	newtype = palloc_object(BaseBackupTargetType);
 	newtype->name = pstrdup(name);
 	newtype->check_detail = check_detail;
 	newtype->get_sink = get_sink;
@@ -132,7 +132,7 @@ BaseBackupGetTargetHandle(char *target, char *target_detail)
 			BaseBackupTargetHandle *handle;
 
 			/* Found the target. */
-			handle = palloc(sizeof(BaseBackupTargetHandle));
+			handle = palloc_object(BaseBackupTargetHandle);
 			handle->type = ttype;
 			handle->detail_arg = ttype->check_detail(target, target_detail);
 
diff --git a/src/backend/backup/basebackup_throttle.c b/src/backend/backup/basebackup_throttle.c
index b2b743238f9..95746c3ea40 100644
--- a/src/backend/backup/basebackup_throttle.c
+++ b/src/backend/backup/basebackup_throttle.c
@@ -72,7 +72,7 @@ bbsink_throttle_new(bbsink *next, uint32 maxrate)
 	Assert(next != NULL);
 	Assert(maxrate > 0);
 
-	sink = palloc0(sizeof(bbsink_throttle));
+	sink = palloc0_object(bbsink_throttle);
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_throttle_ops;
 	sink->base.bbs_next = next;
 
diff --git a/src/backend/backup/basebackup_zstd.c b/src/backend/backup/basebackup_zstd.c
index 18b2e8fb0b3..647ee0eb978 100644
--- a/src/backend/backup/basebackup_zstd.c
+++ b/src/backend/backup/basebackup_zstd.c
@@ -70,7 +70,7 @@ bbsink_zstd_new(bbsink *next, pg_compress_specification *compress)
 
 	Assert(next != NULL);
 
-	sink = palloc0(sizeof(bbsink_zstd));
+	sink = palloc0_object(bbsink_zstd);
 	*((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_zstd_ops;
 	sink->base.bbs_next = next;
 	sink->compress = compress;
diff --git a/src/backend/backup/walsummary.c b/src/backend/backup/walsummary.c
index 2689eae3328..a843876337b 100644
--- a/src/backend/backup/walsummary.c
+++ b/src/backend/backup/walsummary.c
@@ -73,7 +73,7 @@ GetWalSummaries(TimeLineID tli, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
 			continue;
 
 		/* Add it to the list. */
-		ws = palloc(sizeof(WalSummaryFile));
+		ws = palloc_object(WalSummaryFile);
 		ws->tli = file_tli;
 		ws->start_lsn = file_start_lsn;
 		ws->end_lsn = file_end_lsn;
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index fc8638c1b61..4986b1ea7ed 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -742,7 +742,7 @@ populate_typ_list(void)
 		Form_pg_type typForm = (Form_pg_type) GETSTRUCT(tup);
 		struct typmap *newtyp;
 
-		newtyp = (struct typmap *) palloc(sizeof(struct typmap));
+		newtyp = palloc_object(struct typmap);
 		Typ = lappend(Typ, newtyp);
 
 		newtyp->am_oid = typForm->oid;
@@ -951,10 +951,10 @@ index_register(Oid heap,
 
 	oldcxt = MemoryContextSwitchTo(nogc);
 
-	newind = (IndexList *) palloc(sizeof(IndexList));
+	newind = palloc_object(IndexList);
 	newind->il_heap = heap;
 	newind->il_ind = ind;
-	newind->il_info = (IndexInfo *) palloc(sizeof(IndexInfo));
+	newind->il_info = palloc_object(IndexInfo);
 
 	memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
 	/* expressions will likely be null, but may as well copy it */
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 8e70a85a3f7..838ed26d6b9 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -801,8 +801,7 @@ findDependentObjects(const ObjectAddress *object,
 	 * regression testing.)
 	 */
 	maxDependentObjects = 128;	/* arbitrary initial allocation */
-	dependentObjects = (ObjectAddressAndFlags *)
-		palloc(maxDependentObjects * sizeof(ObjectAddressAndFlags));
+	dependentObjects = palloc_array(ObjectAddressAndFlags, maxDependentObjects);
 	numDependentObjects = 0;
 
 	ScanKeyInit(&key[0],
@@ -2616,12 +2615,11 @@ new_object_addresses(void)
 {
 	ObjectAddresses *addrs;
 
-	addrs = palloc(sizeof(ObjectAddresses));
+	addrs = palloc_object(ObjectAddresses);
 
 	addrs->numrefs = 0;
 	addrs->maxrefs = 32;
-	addrs->refs = (ObjectAddress *)
-		palloc(addrs->maxrefs * sizeof(ObjectAddress));
+	addrs->refs = palloc_array(ObjectAddress, addrs->maxrefs);
 	addrs->extras = NULL;		/* until/unless needed */
 
 	return addrs;
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index fd6537567ea..265cc3e5fbf 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -732,7 +732,7 @@ InsertPgAttributeTuples(Relation pg_attribute_rel,
 	/* Initialize the number of slots to use */
 	nslots = Min(tupdesc->natts,
 				 (MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_attribute)));
-	slot = palloc(sizeof(TupleTableSlot *) * nslots);
+	slot = palloc_array(TupleTableSlot *, nslots);
 	for (int i = 0; i < nslots; i++)
 		slot[i] = MakeSingleTupleTableSlot(td, &TTSOpsHeapTuple);
 
@@ -2459,7 +2459,7 @@ AddRelationNewConstraints(Relation rel,
 
 		defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
 
-		cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+		cooked = palloc_object(CookedConstraint);
 		cooked->contype = CONSTR_DEFAULT;
 		cooked->conoid = defOid;
 		cooked->name = NULL;
@@ -2593,7 +2593,7 @@ AddRelationNewConstraints(Relation rel,
 
 			numchecks++;
 
-			cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+			cooked = palloc_object(CookedConstraint);
 			cooked->contype = CONSTR_CHECK;
 			cooked->conoid = constrOid;
 			cooked->name = ccname;
@@ -2669,7 +2669,7 @@ AddRelationNewConstraints(Relation rel,
 								inhcount,
 								cdef->is_no_inherit);
 
-			nncooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+			nncooked = palloc_object(CookedConstraint);
 			nncooked->contype = CONSTR_NOTNULL;
 			nncooked->conoid = constrOid;
 			nncooked->name = nnname;
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 5d9db167e59..d94ca7ea53a 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1414,7 +1414,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
 	}
 
 	/* Extract opclass options for each attribute */
-	opclassOptions = palloc0(sizeof(Datum) * newInfo->ii_NumIndexAttrs);
+	opclassOptions = palloc0_array(Datum, newInfo->ii_NumIndexAttrs);
 	for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
 		opclassOptions[i] = get_attoptions(oldIndexId, i + 1);
 
@@ -2678,9 +2678,9 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
 	 */
 	Assert(ii->ii_Unique);
 
-	ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
+	ii->ii_UniqueOps = (Oid *) palloc_array(Oid, indnkeyatts);
+	ii->ii_UniqueProcs = (Oid *) palloc_array(Oid, indnkeyatts);
+	ii->ii_UniqueStrats = (uint16 *) palloc_array(uint16, indnkeyatts);
 
 	/*
 	 * We have to look up the operator's strategy number.  This provides a
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index d23474da4fb..c94089caa58 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -3929,7 +3929,7 @@ GetSearchPathMatcher(MemoryContext context)
 
 	oldcxt = MemoryContextSwitchTo(context);
 
-	result = (SearchPathMatcher *) palloc0(sizeof(SearchPathMatcher));
+	result = palloc0_object(SearchPathMatcher);
 	schemas = list_copy(activeSearchPath);
 	while (schemas && linitial_oid(schemas) != activeCreationNamespace)
 	{
@@ -3960,7 +3960,7 @@ CopySearchPathMatcher(SearchPathMatcher *path)
 {
 	SearchPathMatcher *result;
 
-	result = (SearchPathMatcher *) palloc(sizeof(SearchPathMatcher));
+	result = palloc_object(SearchPathMatcher);
 	result->schemas = list_copy(path->schemas);
 	result->addCatalog = path->addCatalog;
 	result->addTemp = path->addTemp;
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index c75b7131ed7..fa6c6df598a 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -6144,8 +6144,8 @@ strlist_to_textarray(List *list)
 								   ALLOCSET_DEFAULT_SIZES);
 	oldcxt = MemoryContextSwitchTo(memcxt);
 
-	datums = (Datum *) palloc(sizeof(Datum) * list_length(list));
-	nulls = palloc(sizeof(bool) * list_length(list));
+	datums = palloc_array(Datum, list_length(list));
+	nulls = palloc_array(bool, list_length(list));
 
 	foreach(cell, list)
 	{
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 9944e4bd2d1..fa73ca178c5 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -846,7 +846,7 @@ RelationGetNotNullConstraints(Oid relid, bool cooked, bool include_noinh)
 		{
 			CookedConstraint *cooked;
 
-			cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+			cooked = palloc_object(CookedConstraint);
 
 			cooked->contype = CONSTR_NOTNULL;
 			cooked->conoid = conForm->oid;
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index c8b11f887e2..a6f63e107bb 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -88,7 +88,7 @@ recordMultipleDependencies(const ObjectAddress *depender,
 	 */
 	max_slots = Min(nreferenced,
 					MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_depend));
-	slot = palloc(sizeof(TupleTableSlot *) * max_slots);
+	slot = palloc_array(TupleTableSlot *, max_slots);
 
 	/* Don't open indexes unless we need to make an update */
 	indstate = NULL;
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index da9c2a46cfa..07998839aff 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -120,7 +120,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 	 * allocating the next), trouble could only occur if the OID counter wraps
 	 * all the way around before we finish. Which seems unlikely.
 	 */
-	oids = (Oid *) palloc(num_elems * sizeof(Oid));
+	oids = palloc_array(Oid, num_elems);
 
 	for (elemno = 0; elemno < num_elems; elemno++)
 	{
@@ -148,7 +148,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 	/* allocate the slots to use and initialize them */
 	nslots = Min(num_elems,
 				 MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_enum));
-	slot = palloc(sizeof(TupleTableSlot *) * nslots);
+	slot = palloc_array(TupleTableSlot *, nslots);
 	for (int i = 0; i < nslots; i++)
 		slot[i] = MakeSingleTupleTableSlot(RelationGetDescr(pg_enum),
 										   &TTSOpsHeapTuple);
@@ -375,7 +375,7 @@ restart:
 	nelems = list->n_members;
 
 	/* Sort the existing members by enumsortorder */
-	existing = (HeapTuple *) palloc(nelems * sizeof(HeapTuple));
+	existing = palloc_array(HeapTuple, nelems);
 	for (i = 0; i < nelems; i++)
 		existing[i] = &(list->members[i]->tuple);
 
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index 0994220c53d..be5ef5e4c0e 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -1086,7 +1086,7 @@ GetPublication(Oid pubid)
 
 	pubform = (Form_pg_publication) GETSTRUCT(tup);
 
-	pub = (Publication *) palloc(sizeof(Publication));
+	pub = palloc_object(Publication);
 	pub->oid = pubid;
 	pub->name = pstrdup(NameStr(pubform->pubname));
 	pub->alltables = pubform->puballtables;
@@ -1196,7 +1196,7 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
 			 */
 			foreach(lc, pub_elem_tables)
 			{
-				published_rel *table_info = (published_rel *) palloc(sizeof(published_rel));
+				published_rel *table_info = palloc_object(published_rel);
 
 				table_info->relid = lfirst_oid(lc);
 				table_info->pubid = pub_elem->oid;
@@ -1299,7 +1299,7 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
 			TupleDesc	desc = RelationGetDescr(rel);
 			int			i;
 
-			attnums = (int16 *) palloc(desc->natts * sizeof(int16));
+			attnums = palloc_array(int16, desc->natts);
 
 			for (i = 0; i < desc->natts; i++)
 			{
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index 16e3e5c7457..fe4e4536676 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -791,7 +791,7 @@ checkSharedDependencies(Oid classId, Oid objectId,
 			}
 			if (!stored)
 			{
-				dep = (remoteDep *) palloc(sizeof(remoteDep));
+				dep = palloc_object(remoteDep);
 				dep->dbOid = sdepForm->dbid;
 				dep->count = 1;
 				remDeps = lappend(remDeps, dep);
@@ -913,7 +913,7 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId)
 	 * know that they will be used.
 	 */
 	max_slots = MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_shdepend);
-	slot = palloc(sizeof(TupleTableSlot *) * max_slots);
+	slot = palloc_array(TupleTableSlot *, max_slots);
 
 	indstate = CatalogOpenIndexes(sdepRel);
 
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index 180e77e9484..ad6fbd77ffd 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -89,7 +89,7 @@ GetSubscription(Oid subid, bool missing_ok)
 
 	subform = (Form_pg_subscription) GETSTRUCT(tup);
 
-	sub = (Subscription *) palloc(sizeof(Subscription));
+	sub = palloc_object(Subscription);
 	sub->oid = subid;
 	sub->dbid = subform->subdbid;
 	sub->skiplsn = subform->subskiplsn;
@@ -618,7 +618,7 @@ GetSubscriptionRelations(Oid subid, bool tables, bool sequences,
 			 relkind == RELKIND_PARTITIONED_TABLE) && !tables)
 			continue;
 
-		relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState));
+		relstate = palloc_object(SubscriptionRelState);
 		relstate->relid = subrel->srrelid;
 		relstate->state = subrel->srsubstate;
 		d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup,
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index c58e9418ac3..d06c1c68174 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -707,12 +707,12 @@ smgrDoPendingDeletes(bool isCommit)
 				if (maxrels == 0)
 				{
 					maxrels = 8;
-					srels = palloc(sizeof(SMgrRelation) * maxrels);
+					srels = palloc_array(SMgrRelation, maxrels);
 				}
 				else if (maxrels <= nrels)
 				{
 					maxrels *= 2;
-					srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
+					srels = repalloc_array(srels, SMgrRelation, maxrels);
 				}
 
 				srels[nrels++] = srel;
@@ -829,12 +829,12 @@ smgrDoPendingSyncs(bool isCommit, bool isParallelWorker)
 			if (maxrels == 0)
 			{
 				maxrels = 8;
-				srels = palloc(sizeof(SMgrRelation) * maxrels);
+				srels = palloc_array(SMgrRelation, maxrels);
 			}
 			else if (maxrels <= nrels)
 			{
 				maxrels *= 2;
-				srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
+				srels = repalloc_array(srels, SMgrRelation, maxrels);
 			}
 
 			srels[nrels++] = srel;
@@ -909,7 +909,7 @@ smgrGetPendingDeletes(bool forCommit, RelFileLocator **ptr)
 		*ptr = NULL;
 		return 0;
 	}
-	rptr = (RelFileLocator *) palloc(nrels * sizeof(RelFileLocator));
+	rptr = palloc_array(RelFileLocator, nrels);
 	*ptr = rptr;
 	for (pending = pendingDeletes; pending != NULL; pending = pending->next)
 	{
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 25089fae3e0..282c53683ad 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -1073,7 +1073,7 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr)
 	/*
 	 * Create the VacAttrStats struct.
 	 */
-	stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
+	stats = palloc0_object(VacAttrStats);
 	stats->attstattarget = attstattarget;
 
 	/*
@@ -1904,7 +1904,7 @@ std_typanalyze(VacAttrStats *stats)
 							 NULL);
 
 	/* Save the operator info for compute_stats routines */
-	mystats = (StdAnalyzeData *) palloc(sizeof(StdAnalyzeData));
+	mystats = palloc_object(StdAnalyzeData);
 	mystats->eqopr = eqopr;
 	mystats->eqfunc = OidIsValid(eqopr) ? get_opcode(eqopr) : InvalidOid;
 	mystats->ltopr = ltopr;
@@ -2859,7 +2859,7 @@ compute_scalar_stats(VacAttrStatsP stats,
 
 			/* Must copy the target values into anl_context */
 			old_context = MemoryContextSwitchTo(stats->anl_context);
-			corrs = (float4 *) palloc(sizeof(float4));
+			corrs = palloc_object(float4);
 			MemoryContextSwitchTo(old_context);
 
 			/*----------
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index b55221d44cd..a838a734321 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -1672,7 +1672,7 @@ get_tables_to_cluster(MemoryContext cluster_context)
 		/* Use a permanent memory context for the result list */
 		old_context = MemoryContextSwitchTo(cluster_context);
 
-		rtc = (RelToCluster *) palloc(sizeof(RelToCluster));
+		rtc = palloc_object(RelToCluster);
 		rtc->tableOid = index->indrelid;
 		rtc->indexOid = index->indexrelid;
 		rtcs = lappend(rtcs, rtc);
@@ -1726,7 +1726,7 @@ get_tables_to_cluster_partitioned(MemoryContext cluster_context, Oid indexOid)
 		/* Use a permanent memory context for the result list */
 		old_context = MemoryContextSwitchTo(cluster_context);
 
-		rtc = (RelToCluster *) palloc(sizeof(RelToCluster));
+		rtc = palloc_object(RelToCluster);
 		rtc->tableOid = relid;
 		rtc->indexOid = indexrelid;
 		rtcs = lappend(rtcs, rtc);
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 28e878c3688..6454a39a01f 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -561,7 +561,7 @@ ProcessCopyOptions(ParseState *pstate,
 
 	/* Support external use for option sanity checking */
 	if (opts_out == NULL)
-		opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
+		opts_out = palloc0_object(CopyFormatOptions);
 
 	opts_out->file_encoding = -1;
 
diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c
index 12781963b4f..2ae3d2ba86e 100644
--- a/src/backend/commands/copyfrom.c
+++ b/src/backend/commands/copyfrom.c
@@ -364,7 +364,7 @@ CopyMultiInsertBufferInit(ResultRelInfo *rri)
 {
 	CopyMultiInsertBuffer *buffer;
 
-	buffer = (CopyMultiInsertBuffer *) palloc(sizeof(CopyMultiInsertBuffer));
+	buffer = palloc_object(CopyMultiInsertBuffer);
 	memset(buffer->slots, 0, sizeof(TupleTableSlot *) * MAX_BUFFERED_TUPLES);
 	buffer->resultRelInfo = rri;
 	buffer->bistate = (rri->ri_FdwRoutine == NULL) ? GetBulkInsertState() : NULL;
@@ -1558,7 +1558,7 @@ BeginCopyFrom(ParseState *pstate,
 	};
 
 	/* Allocate workspace and zero all fields */
-	cstate = (CopyFromStateData *) palloc0(sizeof(CopyFromStateData));
+	cstate = palloc0_object(CopyFromStateData);
 
 	/*
 	 * We allocate everything used by a cstate in a new memory context. This
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index cef452584e5..dae91630ac3 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -720,7 +720,7 @@ BeginCopyTo(ParseState *pstate,
 
 
 	/* Allocate workspace and zero all fields */
-	cstate = (CopyToStateData *) palloc0(sizeof(CopyToStateData));
+	cstate = palloc0_object(CopyToStateData);
 
 	/*
 	 * We allocate everything used by a cstate in a new memory context. This
@@ -1527,7 +1527,7 @@ copy_dest_destroy(DestReceiver *self)
 DestReceiver *
 CreateCopyDestReceiver(void)
 {
-	DR_copy    *self = (DR_copy *) palloc(sizeof(DR_copy));
+	DR_copy    *self = palloc_object(DR_copy);
 
 	self->pub.receiveSlot = copy_dest_receive;
 	self->pub.rStartup = copy_dest_startup;
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 1ccc2e55c64..ddc45e3aa0d 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -439,7 +439,7 @@ CreateTableAsRelExists(CreateTableAsStmt *ctas)
 DestReceiver *
 CreateIntoRelDestReceiver(IntoClause *intoClause)
 {
-	DR_intorel *self = (DR_intorel *) palloc0(sizeof(DR_intorel));
+	DR_intorel *self = palloc0_object(DR_intorel);
 
 	self->pub.receiveSlot = intorel_receive;
 	self->pub.rStartup = intorel_startup;
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 4d65e8c46c2..c12777f4464 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -431,7 +431,7 @@ ScanSourceDatabasePgClassTuple(HeapTupleData *tuple, Oid tbid, Oid dbid,
 			 classForm->oid);
 
 	/* Prepare a rel info element and add it to the list. */
-	relinfo = (CreateDBRelInfo *) palloc(sizeof(CreateDBRelInfo));
+	relinfo = palloc_object(CreateDBRelInfo);
 	if (OidIsValid(classForm->reltablespace))
 		relinfo->rlocator.spcOid = classForm->reltablespace;
 	else
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index f34868da5ab..e7182308130 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -364,7 +364,7 @@ filter_list_to_array(List *filterlist)
 	int			i = 0,
 				l = list_length(filterlist);
 
-	data = (Datum *) palloc(l * sizeof(Datum));
+	data = palloc_array(Datum, l);
 
 	foreach(lc, filterlist)
 	{
@@ -1286,7 +1286,7 @@ EventTriggerSQLDropAddObject(const ObjectAddress *object, bool original, bool no
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	obj = palloc0(sizeof(SQLDropObject));
+	obj = palloc0_object(SQLDropObject);
 	obj->address = *object;
 	obj->original = original;
 	obj->normal = normal;
@@ -1726,7 +1726,7 @@ EventTriggerCollectSimpleCommand(ObjectAddress address,
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc(sizeof(CollectedCommand));
+	command = palloc_object(CollectedCommand);
 
 	command->type = SCT_Simple;
 	command->in_extension = creating_extension;
@@ -1762,7 +1762,7 @@ EventTriggerAlterTableStart(Node *parsetree)
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc(sizeof(CollectedCommand));
+	command = palloc_object(CollectedCommand);
 
 	command->type = SCT_AlterTable;
 	command->in_extension = creating_extension;
@@ -1818,7 +1818,7 @@ EventTriggerCollectAlterTableSubcmd(Node *subcmd, ObjectAddress address)
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	newsub = palloc(sizeof(CollectedATSubcmd));
+	newsub = palloc_object(CollectedATSubcmd);
 	newsub->address = address;
 	newsub->parsetree = copyObject(subcmd);
 
@@ -1892,7 +1892,7 @@ EventTriggerCollectGrant(InternalGrant *istmt)
 	/*
 	 * This is tedious, but necessary.
 	 */
-	icopy = palloc(sizeof(InternalGrant));
+	icopy = palloc_object(InternalGrant);
 	memcpy(icopy, istmt, sizeof(InternalGrant));
 	icopy->objects = list_copy(istmt->objects);
 	icopy->grantees = list_copy(istmt->grantees);
@@ -1901,7 +1901,7 @@ EventTriggerCollectGrant(InternalGrant *istmt)
 		icopy->col_privs = lappend(icopy->col_privs, copyObject(lfirst(cell)));
 
 	/* Now collect it, using the copied InternalGrant */
-	command = palloc(sizeof(CollectedCommand));
+	command = palloc_object(CollectedCommand);
 	command->type = SCT_Grant;
 	command->in_extension = creating_extension;
 	command->d.grant.istmt = icopy;
@@ -1932,7 +1932,7 @@ EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc(sizeof(CollectedCommand));
+	command = palloc_object(CollectedCommand);
 	command->type = SCT_AlterOpFamily;
 	command->in_extension = creating_extension;
 	ObjectAddressSet(command->d.opfam.address,
@@ -1965,7 +1965,7 @@ EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt, Oid opcoid,
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc0(sizeof(CollectedCommand));
+	command = palloc0_object(CollectedCommand);
 	command->type = SCT_CreateOpClass;
 	command->in_extension = creating_extension;
 	ObjectAddressSet(command->d.createopc.address,
@@ -1999,12 +1999,12 @@ EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId,
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc0(sizeof(CollectedCommand));
+	command = palloc0_object(CollectedCommand);
 	command->type = SCT_AlterTSConfig;
 	command->in_extension = creating_extension;
 	ObjectAddressSet(command->d.atscfg.address,
 					 TSConfigRelationId, cfgId);
-	command->d.atscfg.dictIds = palloc(sizeof(Oid) * ndicts);
+	command->d.atscfg.dictIds = palloc_array(Oid, ndicts);
 	memcpy(command->d.atscfg.dictIds, dictIds, sizeof(Oid) * ndicts);
 	command->d.atscfg.ndicts = ndicts;
 	command->parsetree = (Node *) copyObject(stmt);
@@ -2033,7 +2033,7 @@ EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt)
 
 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
 
-	command = palloc0(sizeof(CollectedCommand));
+	command = palloc0_object(CollectedCommand);
 	command->type = SCT_AlterDefaultPrivileges;
 	command->d.defprivs.objtype = stmt->action->objtype;
 	command->in_extension = creating_extension;
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 7e699f8595e..5a6390631eb 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4980,7 +4980,7 @@ ExplainCreateWorkersState(int num_workers)
 {
 	ExplainWorkersState *wstate;
 
-	wstate = (ExplainWorkersState *) palloc(sizeof(ExplainWorkersState));
+	wstate = palloc_object(ExplainWorkersState);
 	wstate->num_workers = num_workers;
 	wstate->worker_inited = (bool *) palloc0(num_workers * sizeof(bool));
 	wstate->worker_str = (StringInfoData *)
diff --git a/src/backend/commands/explain_dr.c b/src/backend/commands/explain_dr.c
index 95685d7e88d..5833aa80fb5 100644
--- a/src/backend/commands/explain_dr.c
+++ b/src/backend/commands/explain_dr.c
@@ -276,7 +276,7 @@ CreateExplainSerializeDestReceiver(ExplainState *es)
 {
 	SerializeDestReceiver *self;
 
-	self = (SerializeDestReceiver *) palloc0(sizeof(SerializeDestReceiver));
+	self = palloc0_object(SerializeDestReceiver);
 
 	self->pub.receiveSlot = serializeAnalyzeReceive;
 	self->pub.rStartup = serializeAnalyzeStartup;
diff --git a/src/backend/commands/explain_state.c b/src/backend/commands/explain_state.c
index 9fdeeab6436..6e26ec9b31e 100644
--- a/src/backend/commands/explain_state.c
+++ b/src/backend/commands/explain_state.c
@@ -60,7 +60,7 @@ static int	ExplainExtensionOptionsAllocated = 0;
 ExplainState *
 NewExplainState(void)
 {
-	ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
+	ExplainState *es = palloc0_object(ExplainState);
 
 	/* Set default options (most fields can be left as zeroes). */
 	es->costs = true;
@@ -293,10 +293,7 @@ SetExplainExtensionState(ExplainState *es, int extension_id, void *opaque)
 		int			i;
 
 		i = pg_nextpower2_32(extension_id + 1);
-		es->extension_state = (void **)
-			repalloc0(es->extension_state,
-					  es->extension_state_allocated * sizeof(void *),
-					  i * sizeof(void *));
+		es->extension_state = repalloc0_array(es->extension_state, void *, es->extension_state_allocated, i);
 		es->extension_state_allocated = i;
 	}
 
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index ebc204c4462..c43b74e319e 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -724,7 +724,7 @@ read_extension_aux_control_file(const ExtensionControlFile *pcontrol,
 	/*
 	 * Flat-copy the struct.  Pointer fields share values with original.
 	 */
-	acontrol = (ExtensionControlFile *) palloc(sizeof(ExtensionControlFile));
+	acontrol = palloc_object(ExtensionControlFile);
 	memcpy(acontrol, pcontrol, sizeof(ExtensionControlFile));
 
 	/*
@@ -1349,7 +1349,7 @@ get_ext_ver_info(const char *versionname, List **evi_list)
 			return evi;
 	}
 
-	evi = (ExtensionVersionInfo *) palloc(sizeof(ExtensionVersionInfo));
+	evi = palloc_object(ExtensionVersionInfo);
 	evi->name = pstrdup(versionname);
 	evi->reachable = NIL;
 	evi->installable = false;
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 59d00638ee6..8a435cd93db 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -913,7 +913,7 @@ interpret_AS_clause(Oid languageOid, const char *languageName,
 	{
 		SQLFunctionParseInfoPtr pinfo;
 
-		pinfo = (SQLFunctionParseInfoPtr) palloc0(sizeof(SQLFunctionParseInfo));
+		pinfo = palloc0_object(SQLFunctionParseInfo);
 
 		pinfo->fname = funcname;
 		pinfo->nargs = list_length(parameterTypes);
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index ef7c0d624f1..f63f8753b05 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -463,7 +463,7 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
 DestReceiver *
 CreateTransientRelDestReceiver(Oid transientoid)
 {
-	DR_transientrel *self = (DR_transientrel *) palloc0(sizeof(DR_transientrel));
+	DR_transientrel *self = palloc0_object(DR_transientrel);
 
 	self->pub.receiveSlot = transientrel_receive;
 	self->pub.rStartup = transientrel_startup;
@@ -713,7 +713,7 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 	 * include all rows.
 	 */
 	tupdesc = matviewRel->rd_att;
-	opUsedForQual = (Oid *) palloc0(sizeof(Oid) * relnatts);
+	opUsedForQual = palloc0_array(Oid, relnatts);
 	foundUniqueIndex = false;
 
 	indexoidlist = RelationGetIndexList(matviewRel);
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index a6dd8eab518..992ae789b00 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -523,7 +523,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 #endif
 
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = false;
 				member->object = operOid;
 				member->number = item->number;
@@ -547,7 +547,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 								   get_func_name(funcOid));
 #endif
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = true;
 				member->object = funcOid;
 				member->number = item->number;
@@ -940,7 +940,7 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 #endif
 
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = false;
 				member->object = operOid;
 				member->number = item->number;
@@ -970,7 +970,7 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 #endif
 
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = true;
 				member->object = funcOid;
 				member->number = item->number;
@@ -1058,7 +1058,7 @@ AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 									item->number, maxOpNumber)));
 				processTypesSpec(item->class_args, &lefttype, &righttype);
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = false;
 				member->number = item->number;
 				member->lefttype = lefttype;
@@ -1074,7 +1074,7 @@ AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 									item->number, maxProcNumber)));
 				processTypesSpec(item->class_args, &lefttype, &righttype);
 				/* Save the info */
-				member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
+				member = palloc0_object(OpFamilyMember);
 				member->is_func = true;
 				member->number = item->number;
 				member->lefttype = lefttype;
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index 83056960fe4..5bd5f8c9968 100644
--- a/src/backend/commands/policy.c
+++ b/src/backend/commands/policy.c
@@ -144,7 +144,7 @@ policy_role_list_to_array(List *roles, int *num_roles)
 	if (roles == NIL)
 	{
 		*num_roles = 1;
-		role_oids = (Datum *) palloc(*num_roles * sizeof(Datum));
+		role_oids = palloc_array(Datum, *num_roles);
 		role_oids[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
 
 		return role_oids;
@@ -471,7 +471,7 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
 	 * Ordinarily there'd be exactly one, but we must cope with duplicate
 	 * mentions, since CREATE/ALTER POLICY historically have allowed that.
 	 */
-	role_oids = (Datum *) palloc(num_roles * sizeof(Datum));
+	role_oids = palloc_array(Datum, num_roles);
 	for (i = 0, j = 0; i < num_roles; i++)
 	{
 		if (roles[i] != roleid)
@@ -945,7 +945,7 @@ AlterPolicy(AlterPolicyStmt *stmt)
 
 		nitems = ARR_DIMS(policy_roles)[0];
 
-		role_oids = (Datum *) palloc(nitems * sizeof(Datum));
+		role_oids = palloc_array(Datum, nitems);
 
 		for (i = 0; i < nitems; i++)
 			role_oids[i] = ObjectIdGetDatum(roles[i]);
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 1faf3a8c372..a1983508950 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -1345,7 +1345,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
 			 */
 			if (!found)
 			{
-				oldrel = palloc(sizeof(PublicationRelInfo));
+				oldrel = palloc_object(PublicationRelInfo);
 				oldrel->whereClause = NULL;
 				oldrel->columns = NIL;
 				oldrel->relation = table_open(oldrelid,
@@ -1757,7 +1757,7 @@ OpenTableList(List *tables)
 			continue;
 		}
 
-		pub_rel = palloc(sizeof(PublicationRelInfo));
+		pub_rel = palloc_object(PublicationRelInfo);
 		pub_rel->relation = rel;
 		pub_rel->whereClause = t->whereClause;
 		pub_rel->columns = t->columns;
@@ -1826,7 +1826,7 @@ OpenTableList(List *tables)
 
 				/* find_all_inheritors already got lock */
 				rel = table_open(childrelid, NoLock);
-				pub_rel = palloc(sizeof(PublicationRelInfo));
+				pub_rel = palloc_object(PublicationRelInfo);
 				pub_rel->relation = rel;
 				/* child inherits WHERE clause from parent */
 				pub_rel->whereClause = t->whereClause;
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index cee5d7bbb9c..07bed6e1487 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -573,7 +573,7 @@ register_label_provider(const char *provider_name, check_object_relabel_type hoo
 	MemoryContext oldcxt;
 
 	oldcxt = MemoryContextSwitchTo(TopMemoryContext);
-	provider = palloc(sizeof(LabelProvider));
+	provider = palloc_object(LabelProvider);
 	provider->provider_name = pstrdup(provider_name);
 	provider->hook = hook;
 	label_provider_list = lappend(label_provider_list, provider);
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 8c856af3493..abbcaff0838 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -566,7 +566,7 @@ publicationListToArray(List *publist)
 								   ALLOCSET_DEFAULT_SIZES);
 	oldcxt = MemoryContextSwitchTo(memcxt);
 
-	datums = (Datum *) palloc(sizeof(Datum) * list_length(publist));
+	datums = palloc_array(Datum, list_length(publist));
 
 	check_duplicates_in_publist(publist, datums);
 
@@ -1055,7 +1055,7 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data,
 			{
 				char		state;
 				XLogRecPtr	statelsn;
-				SubRemoveRels *remove_rel = palloc(sizeof(SubRemoveRels));
+				SubRemoveRels *remove_rel = palloc_object(SubRemoveRels);
 
 				/*
 				 * Lock pg_subscription_rel with AccessExclusiveLock to
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 07e5b95782e..1c9ef53be20 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -999,7 +999,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 
 			Assert(colDef->cooked_default == NULL);
 
-			rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+			rawEnt = palloc_object(RawColumnDefault);
 			rawEnt->attnum = attnum;
 			rawEnt->raw_default = colDef->raw_default;
 			rawEnt->generated = colDef->generated;
@@ -1009,7 +1009,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 		{
 			CookedConstraint *cooked;
 
-			cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+			cooked = palloc_object(CookedConstraint);
 			cooked->contype = CONSTR_DEFAULT;
 			cooked->conoid = InvalidOid;	/* until created */
 			cooked->name = NULL;
@@ -6568,7 +6568,7 @@ ATGetQueueEntry(List **wqueue, Relation rel)
 	 * Not there, so add it.  Note that we make a copy of the relation's
 	 * existing descriptor before anything interesting can happen to it.
 	 */
-	tab = (AlteredTableInfo *) palloc0(sizeof(AlteredTableInfo));
+	tab = palloc0_object(AlteredTableInfo);
 	tab->relid = relid;
 	tab->rel = NULL;			/* set later */
 	tab->relkind = rel->rd_rel->relkind;
@@ -7406,7 +7406,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	{
 		RawColumnDefault *rawEnt;
 
-		rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+		rawEnt = palloc_object(RawColumnDefault);
 		rawEnt->attnum = attribute->attnum;
 		rawEnt->raw_default = copyObject(colDef->raw_default);
 		rawEnt->generated = colDef->generated;
@@ -7507,7 +7507,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 			defval = expression_planner(defval);
 
 			/* Add the new default to the newvals list */
-			newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
+			newval = palloc0_object(NewColumnValue);
 			newval->attnum = attribute->attnum;
 			newval->expr = defval;
 			newval->is_generated = (colDef->generated != '\0');
@@ -8176,7 +8176,7 @@ ATExecColumnDefault(Relation rel, const char *colName,
 		/* SET DEFAULT */
 		RawColumnDefault *rawEnt;
 
-		rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+		rawEnt = palloc_object(RawColumnDefault);
 		rawEnt->attnum = attnum;
 		rawEnt->raw_default = newDefault;
 		rawEnt->generated = '\0';
@@ -8704,7 +8704,7 @@ ATExecSetExpression(AlteredTableInfo *tab, Relation rel, const char *colName,
 					  false, false);
 
 	/* Prepare to store the new expression, in the catalogs */
-	rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+	rawEnt = palloc_object(RawColumnDefault);
 	rawEnt->attnum = attnum;
 	rawEnt->raw_default = newExpr;
 	rawEnt->generated = attgenerated;
@@ -8721,7 +8721,7 @@ ATExecSetExpression(AlteredTableInfo *tab, Relation rel, const char *colName,
 		/* Prepare for table rewrite */
 		defval = (Expr *) build_column_default(rel, attnum);
 
-		newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
+		newval = palloc0_object(NewColumnValue);
 		newval->attnum = attnum;
 		newval->expr = expression_planner(defval);
 		newval->is_generated = true;
@@ -9949,7 +9949,7 @@ ATAddCheckNNConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		{
 			NewConstraint *newcon;
 
-			newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+			newcon = palloc0_object(NewConstraint);
 			newcon->name = ccon->name;
 			newcon->contype = ccon->contype;
 			newcon->qual = ccon->expr;
@@ -10946,7 +10946,7 @@ addFkRecurseReferenced(Constraint *fkconstraint, Relation rel,
 											   false);
 			if (map)
 			{
-				mapped_pkattnum = palloc(sizeof(AttrNumber) * numfks);
+				mapped_pkattnum = palloc_array(AttrNumber, numfks);
 				for (int j = 0; j < numfks; j++)
 					mapped_pkattnum[j] = map->attnums[pkattnum[j] - 1];
 			}
@@ -11081,7 +11081,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
 
 			tab = ATGetQueueEntry(wqueue, rel);
 
-			newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+			newcon = palloc0_object(NewConstraint);
 			newcon->name = get_constraint_name(parentConstr);
 			newcon->contype = CONSTR_FOREIGN;
 			newcon->refrelid = RelationGetRelid(pkrel);
@@ -12503,7 +12503,7 @@ ATExecAlterConstrEnforceability(List **wqueue, ATAlterConstraint *cmdcon,
 			AlteredTableInfo *tab;
 			NewConstraint *newcon;
 
-			newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+			newcon = palloc0_object(NewConstraint);
 			newcon->name = fkconstraint->conname;
 			newcon->contype = CONSTR_FOREIGN;
 			newcon->refrelid = currcon->confrelid;
@@ -13019,7 +13019,7 @@ QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation fkrel,
 		/* for now this is all we need */
 		fkconstraint->conname = pstrdup(NameStr(con->conname));
 
-		newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+		newcon = palloc0_object(NewConstraint);
 		newcon->name = fkconstraint->conname;
 		newcon->contype = CONSTR_FOREIGN;
 		newcon->refrelid = con->confrelid;
@@ -13167,7 +13167,7 @@ QueueCheckConstraintValidation(List **wqueue, Relation conrel, Relation rel,
 	}
 
 	/* Queue validation for phase 3 */
-	newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+	newcon = palloc0_object(NewConstraint);
 	newcon->name = constrName;
 	newcon->contype = CONSTR_CHECK;
 	newcon->refrelid = InvalidOid;
@@ -14522,7 +14522,7 @@ ATPrepAlterColumnType(List **wqueue,
 		 * Add a work queue item to make ATRewriteTable update the column
 		 * contents.
 		 */
-		newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
+		newval = palloc0_object(NewColumnValue);
 		newval->attnum = attnum;
 		newval->expr = (Expr *) transform;
 		newval->is_generated = false;
@@ -19262,7 +19262,7 @@ register_on_commit_action(Oid relid, OnCommitAction action)
 
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
-	oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
+	oc = palloc_object(OnCommitItem);
 	oc->relid = relid;
 	oc->oncommit = action;
 	oc->creating_subid = GetCurrentSubTransactionId();
@@ -20575,8 +20575,8 @@ AttachPartitionEnsureIndexes(List **wqueue, Relation rel, Relation attachrel)
 
 	idxes = RelationGetIndexList(rel);
 	attachRelIdxs = RelationGetIndexList(attachrel);
-	attachrelIdxRels = palloc(sizeof(Relation) * list_length(attachRelIdxs));
-	attachInfos = palloc(sizeof(IndexInfo *) * list_length(attachRelIdxs));
+	attachrelIdxRels = palloc_array(Relation, list_length(attachRelIdxs));
+	attachInfos = palloc_array(IndexInfo *, list_length(attachRelIdxs));
 
 	/* Build arrays of all existing indexes and their IndexInfos */
 	foreach_oid(cldIdxId, attachRelIdxs)
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 579ac8d76ae..12c97f2c023 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -1991,7 +1991,7 @@ RelationBuildTriggers(Relation relation)
 	}
 
 	/* Build trigdesc */
-	trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
+	trigdesc = palloc0_object(TriggerDesc);
 	trigdesc->triggers = triggers;
 	trigdesc->numtriggers = numtrigs;
 	for (i = 0; i < numtrigs; i++)
@@ -2096,7 +2096,7 @@ CopyTriggerDesc(TriggerDesc *trigdesc)
 	if (trigdesc == NULL || trigdesc->numtriggers <= 0)
 		return NULL;
 
-	newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
+	newdesc = palloc_object(TriggerDesc);
 	memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
 
 	trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
@@ -4901,7 +4901,7 @@ GetAfterTriggersTableData(Oid relid, CmdType cmdType)
 
 	oldcxt = MemoryContextSwitchTo(CurTransactionContext);
 
-	table = (AfterTriggersTableData *) palloc0(sizeof(AfterTriggersTableData));
+	table = palloc0_object(AfterTriggersTableData);
 	table->relid = relid;
 	table->cmdType = cmdType;
 	qs->tables = lappend(qs->tables, table);
@@ -5050,7 +5050,7 @@ MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
 	MemoryContextSwitchTo(oldcxt);
 
 	/* Now build the TransitionCaptureState struct, in caller's context */
-	state = (TransitionCaptureState *) palloc0(sizeof(TransitionCaptureState));
+	state = palloc0_object(TransitionCaptureState);
 	state->tcs_delete_old_table = need_old_del;
 	state->tcs_update_old_table = need_old_upd;
 	state->tcs_update_new_table = need_new_upd;
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index dc7df736fb8..ec4580e17c9 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -1027,7 +1027,7 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
 		 * know that they will be used.
 		 */
 		max_slots = MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_ts_config_map);
-		slot = palloc(sizeof(TupleTableSlot *) * max_slots);
+		slot = palloc_array(TupleTableSlot *, max_slots);
 
 		ScanKeyInit(&skey,
 					Anum_pg_ts_config_map_mapcfg,
@@ -1261,7 +1261,7 @@ getTokenTypes(Oid prsId, List *tokennames)
 		{
 			if (strcmp(strVal(val), list[j].alias) == 0)
 			{
-				TSTokenTypeItem *ts = (TSTokenTypeItem *) palloc0(sizeof(TSTokenTypeItem));
+				TSTokenTypeItem *ts = palloc0_object(TSTokenTypeItem);
 
 				ts->num = list[j].lexid;
 				ts->name = pstrdup(strVal(val));
@@ -1344,7 +1344,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
 	 * Convert list of dictionary names to array of dict OIDs
 	 */
 	ndict = list_length(stmt->dicts);
-	dictIds = (Oid *) palloc(sizeof(Oid) * ndict);
+	dictIds = palloc_array(Oid, ndict);
 	i = 0;
 	foreach(c, stmt->dicts)
 	{
@@ -1432,7 +1432,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
 		/* Allocate the slots to use and initialize them */
 		nslots = Min(ntoken * ndict,
 					 MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_ts_config_map));
-		slot = palloc(sizeof(TupleTableSlot *) * nslots);
+		slot = palloc_array(TupleTableSlot *, nslots);
 		for (i = 0; i < nslots; i++)
 			slot[i] = MakeSingleTupleTableSlot(RelationGetDescr(relMap),
 											   &TTSOpsHeapTuple);
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 47d5047fe8b..0eb8e0a2bb0 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -3447,10 +3447,10 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode)
 			}
 
 			/* Build the RelToCheck entry with enough space for all atts */
-			rtc = (RelToCheck *) palloc(sizeof(RelToCheck));
+			rtc = palloc_object(RelToCheck);
 			rtc->rel = rel;
 			rtc->natts = 0;
-			rtc->atts = (int *) palloc(sizeof(int) * RelationGetNumberOfAttributes(rel));
+			rtc->atts = palloc_array(int, RelationGetNumberOfAttributes(rel));
 			result = lappend(result, rtc);
 		}
 
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 6ae42ea5656..ef4de1e7fd1 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -1904,7 +1904,7 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
 		else
 		{
 			Oid			objectId;
-			Oid		   *newmembers = palloc(sizeof(Oid));
+			Oid		   *newmembers = palloc_object(Oid);
 
 			/*
 			 * The values for these options can be taken directly from 'popt'.
@@ -2295,7 +2295,7 @@ initialize_revoke_actions(CatCList *memlist)
 	if (memlist->n_members == 0)
 		return NULL;
 
-	result = palloc(sizeof(RevokeRoleGrantAction) * memlist->n_members);
+	result = palloc_array(RevokeRoleGrantAction, memlist->n_members);
 	for (i = 0; i < memlist->n_members; i++)
 		result[i] = RRG_NOOP;
 	return result;
diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c
index 0feea1d30ec..8a37c08871a 100644
--- a/src/backend/commands/vacuumparallel.c
+++ b/src/backend/commands/vacuumparallel.c
@@ -268,7 +268,7 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes,
 	/*
 	 * Compute the number of parallel vacuum workers to launch
 	 */
-	will_parallel_vacuum = (bool *) palloc0(sizeof(bool) * nindexes);
+	will_parallel_vacuum = palloc0_array(bool, nindexes);
 	parallel_workers = parallel_vacuum_compute_workers(indrels, nindexes,
 													   nrequested_workers,
 													   will_parallel_vacuum);
@@ -279,7 +279,7 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes,
 		return NULL;
 	}
 
-	pvs = (ParallelVacuumState *) palloc0(sizeof(ParallelVacuumState));
+	pvs = palloc0_object(ParallelVacuumState);
 	pvs->indrels = indrels;
 	pvs->nindexes = nindexes;
 	pvs->will_parallel_vacuum = will_parallel_vacuum;
@@ -444,7 +444,7 @@ parallel_vacuum_end(ParallelVacuumState *pvs, IndexBulkDeleteResult **istats)
 
 		if (indstats->istat_updated)
 		{
-			istats[i] = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+			istats[i] = palloc0_object(IndexBulkDeleteResult);
 			memcpy(istats[i], &indstats->istat, sizeof(IndexBulkDeleteResult));
 		}
 		else
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index b05ff476a63..c35744b105e 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -1312,7 +1312,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				}
 
 				/* Set up the primary fmgr lookup information */
-				finfo = palloc0(sizeof(FmgrInfo));
+				finfo = palloc0_object(FmgrInfo);
 				fcinfo = palloc0(SizeForFunctionCallInfo(2));
 				fmgr_info(cmpfuncid, finfo);
 				fmgr_info_set_expr((Node *) node, finfo);
@@ -1388,7 +1388,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				/* allocate scratch memory used by all steps of AND/OR */
 				if (boolexpr->boolop != NOT_EXPR)
-					scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool));
+					scratch.d.boolexpr.anynull = palloc_object(bool);
 
 				/*
 				 * For each argument evaluate the argument itself, then
@@ -1521,11 +1521,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				ReleaseTupleDesc(tupDesc);
 
 				/* create workspace for column values */
-				values = (Datum *) palloc(sizeof(Datum) * ncolumns);
-				nulls = (bool *) palloc(sizeof(bool) * ncolumns);
+				values = palloc_array(Datum, ncolumns);
+				nulls = palloc_array(bool, ncolumns);
 
 				/* create shared composite-type-lookup cache struct */
-				rowcachep = palloc(sizeof(ExprEvalRowtypeCache));
+				rowcachep = palloc_object(ExprEvalRowtypeCache);
 				rowcachep->cacheptr = NULL;
 
 				/* emit code to evaluate the composite input value */
@@ -1634,7 +1634,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 					scratch.opcode = EEOP_IOCOERCE_SAFE;
 
 				/* lookup the source type's output function */
-				scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
+				scratch.d.iocoerce.finfo_out = palloc0_object(FmgrInfo);
 				scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfo(1));
 
 				getTypeOutputInfo(exprType((Node *) iocoerce->arg),
@@ -1646,7 +1646,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 										 1, InvalidOid, NULL, NULL);
 
 				/* lookup the result type's input function */
-				scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
+				scratch.d.iocoerce.finfo_in = palloc0_object(FmgrInfo);
 				scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3));
 
 				getTypeInputInfo(iocoerce->resulttype,
@@ -1699,8 +1699,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				elemstate->parent = state->parent;
 				elemstate->ext_params = state->ext_params;
 
-				elemstate->innermost_caseval = (Datum *) palloc(sizeof(Datum));
-				elemstate->innermost_casenull = (bool *) palloc(sizeof(bool));
+				elemstate->innermost_caseval = palloc_object(Datum);
+				elemstate->innermost_casenull = palloc_object(bool);
 
 				ExecInitExprRec(acoerce->elemexpr, elemstate,
 								&elemstate->resvalue, &elemstate->resnull);
@@ -1727,8 +1727,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				if (elemstate)
 				{
 					/* Set up workspace for array_map */
-					scratch.d.arraycoerce.amstate =
-						(ArrayMapState *) palloc0(sizeof(ArrayMapState));
+					scratch.d.arraycoerce.amstate = palloc0_object(ArrayMapState);
 				}
 				else
 				{
@@ -1783,8 +1782,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				if (caseExpr->arg != NULL)
 				{
 					/* Evaluate testexpr into caseval/casenull workspace */
-					caseval = palloc(sizeof(Datum));
-					casenull = palloc(sizeof(bool));
+					caseval = palloc_object(Datum);
+					casenull = palloc_object(bool);
 
 					ExecInitExprRec(caseExpr->arg, state,
 									caseval, casenull);
@@ -1930,9 +1929,9 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				 */
 				scratch.opcode = EEOP_ARRAYEXPR;
 				scratch.d.arrayexpr.elemvalues =
-					(Datum *) palloc(sizeof(Datum) * nelems);
+					palloc_array(Datum, nelems);
 				scratch.d.arrayexpr.elemnulls =
-					(bool *) palloc(sizeof(bool) * nelems);
+					palloc_array(bool, nelems);
 				scratch.d.arrayexpr.nelems = nelems;
 
 				/* fill remaining fields of step */
@@ -2006,9 +2005,9 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				/* space for the individual field datums */
 				scratch.d.row.elemvalues =
-					(Datum *) palloc(sizeof(Datum) * nelems);
+					palloc_array(Datum, nelems);
 				scratch.d.row.elemnulls =
-					(bool *) palloc(sizeof(bool) * nelems);
+					palloc_array(bool, nelems);
 				/* as explained above, make sure any extra columns are null */
 				memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems);
 
@@ -2109,7 +2108,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 							 BTORDER_PROC, lefttype, righttype, opfamily);
 
 					/* Set up the primary fmgr lookup information */
-					finfo = palloc0(sizeof(FmgrInfo));
+					finfo = palloc0_object(FmgrInfo);
 					fcinfo = palloc0(SizeForFunctionCallInfo(2));
 					fmgr_info(proc, finfo);
 					fmgr_info_set_expr((Node *) node, finfo);
@@ -2252,7 +2251,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				 */
 
 				/* Perform function lookup */
-				finfo = palloc0(sizeof(FmgrInfo));
+				finfo = palloc0_object(FmgrInfo);
 				fcinfo = palloc0(SizeForFunctionCallInfo(2));
 				fmgr_info(typentry->cmp_proc, finfo);
 				fmgr_info_set_expr((Node *) node, finfo);
@@ -2261,10 +2260,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				scratch.opcode = EEOP_MINMAX;
 				/* allocate space to store arguments */
-				scratch.d.minmax.values =
-					(Datum *) palloc(sizeof(Datum) * nelems);
-				scratch.d.minmax.nulls =
-					(bool *) palloc(sizeof(bool) * nelems);
+				scratch.d.minmax.values = palloc_array(Datum, nelems);
+				scratch.d.minmax.nulls = palloc_array(bool, nelems);
 				scratch.d.minmax.nelems = nelems;
 
 				scratch.d.minmax.op = minmaxexpr->op;
@@ -2313,10 +2310,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				/* allocate space for storing all the arguments */
 				if (nnamed)
 				{
-					scratch.d.xmlexpr.named_argvalue =
-						(Datum *) palloc(sizeof(Datum) * nnamed);
-					scratch.d.xmlexpr.named_argnull =
-						(bool *) palloc(sizeof(bool) * nnamed);
+					scratch.d.xmlexpr.named_argvalue = palloc_array(Datum, nnamed);
+					scratch.d.xmlexpr.named_argnull = palloc_array(bool, nnamed);
 				}
 				else
 				{
@@ -2326,10 +2321,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				if (nargs)
 				{
-					scratch.d.xmlexpr.argvalue =
-						(Datum *) palloc(sizeof(Datum) * nargs);
-					scratch.d.xmlexpr.argnull =
-						(bool *) palloc(sizeof(bool) * nargs);
+					scratch.d.xmlexpr.argvalue = palloc_array(Datum, nargs);
+					scratch.d.xmlexpr.argnull = palloc_array(bool, nargs);
 				}
 				else
 				{
@@ -2398,15 +2391,15 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				{
 					JsonConstructorExprState *jcstate;
 
-					jcstate = palloc0(sizeof(JsonConstructorExprState));
+					jcstate = palloc0_object(JsonConstructorExprState);
 
 					scratch.opcode = EEOP_JSON_CONSTRUCTOR;
 					scratch.d.json_constructor.jcstate = jcstate;
 
 					jcstate->constructor = ctor;
-					jcstate->arg_values = (Datum *) palloc(sizeof(Datum) * nargs);
-					jcstate->arg_nulls = (bool *) palloc(sizeof(bool) * nargs);
-					jcstate->arg_types = (Oid *) palloc(sizeof(Oid) * nargs);
+					jcstate->arg_values = palloc_array(Datum, nargs);
+					jcstate->arg_nulls = palloc_array(bool, nargs);
+					jcstate->arg_types = palloc_array(Oid, nargs);
 					jcstate->nargs = nargs;
 
 					foreach(lc, args)
@@ -2680,7 +2673,7 @@ ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
 	if (es->steps_alloc == 0)
 	{
 		es->steps_alloc = 16;
-		es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
+		es->steps = palloc_array(ExprEvalStep, es->steps_alloc);
 	}
 	else if (es->steps_alloc == es->steps_len)
 	{
@@ -2732,7 +2725,7 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
 							   FUNC_MAX_ARGS)));
 
 	/* Allocate function lookup data and parameter workspace for this call */
-	scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
+	scratch->d.func.finfo = palloc0_object(FmgrInfo);
 	scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs));
 	flinfo = scratch->d.func.finfo;
 	fcinfo = scratch->d.func.fcinfo_data;
@@ -3557,8 +3550,7 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
 	 * during executor initialization.  That means we don't need typcache.c to
 	 * provide compiled exprs.
 	 */
-	constraint_ref = (DomainConstraintRef *)
-		palloc(sizeof(DomainConstraintRef));
+	constraint_ref = palloc_object(DomainConstraintRef);
 	InitDomainConstraintRef(ctest->resulttype,
 							constraint_ref,
 							CurrentMemoryContext,
@@ -3588,9 +3580,9 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
 				if (scratch->d.domaincheck.checkvalue == NULL)
 				{
 					scratch->d.domaincheck.checkvalue =
-						(Datum *) palloc(sizeof(Datum));
+						palloc_object(Datum);
 					scratch->d.domaincheck.checknull =
-						(bool *) palloc(sizeof(bool));
+						palloc_object(bool);
 				}
 
 				/*
@@ -3608,8 +3600,8 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
 						ExprEvalStep scratch2 = {0};
 
 						/* Yes, so make output workspace for MAKE_READONLY */
-						domainval = (Datum *) palloc(sizeof(Datum));
-						domainnull = (bool *) palloc(sizeof(bool));
+						domainval = palloc_object(Datum);
+						domainnull = palloc_object(bool);
 
 						/* Emit MAKE_READONLY */
 						scratch2.opcode = EEOP_MAKE_READONLY;
@@ -4159,7 +4151,7 @@ ExecBuildHash32FromAttrs(TupleDesc desc, const TupleTableSlotOps *ops,
 	 * one column to hash or an initial value plus one column.
 	 */
 	if ((int64) numCols + (init_value != 0) > 1)
-		iresult = palloc(sizeof(NullableDatum));
+		iresult = palloc_object(NullableDatum);
 
 	/* find the highest attnum so we deform the tuple to that point */
 	for (int i = 0; i < numCols; i++)
@@ -4325,7 +4317,7 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops,
 	 * than one expression to hash or an initial value plus one expression.
 	 */
 	if ((int64) num_exprs + (init_value != 0) > 1)
-		iresult = palloc(sizeof(NullableDatum));
+		iresult = palloc_object(NullableDatum);
 
 	if (init_value == 0)
 	{
@@ -4371,7 +4363,7 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops,
 		funcid = hashfunc_oids[i];
 
 		/* Allocate hash function lookup data. */
-		finfo = palloc0(sizeof(FmgrInfo));
+		finfo = palloc0_object(FmgrInfo);
 		fcinfo = palloc0(SizeForFunctionCallInfo(1));
 
 		fmgr_info(funcid, finfo);
@@ -4540,7 +4532,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
 		InvokeFunctionExecuteHook(foid);
 
 		/* Set up the primary fmgr lookup information */
-		finfo = palloc0(sizeof(FmgrInfo));
+		finfo = palloc0_object(FmgrInfo);
 		fcinfo = palloc0(SizeForFunctionCallInfo(2));
 		fmgr_info(foid, finfo);
 		fmgr_info_set_expr(NULL, finfo);
@@ -4676,7 +4668,7 @@ ExecBuildParamSetEqual(TupleDesc desc,
 		InvokeFunctionExecuteHook(foid);
 
 		/* Set up the primary fmgr lookup information */
-		finfo = palloc0(sizeof(FmgrInfo));
+		finfo = palloc0_object(FmgrInfo);
 		fcinfo = palloc0(SizeForFunctionCallInfo(2));
 		fmgr_info(foid, finfo);
 		fmgr_info_set_expr(NULL, finfo);
@@ -4749,7 +4741,7 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
 				 Datum *resv, bool *resnull,
 				 ExprEvalStep *scratch)
 {
-	JsonExprState *jsestate = palloc0(sizeof(JsonExprState));
+	JsonExprState *jsestate = palloc0_object(JsonExprState);
 	ListCell   *argexprlc;
 	ListCell   *argnamelc;
 	List	   *jumps_return_null = NIL;
@@ -4800,7 +4792,7 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
 	{
 		Expr	   *argexpr = (Expr *) lfirst(argexprlc);
 		String	   *argname = lfirst_node(String, argnamelc);
-		JsonPathVariable *var = palloc(sizeof(*var));
+		JsonPathVariable *var = palloc_object(JsonPathVariable);
 
 		var->name = argname->sval;
 		var->namelen = strlen(var->name);
@@ -4874,7 +4866,7 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
 		FunctionCallInfo fcinfo;
 
 		getTypeInputInfo(jsexpr->returning->typid, &typinput, &typioparam);
-		finfo = palloc0(sizeof(FmgrInfo));
+		finfo = palloc0_object(FmgrInfo);
 		fcinfo = palloc0(SizeForFunctionCallInfo(3));
 		fmgr_info(typinput, finfo);
 		fmgr_info_set_expr((Node *) jsexpr->returning, finfo);
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 8b64a625ca5..3336ddaff79 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -224,7 +224,7 @@ BuildTupleHashTable(PlanState *parent,
 
 	oldcontext = MemoryContextSwitchTo(metacxt);
 
-	hashtable = (TupleHashTable) palloc(sizeof(TupleHashTableData));
+	hashtable = (TupleHashTable) palloc_object(TupleHashTableData);
 
 	hashtable->numCols = numCols;
 	hashtable->keyColIdx = keyColIdx;
diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c
index dd323c9b9fd..0b3a31f1703 100644
--- a/src/backend/executor/execIndexing.c
+++ b/src/backend/executor/execIndexing.c
@@ -188,8 +188,8 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
 	/*
 	 * allocate space for result arrays
 	 */
-	relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
-	indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));
+	relationDescs = palloc_array(Relation, len);
+	indexInfoArray = palloc_array(IndexInfo *, len);
 
 	resultRelInfo->ri_NumIndices = len;
 	resultRelInfo->ri_IndexRelationDescs = relationDescs;
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 27c9eec697b..3ae349cc8f8 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -189,7 +189,7 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
 
 		nParamExec = list_length(queryDesc->plannedstmt->paramExecTypes);
 		estate->es_param_exec_vals = (ParamExecData *)
-			palloc0(nParamExec * sizeof(ParamExecData));
+			palloc0_array(ParamExecData, nParamExec);
 	}
 
 	/* We now require all callers to provide sourceText */
@@ -876,7 +876,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
 	if (plannedstmt->rowMarks)
 	{
 		estate->es_rowmarks = (ExecRowMark **)
-			palloc0(estate->es_range_table_size * sizeof(ExecRowMark *));
+			palloc0_array(ExecRowMark *, estate->es_range_table_size);
 		foreach(l, plannedstmt->rowMarks)
 		{
 			PlanRowMark *rc = (PlanRowMark *) lfirst(l);
@@ -920,7 +920,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
 			if (relation)
 				CheckValidRowMarkRel(relation, rc->markType);
 
-			erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
+			erm = palloc_object(ExecRowMark);
 			erm->relation = relation;
 			erm->relid = relid;
 			erm->rti = rc->rti;
@@ -1262,9 +1262,9 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
 		int			n = resultRelInfo->ri_TrigDesc->numtriggers;
 
 		resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
-			palloc0(n * sizeof(FmgrInfo));
+			palloc0_array(FmgrInfo, n);
 		resultRelInfo->ri_TrigWhenExprs = (ExprState **)
-			palloc0(n * sizeof(ExprState *));
+			palloc0_array(ExprState *, n);
 		if (instrument_options)
 			resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options, false);
 	}
@@ -2578,7 +2578,7 @@ ExecFindRowMark(EState *estate, Index rti, bool missing_ok)
 ExecAuxRowMark *
 ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
 {
-	ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
+	ExecAuxRowMark *aerm = palloc0_object(ExecAuxRowMark);
 	char		resname[32];
 
 	aerm->rowmark = erm;
@@ -2735,7 +2735,7 @@ EvalPlanQualInit(EPQState *epqstate, EState *parentestate,
 	 */
 	epqstate->tuple_table = NIL;
 	epqstate->relsubs_slot = (TupleTableSlot **)
-		palloc0(rtsize * sizeof(TupleTableSlot *));
+		palloc0_array(TupleTableSlot *, rtsize);
 
 	/* ... and remember data that EvalPlanQualBegin will need */
 	epqstate->plan = subplan;
@@ -3075,7 +3075,7 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
 		/* now make the internal param workspace ... */
 		i = list_length(parentestate->es_plannedstmt->paramExecTypes);
 		rcestate->es_param_exec_vals = (ParamExecData *)
-			palloc0(i * sizeof(ParamExecData));
+			palloc0_array(ParamExecData, i);
 		/* ... and copy down all values, whether really needed or not */
 		while (--i >= 0)
 		{
@@ -3131,7 +3131,7 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
 	 * rowmark.
 	 */
 	epqstate->relsubs_rowmark = (ExecAuxRowMark **)
-		palloc0(rtsize * sizeof(ExecAuxRowMark *));
+		palloc0_array(ExecAuxRowMark *, rtsize);
 	foreach(l, epqstate->arowMarks)
 	{
 		ExecAuxRowMark *earm = (ExecAuxRowMark *) lfirst(l);
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index 0125464d942..26200c5a3d6 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -647,7 +647,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate,
 	ExecSetParamPlanMulti(sendParams, GetPerTupleExprContext(estate));
 
 	/* Allocate object for return value. */
-	pei = palloc0(sizeof(ParallelExecutorInfo));
+	pei = palloc0_object(ParallelExecutorInfo);
 	pei->finished = false;
 	pei->planstate = planstate;
 
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
index def32774c90..860f79f9cc1 100644
--- a/src/backend/executor/execReplication.c
+++ b/src/backend/executor/execReplication.c
@@ -221,7 +221,7 @@ retry:
 		if (!isIdxSafeToSkipDuplicates)
 		{
 			if (eq == NULL)
-				eq = palloc0(sizeof(*eq) * outslot->tts_tupleDescriptor->natts);
+				eq = palloc0_array(TypeCacheEntry *, outslot->tts_tupleDescriptor->natts);
 
 			if (!tuples_equal(outslot, searchslot, eq, NULL))
 				continue;
@@ -378,7 +378,7 @@ RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode,
 
 	Assert(equalTupleDescs(desc, outslot->tts_tupleDescriptor));
 
-	eq = palloc0(sizeof(*eq) * outslot->tts_tupleDescriptor->natts);
+	eq = palloc0_array(TypeCacheEntry *, outslot->tts_tupleDescriptor->natts);
 
 	/* Start a heap scan. */
 	InitDirtySnapshot(snap);
@@ -593,7 +593,7 @@ RelationFindDeletedTupleInfoSeq(Relation rel, TupleTableSlot *searchslot,
 		indexbitmap = RelationGetIndexAttrBitmap(rel,
 												 INDEX_ATTR_BITMAP_PRIMARY_KEY);
 
-	eq = palloc0(sizeof(*eq) * searchslot->tts_tupleDescriptor->natts);
+	eq = palloc0_array(TypeCacheEntry *, searchslot->tts_tupleDescriptor->natts);
 
 	/*
 	 * Start a heap scan using SnapshotAny to identify dead tuples that are
@@ -679,7 +679,7 @@ RelationFindDeletedTupleInfoByIndex(Relation rel, Oid idxoid,
 		if (!isIdxSafeToSkipDuplicates)
 		{
 			if (eq == NULL)
-				eq = palloc0(sizeof(*eq) * scanslot->tts_tupleDescriptor->natts);
+				eq = palloc0_array(TypeCacheEntry *, scanslot->tts_tupleDescriptor->natts);
 
 			if (!tuples_equal(scanslot, searchslot, eq, NULL))
 				continue;
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 8e02d68824f..b0dc2cfa66f 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -2283,7 +2283,7 @@ TupleDescGetAttInMetadata(TupleDesc tupdesc)
 	int32	   *atttypmods;
 	AttInMetadata *attinmeta;
 
-	attinmeta = (AttInMetadata *) palloc(sizeof(AttInMetadata));
+	attinmeta = palloc_object(AttInMetadata);
 
 	/* "Bless" the tupledesc so that we can make rowtype datums with it */
 	attinmeta->tupdesc = BlessTupleDesc(tupdesc);
@@ -2447,7 +2447,7 @@ begin_tup_output_tupdesc(DestReceiver *dest,
 {
 	TupOutputState *tstate;
 
-	tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
+	tstate = palloc_object(TupOutputState);
 
 	tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
 	tstate->dest = dest;
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 630d708d2a3..64e2ada7960 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -256,7 +256,7 @@ prepare_sql_fn_parse_info(HeapTuple procedureTuple,
 	Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
 	int			nargs;
 
-	pinfo = (SQLFunctionParseInfoPtr) palloc0(sizeof(SQLFunctionParseInfo));
+	pinfo = (SQLFunctionParseInfoPtr) palloc0_object(SQLFunctionParseInfo); 
 
 	/* Function's name (only) can be used to qualify argument names */
 	pinfo->fname = pstrdup(NameStr(procedureStruct->proname));
@@ -2616,7 +2616,7 @@ get_sql_fn_result_tlist(List *queryTreeList)
 DestReceiver *
 CreateSQLFunctionDestReceiver(void)
 {
-	DR_sqlfunction *self = (DR_sqlfunction *) palloc0(sizeof(DR_sqlfunction));
+	DR_sqlfunction *self = palloc0_object(DR_sqlfunction);
 
 	self->pub.receiveSlot = sqlfunction_receive;
 	self->pub.rStartup = sqlfunction_startup;
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 0b02fd32107..a18556f62ec 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1920,7 +1920,7 @@ hash_agg_enter_spill_mode(AggState *aggstate)
 
 		aggstate->hash_tapeset = LogicalTapeSetCreate(true, NULL, -1);
 
-		aggstate->hash_spills = palloc(sizeof(HashAggSpill) * aggstate->num_hashes);
+		aggstate->hash_spills = palloc_array(HashAggSpill, aggstate->num_hashes);
 
 		for (int setno = 0; setno < aggstate->num_hashes; setno++)
 		{
@@ -2999,9 +2999,9 @@ hashagg_spill_init(HashAggSpill *spill, LogicalTapeSet *tapeset, int used_bits,
 	}
 #endif
 
-	spill->partitions = palloc0(sizeof(LogicalTape *) * npartitions);
-	spill->ntuples = palloc0(sizeof(int64) * npartitions);
-	spill->hll_card = palloc0(sizeof(hyperLogLogState) * npartitions);
+	spill->partitions = palloc0_array(LogicalTape *, npartitions);
+	spill->ntuples = palloc0_array(int64, npartitions);
+	spill->hll_card = palloc0_array(hyperLogLogState, npartitions);
 
 	for (int i = 0; i < npartitions; i++)
 		spill->partitions[i] = LogicalTapeCreate(tapeset);
@@ -3097,7 +3097,7 @@ static HashAggBatch *
 hashagg_batch_new(LogicalTape *input_tape, int setno,
 				  int64 input_tuples, double input_card, int used_bits)
 {
-	HashAggBatch *batch = palloc0(sizeof(HashAggBatch));
+	HashAggBatch *batch = palloc0_object(HashAggBatch);
 
 	batch->setno = setno;
 	batch->used_bits = used_bits;
@@ -3368,8 +3368,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	aggstate->maxsets = numGroupingSets;
 	aggstate->numphases = numPhases;
 
-	aggstate->aggcontexts = (ExprContext **)
-		palloc0(sizeof(ExprContext *) * numGroupingSets);
+	aggstate->aggcontexts = palloc0_array(ExprContext *, numGroupingSets);
 
 	/*
 	 * Create expression contexts.  We need three or more, one for
@@ -3492,15 +3491,15 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	 * For each phase, prepare grouping set data and fmgr lookup data for
 	 * compare functions.  Accumulate all_grouped_cols in passing.
 	 */
-	aggstate->phases = palloc0(numPhases * sizeof(AggStatePerPhaseData));
+	aggstate->phases = palloc0_array(AggStatePerPhaseData, numPhases);
 
 	aggstate->num_hashes = numHashes;
 	if (numHashes)
 	{
-		aggstate->perhash = palloc0(sizeof(AggStatePerHashData) * numHashes);
+		aggstate->perhash = palloc0_array(AggStatePerHashData, numHashes);
 		aggstate->phases[0].numsets = 0;
-		aggstate->phases[0].gset_lengths = palloc(numHashes * sizeof(int));
-		aggstate->phases[0].grouped_cols = palloc(numHashes * sizeof(Bitmapset *));
+		aggstate->phases[0].gset_lengths = palloc_array(int, numHashes);
+		aggstate->phases[0].grouped_cols = palloc_array(Bitmapset *, numHashes);
 	}
 
 	phase = 0;
@@ -3598,8 +3597,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 				 * Build a separate function for each subset of columns that
 				 * need to be compared.
 				 */
-				phasedata->eqfunctions =
-					(ExprState **) palloc0(aggnode->numCols * sizeof(ExprState *));
+				phasedata->eqfunctions = palloc0_array(ExprState *, aggnode->numCols);
 
 				/* for each grouping set */
 				for (int k = 0; k < phasedata->numsets; k++)
@@ -3655,27 +3653,24 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	 * allocate my private per-agg working storage
 	 */
 	econtext = aggstate->ss.ps.ps_ExprContext;
-	econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
-	econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
+	econtext->ecxt_aggvalues = palloc0_array(Datum, numaggs);
+	econtext->ecxt_aggnulls = palloc0_array(bool, numaggs);
 
-	peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
-	pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numtrans);
+	peraggs = palloc0_array(AggStatePerAggData, numaggs);
+	pertransstates = palloc0_array(AggStatePerTransData, numtrans);
 
 	aggstate->peragg = peraggs;
 	aggstate->pertrans = pertransstates;
 
 
-	aggstate->all_pergroups =
-		(AggStatePerGroup *) palloc0(sizeof(AggStatePerGroup)
-									 * (numGroupingSets + numHashes));
+	aggstate->all_pergroups = palloc0_array(AggStatePerGroup, numGroupingSets + numHashes);
 	pergroups = aggstate->all_pergroups;
 
 	if (node->aggstrategy != AGG_HASHED)
 	{
 		for (i = 0; i < numGroupingSets; i++)
 		{
-			pergroups[i] = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
-													  * numaggs);
+			pergroups[i] = palloc0_array(AggStatePerGroupData, numaggs);
 		}
 
 		aggstate->pergroups = pergroups;
@@ -4375,8 +4370,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 		pfree(ops);
 	}
 
-	pertrans->sortstates = (Tuplesortstate **)
-		palloc0(sizeof(Tuplesortstate *) * numGroupingSets);
+	pertrans->sortstates = palloc0_array(Tuplesortstate *, numGroupingSets);
 }
 
 
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index a11b36c7176..77c4dd9e4b1 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -263,7 +263,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
 		{
 			AsyncRequest *areq;
 
-			areq = palloc(sizeof(AsyncRequest));
+			areq = palloc_object(AsyncRequest);
 			areq->requestor = (PlanState *) appendstate;
 			areq->requestee = appendplanstates[i];
 			areq->request_index = i;
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 644363582d9..af75dd8fc5e 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -333,7 +333,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 	 */
 	ExecAssignExprContext(estate, &scanstate->ss.ps);
 
-	scanstate->funcstates = palloc(nfuncs * sizeof(FunctionScanPerFuncState));
+	scanstate->funcstates = palloc_array(FunctionScanPerFuncState, nfuncs);
 
 	natts = 0;
 	i = 0;
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
index 93f3dbc6cf4..c04522fea4d 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -145,8 +145,7 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
 		int			i;
 
 		gm_state->gm_nkeys = node->numCols;
-		gm_state->gm_sortkeys =
-			palloc0(sizeof(SortSupportData) * node->numCols);
+		gm_state->gm_sortkeys = palloc0_array(SortSupportData, node->numCols);
 
 		for (i = 0; i < node->numCols; i++)
 		{
@@ -418,8 +417,7 @@ gather_merge_setup(GatherMergeState *gm_state)
 	for (i = 0; i < nreaders; i++)
 	{
 		/* Allocate the tuple array with length MAX_TUPLE_STORE */
-		gm_state->gm_tuple_buffers[i].tuple =
-			(MinimalTuple *) palloc0(sizeof(MinimalTuple) * MAX_TUPLE_STORE);
+		gm_state->gm_tuple_buffers[i].tuple = palloc0_array(MinimalTuple, MAX_TUPLE_STORE);
 
 		/* Initialize tuple slot for worker */
 		gm_state->gm_slots[i + 1] =
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 5661ad76830..cc50bee19eb 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -899,7 +899,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
 		 */
 		if (OidIsValid(hash->skewTable))
 		{
-			hashstate->skew_hashfunction = palloc0(sizeof(FmgrInfo));
+			hashstate->skew_hashfunction = palloc0_object(FmgrInfo);
 			hashstate->skew_collation = linitial_oid(node->hashcollations);
 			fmgr_info(outer_hashfuncid[0], hashstate->skew_hashfunction);
 		}
@@ -1541,8 +1541,7 @@ ExecReScanHashJoin(HashJoinState *node)
 			/* accumulate stats from old hash table, if wanted */
 			/* (this should match ExecShutdownHash) */
 			if (hashNode->ps.instrument && !hashNode->hinstrument)
-				hashNode->hinstrument = (HashInstrumentation *)
-					palloc0(sizeof(HashInstrumentation));
+				hashNode->hinstrument = palloc0_object(HashInstrumentation);
 			if (hashNode->hinstrument)
 				ExecHashAccumInstrumentation(hashNode->hinstrument,
 											 hashNode->hashtable);
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index f464cca9507..6bea42f128f 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -693,8 +693,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 		 * Now create an array to mark the attribute numbers of the keys that
 		 * need to be converted from cstring to name.
 		 */
-		indexstate->ioss_NameCStringAttNums = (AttrNumber *)
-			palloc(sizeof(AttrNumber) * namecount);
+		indexstate->ioss_NameCStringAttNums = palloc_array(AttrNumber, namecount);
 
 		for (int attnum = 0; attnum < indnkeyatts; attnum++)
 		{
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index f36929deec3..72b135e5dcf 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -466,12 +466,10 @@ reorderqueue_push(IndexScanState *node, TupleTableSlot *slot,
 	ReorderTuple *rt;
 	int			i;
 
-	rt = (ReorderTuple *) palloc(sizeof(ReorderTuple));
+	rt = palloc_object(ReorderTuple);
 	rt->htup = ExecCopySlotHeapTuple(slot);
-	rt->orderbyvals =
-		(Datum *) palloc(sizeof(Datum) * scandesc->numberOfOrderBys);
-	rt->orderbynulls =
-		(bool *) palloc(sizeof(bool) * scandesc->numberOfOrderBys);
+	rt->orderbyvals = palloc_array(Datum, scandesc->numberOfOrderBys);
+	rt->orderbynulls = palloc_array(bool, scandesc->numberOfOrderBys);
 	for (i = 0; i < node->iss_NumOrderByKeys; i++)
 	{
 		if (!orderbynulls[i])
diff --git a/src/backend/executor/nodeMemoize.c b/src/backend/executor/nodeMemoize.c
index d652663cb6a..7444391e8a1 100644
--- a/src/backend/executor/nodeMemoize.c
+++ b/src/backend/executor/nodeMemoize.c
@@ -555,7 +555,7 @@ cache_lookup(MemoizeState *mstate, bool *found)
 	oldcontext = MemoryContextSwitchTo(mstate->tableContext);
 
 	/* Allocate a new key */
-	entry->key = key = (MemoizeKey *) palloc(sizeof(MemoizeKey));
+	entry->key = key = palloc_object(MemoizeKey);
 	key->params = ExecCopySlotMinimalTuple(mstate->probeslot);
 
 	/* Update the total cache memory utilization */
@@ -634,7 +634,7 @@ cache_store_tuple(MemoizeState *mstate, TupleTableSlot *slot)
 
 	oldcontext = MemoryContextSwitchTo(mstate->tableContext);
 
-	tuple = (MemoizeTuple *) palloc(sizeof(MemoizeTuple));
+	tuple = palloc_object(MemoizeTuple);
 	tuple->mintuple = ExecCopySlotMinimalTuple(slot);
 	tuple->next = NULL;
 
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index 405e8f94285..300bcd5cf33 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -122,11 +122,11 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
 		mergestate->ms_prune_state = NULL;
 	}
 
-	mergeplanstates = (PlanState **) palloc(nplans * sizeof(PlanState *));
+	mergeplanstates = palloc_array(PlanState *, nplans);
 	mergestate->mergeplans = mergeplanstates;
 	mergestate->ms_nplans = nplans;
 
-	mergestate->ms_slots = (TupleTableSlot **) palloc0(sizeof(TupleTableSlot *) * nplans);
+	mergestate->ms_slots = palloc0_array(TupleTableSlot *, nplans);
 	mergestate->ms_heap = binaryheap_allocate(nplans, heap_compare_slots,
 											  mergestate);
 
@@ -174,7 +174,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
 	 * initialize sort-key information
 	 */
 	mergestate->ms_nkeys = node->numCols;
-	mergestate->ms_sortkeys = palloc0(sizeof(SortSupportData) * node->numCols);
+	mergestate->ms_sortkeys = palloc0_array(SortSupportData, node->numCols);
 
 	for (i = 0; i < node->numCols; i++)
 	{
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index e44f1223886..874b71e6608 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -581,8 +581,8 @@ ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo,
 
 	oldContext = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
 
-	values = palloc(sizeof(*values) * natts);
-	nulls = palloc(sizeof(*nulls) * natts);
+	values = palloc_array(Datum, natts);
+	nulls = palloc_array(bool, natts);
 
 	slot_getallattrs(slot);
 	memcpy(nulls, slot->tts_isnull, sizeof(*nulls) * natts);
@@ -962,10 +962,8 @@ ExecInsert(ModifyTableContext *context,
 
 			if (resultRelInfo->ri_Slots == NULL)
 			{
-				resultRelInfo->ri_Slots = palloc(sizeof(TupleTableSlot *) *
-												 resultRelInfo->ri_BatchSize);
-				resultRelInfo->ri_PlanSlots = palloc(sizeof(TupleTableSlot *) *
-													 resultRelInfo->ri_BatchSize);
+				resultRelInfo->ri_Slots = palloc_array(TupleTableSlot *, resultRelInfo->ri_BatchSize);
+				resultRelInfo->ri_PlanSlots = palloc_array(TupleTableSlot *, resultRelInfo->ri_BatchSize);
 			}
 
 			/*
@@ -4745,8 +4743,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 	mtstate->mt_done = false;
 
 	mtstate->mt_nrels = nrels;
-	mtstate->resultRelInfo = (ResultRelInfo *)
-		palloc(nrels * sizeof(ResultRelInfo));
+	mtstate->resultRelInfo = palloc_array(ResultRelInfo, nrels);
 
 	mtstate->mt_merge_pending_not_matched = NULL;
 	mtstate->mt_merge_inserted = 0;
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index 880f39fb2ff..7d621cebc7b 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -267,10 +267,8 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
 
 	/* Create workspace for per-tlist-entry expr state & SRF-is-done state */
 	state->nelems = list_length(node->plan.targetlist);
-	state->elems = (Node **)
-		palloc(sizeof(Node *) * state->nelems);
-	state->elemdone = (ExprDoneCond *)
-		palloc(sizeof(ExprDoneCond) * state->nelems);
+	state->elems = palloc_array(Node *, state->nelems);
+	state->elemdone = palloc_array(ExprDoneCond, state->nelems);
 
 	/*
 	 * Build expressions to evaluate targetlist.  We can't use
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index 6b3db7548ed..c28bc6fc620 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -228,7 +228,7 @@ tablesample_init(SampleScanState *scanstate)
 	ListCell   *arg;
 
 	scanstate->donetuples = 0;
-	params = (Datum *) palloc(list_length(scanstate->args) * sizeof(Datum));
+	params = palloc_array(Datum, list_length(scanstate->args));
 
 	i = 0;
 	foreach(arg, scanstate->args)
diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c
index 4bae685d45a..4abada0e03e 100644
--- a/src/backend/executor/nodeTableFuncscan.c
+++ b/src/backend/executor/nodeTableFuncscan.c
@@ -192,8 +192,8 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
 	scanstate->notnulls = tf->notnulls;
 
 	/* these are allocated now and initialized later */
-	scanstate->in_functions = palloc(sizeof(FmgrInfo) * tupdesc->natts);
-	scanstate->typioparams = palloc(sizeof(Oid) * tupdesc->natts);
+	scanstate->in_functions = palloc_array(FmgrInfo, tupdesc->natts);
+	scanstate->typioparams = palloc_array(Oid, tupdesc->natts);
 
 	/*
 	 * Fill in the necessary fmgr infos.
diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c
index 6fd9f68cddd..4ceb181d622 100644
--- a/src/backend/executor/nodeTidrangescan.c
+++ b/src/backend/executor/nodeTidrangescan.c
@@ -72,7 +72,7 @@ MakeTidOpExpr(OpExpr *expr, TidRangeScanState *tidstate)
 	else
 		elog(ERROR, "could not identify CTID variable");
 
-	tidopexpr = (TidOpExpr *) palloc(sizeof(TidOpExpr));
+	tidopexpr = palloc_object(TidOpExpr);
 	tidopexpr->inclusive = false;	/* for now */
 
 	switch (expr->opno)
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index d50c6600358..35fcd5625db 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -78,7 +78,7 @@ TidExprListCreate(TidScanState *tidstate)
 	foreach(l, node->tidquals)
 	{
 		Expr	   *expr = (Expr *) lfirst(l);
-		TidExpr    *tidexpr = (TidExpr *) palloc0(sizeof(TidExpr));
+		TidExpr    *tidexpr = palloc0_object(TidExpr);
 
 		if (is_opclause(expr))
 		{
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 3a0d1f0c922..c0e5ab8dbbf 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -2661,14 +2661,14 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 	numfuncs = winstate->numfuncs;
 	numaggs = winstate->numaggs;
 	econtext = winstate->ss.ps.ps_ExprContext;
-	econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numfuncs);
-	econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numfuncs);
+	econtext->ecxt_aggvalues = palloc0_array(Datum, numfuncs);
+	econtext->ecxt_aggnulls = palloc0_array(bool, numfuncs);
 
 	/*
 	 * allocate per-wfunc/per-agg state information.
 	 */
-	perfunc = (WindowStatePerFunc) palloc0(sizeof(WindowStatePerFuncData) * numfuncs);
-	peragg = (WindowStatePerAgg) palloc0(sizeof(WindowStatePerAggData) * numaggs);
+	perfunc = palloc0_array(WindowStatePerFuncData, numfuncs);
+	peragg = palloc0_array(WindowStatePerAggData, numaggs);
 	winstate->perfunc = perfunc;
 	winstate->peragg = peragg;
 
@@ -3467,8 +3467,8 @@ init_notnull_info(WindowObject winobj, WindowStatePerFunc perfuncstate)
 
 	if (winobj->ignore_nulls == PARSER_IGNORE_NULLS)
 	{
-		winobj->notnull_info = palloc0(sizeof(uint8 *) * numargs);
-		winobj->num_notnull_info = palloc0(sizeof(int64) * numargs);
+		winobj->notnull_info = palloc0_array(uint8 *, numargs);
+		winobj->num_notnull_info = palloc0_array(int64, numargs);
 	}
 }
 
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 653500b38dc..34a63a977b6 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1130,8 +1130,8 @@ SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
 	SPI_result = 0;
 
 	numberOfAttributes = rel->rd_att->natts;
-	v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
-	n = (bool *) palloc(numberOfAttributes * sizeof(bool));
+	v = palloc_array(Datum, numberOfAttributes);
+	n = palloc_array(bool, numberOfAttributes);
 
 	/* fetch old values and nulls */
 	heap_deform_tuple(tuple, rel->rd_att, v, n);
@@ -2141,8 +2141,7 @@ spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
 									  ALLOCSET_DEFAULT_SIZES);
 	MemoryContextSwitchTo(tuptabcxt);
 
-	_SPI_current->tuptable = tuptable = (SPITupleTable *)
-		palloc0(sizeof(SPITupleTable));
+	_SPI_current->tuptable = tuptable = palloc0_object(SPITupleTable);
 	tuptable->tuptabcxt = tuptabcxt;
 	tuptable->subid = GetCurrentSubTransactionId();
 
@@ -2155,7 +2154,7 @@ spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
 
 	/* set up initial allocations */
 	tuptable->alloced = 128;
-	tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
+	tuptable->vals = palloc_array(HeapTuple, tuptable->alloced);
 	tuptable->numvals = 0;
 	tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
 
@@ -3162,7 +3161,7 @@ _SPI_make_plan_non_temp(SPIPlanPtr plan)
 	oldcxt = MemoryContextSwitchTo(plancxt);
 
 	/* Copy the _SPI_plan struct and subsidiary data into the new context */
-	newplan = (SPIPlanPtr) palloc0(sizeof(_SPI_plan));
+	newplan = palloc0_object(_SPI_plan);
 	newplan->magic = _SPI_PLAN_MAGIC;
 	newplan->plancxt = plancxt;
 	newplan->parse_mode = plan->parse_mode;
@@ -3170,7 +3169,7 @@ _SPI_make_plan_non_temp(SPIPlanPtr plan)
 	newplan->nargs = plan->nargs;
 	if (plan->nargs > 0)
 	{
-		newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
+		newplan->argtypes = palloc_array(Oid, plan->nargs);
 		memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
 	}
 	else
@@ -3227,7 +3226,7 @@ _SPI_save_plan(SPIPlanPtr plan)
 	oldcxt = MemoryContextSwitchTo(plancxt);
 
 	/* Copy the SPI plan into its own context */
-	newplan = (SPIPlanPtr) palloc0(sizeof(_SPI_plan));
+	newplan = palloc0_object(_SPI_plan);
 	newplan->magic = _SPI_PLAN_MAGIC;
 	newplan->plancxt = plancxt;
 	newplan->parse_mode = plan->parse_mode;
@@ -3235,7 +3234,7 @@ _SPI_save_plan(SPIPlanPtr plan)
 	newplan->nargs = plan->nargs;
 	if (plan->nargs > 0)
 	{
-		newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
+		newplan->argtypes = palloc_array(Oid, plan->nargs);
 		memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
 	}
 	else
@@ -3369,7 +3368,7 @@ SPI_register_trigger_data(TriggerData *tdata)
 	if (tdata->tg_newtable)
 	{
 		EphemeralNamedRelation enr =
-			palloc(sizeof(EphemeralNamedRelationData));
+			palloc_object(EphemeralNamedRelationData);
 		int			rc;
 
 		enr->md.name = tdata->tg_trigger->tgnewtable;
@@ -3386,7 +3385,7 @@ SPI_register_trigger_data(TriggerData *tdata)
 	if (tdata->tg_oldtable)
 	{
 		EphemeralNamedRelation enr =
-			palloc(sizeof(EphemeralNamedRelationData));
+			palloc_object(EphemeralNamedRelationData);
 		int			rc;
 
 		enr->md.name = tdata->tg_trigger->tgoldtable;
diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c
index 6c5e1f1262d..d9bf59f672d 100644
--- a/src/backend/executor/tqueue.c
+++ b/src/backend/executor/tqueue.c
@@ -120,7 +120,7 @@ CreateTupleQueueDestReceiver(shm_mq_handle *handle)
 {
 	TQueueDestReceiver *self;
 
-	self = (TQueueDestReceiver *) palloc0(sizeof(TQueueDestReceiver));
+	self = palloc0_object(TQueueDestReceiver);
 
 	self->pub.receiveSlot = tqueueReceiveSlot;
 	self->pub.rStartup = tqueueStartupReceiver;
@@ -138,7 +138,7 @@ CreateTupleQueueDestReceiver(shm_mq_handle *handle)
 TupleQueueReader *
 CreateTupleQueueReader(shm_mq_handle *handle)
 {
-	TupleQueueReader *reader = palloc0(sizeof(TupleQueueReader));
+	TupleQueueReader *reader = palloc0_object(TupleQueueReader);
 
 	reader->queue = handle;
 
diff --git a/src/backend/executor/tstoreReceiver.c b/src/backend/executor/tstoreReceiver.c
index 02a3ad3aa68..2012618e230 100644
--- a/src/backend/executor/tstoreReceiver.c
+++ b/src/backend/executor/tstoreReceiver.c
@@ -238,7 +238,7 @@ tstoreDestroyReceiver(DestReceiver *self)
 DestReceiver *
 CreateTuplestoreDestReceiver(void)
 {
-	TStoreState *self = (TStoreState *) palloc0(sizeof(TStoreState));
+	TStoreState *self = palloc0_object(TStoreState);
 
 	self->pub.receiveSlot = tstoreReceiveSlot_notoast;	/* might change */
 	self->pub.rStartup = tstoreStartupReceiver;
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index a57e59f27ea..fa3f4c75247 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -66,7 +66,7 @@ GetForeignDataWrapperExtended(Oid fdwid, bits16 flags)
 
 	fdwform = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp);
 
-	fdw = (ForeignDataWrapper *) palloc(sizeof(ForeignDataWrapper));
+	fdw = palloc_object(ForeignDataWrapper);
 	fdw->fdwid = fdwid;
 	fdw->owner = fdwform->fdwowner;
 	fdw->fdwname = pstrdup(NameStr(fdwform->fdwname));
@@ -140,7 +140,7 @@ GetForeignServerExtended(Oid serverid, bits16 flags)
 
 	serverform = (Form_pg_foreign_server) GETSTRUCT(tp);
 
-	server = (ForeignServer *) palloc(sizeof(ForeignServer));
+	server = palloc_object(ForeignServer);
 	server->serverid = serverid;
 	server->servername = pstrdup(NameStr(serverform->srvname));
 	server->owner = serverform->srvowner;
@@ -227,7 +227,7 @@ GetUserMapping(Oid userid, Oid serverid)
 						MappingUserName(userid), server->servername)));
 	}
 
-	um = (UserMapping *) palloc(sizeof(UserMapping));
+	um = palloc_object(UserMapping);
 	um->umid = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
 	um->userid = userid;
 	um->serverid = serverid;
@@ -265,7 +265,7 @@ GetForeignTable(Oid relid)
 		elog(ERROR, "cache lookup failed for foreign table %u", relid);
 	tableform = (Form_pg_foreign_table) GETSTRUCT(tp);
 
-	ft = (ForeignTable *) palloc(sizeof(ForeignTable));
+	ft = palloc_object(ForeignTable);
 	ft->relid = relid;
 	ft->serverid = tableform->ftserver;
 
@@ -463,7 +463,7 @@ GetFdwRoutineForRelation(Relation relation, bool makecopy)
 	/* We have valid cached data --- does the caller want a copy? */
 	if (makecopy)
 	{
-		fdwroutine = (FdwRoutine *) palloc(sizeof(FdwRoutine));
+		fdwroutine = palloc_object(FdwRoutine);
 		memcpy(fdwroutine, relation->rd_fdwroutine, sizeof(FdwRoutine));
 		return fdwroutine;
 	}
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index e978b996bae..15c3475ede2 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -500,7 +500,7 @@ llvm_copy_attributes_at_index(LLVMValueRef v_from, LLVMValueRef v_to, uint32 ind
 	if (num_attributes == 0)
 		return;
 
-	attrs = palloc(sizeof(LLVMAttributeRef) * num_attributes);
+	attrs = palloc_array(LLVMAttributeRef, num_attributes);
 	LLVMGetAttributesAtIndex(v_from, index, attrs);
 
 	for (int attno = 0; attno < num_attributes; attno++)
@@ -1123,9 +1123,9 @@ llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx,
 					 LLVMOrcCLookupSet LookupSet, size_t LookupSetSize)
 {
 #if LLVM_VERSION_MAJOR > 14
-	LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMOrcCSymbolMapPair) * LookupSetSize);
+	LLVMOrcCSymbolMapPairs symbols = palloc0_array(LLVMOrcCSymbolMapPair, LookupSetSize);
 #else
-	LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMJITCSymbolMapPair) * LookupSetSize);
+	LLVMOrcCSymbolMapPairs symbols = palloc0_array(LLVMJITCSymbolMapPair, LookupSetSize);
 #endif
 	LLVMErrorRef error;
 	LLVMOrcMaterializationUnitRef mu;
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index f500cbda893..89167d15c3f 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -156,12 +156,12 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 	b = LLVMCreateBuilderInContext(lc);
 
-	attcheckattnoblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
-	attstartblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
-	attisnullblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
-	attcheckalignblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
-	attalignblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
-	attstoreblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
+	attcheckattnoblocks = palloc_array(LLVMBasicBlockRef, natts);
+	attstartblocks = palloc_array(LLVMBasicBlockRef, natts);
+	attisnullblocks = palloc_array(LLVMBasicBlockRef, natts);
+	attcheckalignblocks = palloc_array(LLVMBasicBlockRef, natts);
+	attalignblocks = palloc_array(LLVMBasicBlockRef, natts);
+	attstoreblocks = palloc_array(LLVMBasicBlockRef, natts);
 
 	known_alignment = 0;
 
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index ac88881e995..c058583bcb6 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -297,7 +297,7 @@ llvm_compile_expr(ExprState *state)
 								   "v.econtext.aggnulls");
 
 	/* allocate blocks for each op upfront, so we can do jumps easily */
-	opblocks = palloc(sizeof(LLVMBasicBlockRef) * state->steps_len);
+	opblocks = palloc_array(LLVMBasicBlockRef, state->steps_len);
 	for (int opno = 0; opno < state->steps_len; opno++)
 		opblocks[opno] = l_bb_append_v(eval_fn, "b.op.%d.start", opno);
 
@@ -699,7 +699,7 @@ llvm_compile_expr(ExprState *state)
 
 						/* create blocks for checking args, one for each */
 						b_checkargnulls =
-							palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
+							palloc_array(LLVMBasicBlockRef *, op->d.func.nargs);
 						for (int argno = 0; argno < op->d.func.nargs; argno++)
 							b_checkargnulls[argno] =
 								l_bb_before_v(b_nonull, "b.%d.isnull.%d", opno,
@@ -2505,7 +2505,7 @@ llvm_compile_expr(ExprState *state)
 					v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
 
 					/* create blocks for checking args */
-					b_checknulls = palloc(sizeof(LLVMBasicBlockRef) * nargs);
+					b_checknulls = palloc_array(LLVMBasicBlockRef, nargs);
 					for (int argno = 0; argno < nargs; argno++)
 					{
 						b_checknulls[argno] =
@@ -2956,7 +2956,7 @@ llvm_compile_expr(ExprState *state)
 	 */
 	{
 
-		CompiledExprState *cstate = palloc0(sizeof(CompiledExprState));
+		CompiledExprState *cstate = palloc0_object(CompiledExprState);
 
 		cstate->context = context;
 		cstate->funcname = funcname;
@@ -3068,7 +3068,7 @@ build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
 		elog(ERROR, "parameter mismatch: %s expects %d passed %d",
 			 funcname, LLVMCountParams(v_fn), nargs + 2);
 
-	params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
+	params = palloc_array(LLVMValueRef, (2 + nargs));
 
 	params[argno++] = v_state;
 	params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
diff --git a/src/backend/lib/bipartite_match.c b/src/backend/lib/bipartite_match.c
index 5af789652c7..ed54f190494 100644
--- a/src/backend/lib/bipartite_match.c
+++ b/src/backend/lib/bipartite_match.c
@@ -38,7 +38,7 @@ static bool hk_depth_search(BipartiteMatchState *state, int u);
 BipartiteMatchState *
 BipartiteMatch(int u_size, int v_size, short **adjacency)
 {
-	BipartiteMatchState *state = palloc(sizeof(BipartiteMatchState));
+	BipartiteMatchState *state = palloc_object(BipartiteMatchState);
 
 	if (u_size < 0 || u_size >= SHRT_MAX ||
 		v_size < 0 || v_size >= SHRT_MAX)
diff --git a/src/backend/lib/dshash.c b/src/backend/lib/dshash.c
index e1ba367cf17..82f6aa966de 100644
--- a/src/backend/lib/dshash.c
+++ b/src/backend/lib/dshash.c
@@ -211,7 +211,7 @@ dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
 	dsa_pointer control;
 
 	/* Allocate the backend-local object representing the hash table. */
-	hash_table = palloc(sizeof(dshash_table));
+	hash_table = palloc_object(dshash_table);
 
 	/* Allocate the control object in shared memory. */
 	control = dsa_allocate(area, sizeof(dshash_table_control));
@@ -276,7 +276,7 @@ dshash_attach(dsa_area *area, const dshash_parameters *params,
 	dsa_pointer control;
 
 	/* Allocate the backend-local object representing the hash table. */
-	hash_table = palloc(sizeof(dshash_table));
+	hash_table = palloc_object(dshash_table);
 
 	/* Find the control object in shared memory. */
 	control = handle;
diff --git a/src/backend/lib/integerset.c b/src/backend/lib/integerset.c
index f4153b0e15a..aca1df2ad5a 100644
--- a/src/backend/lib/integerset.c
+++ b/src/backend/lib/integerset.c
@@ -284,7 +284,7 @@ intset_create(void)
 {
 	IntegerSet *intset;
 
-	intset = (IntegerSet *) palloc(sizeof(IntegerSet));
+	intset = palloc_object(IntegerSet);
 	intset->context = CurrentMemoryContext;
 	intset->mem_used = GetMemoryChunkSpace(intset);
 
diff --git a/src/backend/lib/pairingheap.c b/src/backend/lib/pairingheap.c
index fa8431f7946..3497dc7902a 100644
--- a/src/backend/lib/pairingheap.c
+++ b/src/backend/lib/pairingheap.c
@@ -43,7 +43,7 @@ pairingheap_allocate(pairingheap_comparator compare, void *arg)
 {
 	pairingheap *heap;
 
-	heap = (pairingheap *) palloc(sizeof(pairingheap));
+	heap = palloc_object(pairingheap);
 	pairingheap_initialize(heap, compare, arg);
 
 	return heap;
diff --git a/src/backend/lib/rbtree.c b/src/backend/lib/rbtree.c
index 1f0553f914d..8fe6bfc539a 100644
--- a/src/backend/lib/rbtree.c
+++ b/src/backend/lib/rbtree.c
@@ -106,7 +106,7 @@ rbt_create(Size node_size,
 		   rbt_freefunc freefunc,
 		   void *arg)
 {
-	RBTree	   *tree = (RBTree *) palloc(sizeof(RBTree));
+	RBTree	   *tree = palloc_object(RBTree);
 
 	Assert(node_size > sizeof(RBTNode));
 
diff --git a/src/backend/libpq/auth-oauth.c b/src/backend/libpq/auth-oauth.c
index 27f7af7be00..32a370ede11 100644
--- a/src/backend/libpq/auth-oauth.c
+++ b/src/backend/libpq/auth-oauth.c
@@ -108,7 +108,7 @@ oauth_init(Port *port, const char *selected_mech, const char *shadow_pass)
 				errcode(ERRCODE_PROTOCOL_VIOLATION),
 				errmsg("client selected an invalid SASL authentication mechanism"));
 
-	ctx = palloc0(sizeof(*ctx));
+	ctx = palloc0_object(struct oauth_ctx);
 
 	ctx->state = OAUTH_STATE_INIT;
 	ctx->port = port;
@@ -656,7 +656,7 @@ validate(Port *port, const char *auth)
 				errmsg("validation of OAuth token requested without a validator loaded"));
 
 	/* Call the validation function from the validator module */
-	ret = palloc0(sizeof(ValidatorModuleResult));
+	ret = palloc0_object(ValidatorModuleResult);
 	if (!ValidatorCallbacks->validate_cb(validator_module_state, token,
 										 port->user_name, ret))
 	{
@@ -785,14 +785,14 @@ load_validator_library(const char *libname)
 					   "OAuth validator", libname, "validate_cb"));
 
 	/* Allocate memory for validator library private state data */
-	validator_module_state = (ValidatorModuleState *) palloc0(sizeof(ValidatorModuleState));
+	validator_module_state = palloc0_object(ValidatorModuleState);
 	validator_module_state->sversion = PG_VERSION_NUM;
 
 	if (ValidatorCallbacks->startup_cb != NULL)
 		ValidatorCallbacks->startup_cb(validator_module_state);
 
 	/* Shut down the library before cleaning up its state. */
-	mcb = palloc0(sizeof(*mcb));
+	mcb = palloc0_object(MemoryContextCallback);
 	mcb->func = shutdown_validator_library;
 
 	MemoryContextRegisterResetCallback(CurrentMemoryContext, mcb);
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index e343ffea46f..2d6d97b4bb6 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -240,7 +240,7 @@ scram_init(Port *port, const char *selected_mech, const char *shadow_pass)
 	scram_state *state;
 	bool		got_secret;
 
-	state = (scram_state *) palloc0(sizeof(scram_state));
+	state = palloc0_object(scram_state);
 	state->port = port;
 	state->state = SCRAM_AUTH_INIT;
 
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 6cb25399c26..4c259f58d77 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -309,7 +309,7 @@ regcomp_auth_token(AuthToken *token, char *filename, int line_num,
 	if (token->string[0] != '/')
 		return 0;				/* nothing to compile */
 
-	token->regex = (regex_t *) palloc0(sizeof(regex_t));
+	token->regex = palloc0_object(regex_t);
 	wstr = palloc((strlen(token->string + 1) + 1) * sizeof(pg_wchar));
 	wlen = pg_mb2wchar_with_len(token->string + 1,
 								wstr, strlen(token->string + 1));
@@ -891,7 +891,7 @@ process_line:
 		 * to this list.
 		 */
 		oldcxt = MemoryContextSwitchTo(tokenize_context);
-		tok_line = (TokenizedAuthLine *) palloc0(sizeof(TokenizedAuthLine));
+		tok_line = palloc0_object(TokenizedAuthLine);
 		tok_line->fields = current_line;
 		tok_line->file_name = pstrdup(filename);
 		tok_line->line_num = line_number;
@@ -1339,7 +1339,7 @@ parse_hba_line(TokenizedAuthLine *tok_line, int elevel)
 	AuthToken  *token;
 	HbaLine    *parsedline;
 
-	parsedline = palloc0(sizeof(HbaLine));
+	parsedline = palloc0_object(HbaLine);
 	parsedline->sourcefile = pstrdup(file_name);
 	parsedline->linenumber = line_num;
 	parsedline->rawline = pstrdup(tok_line->raw_line);
@@ -2622,7 +2622,7 @@ check_hba(Port *port)
 	}
 
 	/* If no matching entry was found, then implicitly reject. */
-	hba = palloc0(sizeof(HbaLine));
+	hba = palloc0_object(HbaLine);
 	hba->auth_method = uaImplicitReject;
 	port->hba = hba;
 }
@@ -2758,7 +2758,7 @@ parse_ident_line(TokenizedAuthLine *tok_line, int elevel)
 	Assert(tok_line->fields != NIL);
 	field = list_head(tok_line->fields);
 
-	parsedline = palloc0(sizeof(IdentLine));
+	parsedline = palloc0_object(IdentLine);
 	parsedline->linenumber = line_num;
 
 	/* Get the map token (must exist) */
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 25f739a6a17..899d8bef9dc 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -178,7 +178,7 @@ pq_init(ClientSocket *client_sock)
 	int			latch_pos PG_USED_FOR_ASSERTS_ONLY;
 
 	/* allocate the Port struct and copy the ClientSocket contents to it */
-	port = palloc0(sizeof(Port));
+	port = palloc0_object(Port);
 	port->sock = client_sock->sock;
 	memcpy(&port->raddr.addr, &client_sock->raddr.addr, client_sock->raddr.salen);
 	port->raddr.salen = client_sock->raddr.salen;
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index d228318dc72..024a2b2fd84 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -2953,7 +2953,7 @@ expression_tree_mutator_impl(Node *node,
 	 */
 
 #define FLATCOPY(newnode, node, nodetype)  \
-	( (newnode) = (nodetype *) palloc(sizeof(nodetype)), \
+	( (newnode) = palloc_object(nodetype), \
 	  memcpy((newnode), (node), sizeof(nodetype)) )
 
 #define MUTATE(newfield, oldfield, fieldtype)  \
diff --git a/src/backend/nodes/queryjumblefuncs.c b/src/backend/nodes/queryjumblefuncs.c
index 31f97151977..ffc230af427 100644
--- a/src/backend/nodes/queryjumblefuncs.c
+++ b/src/backend/nodes/queryjumblefuncs.c
@@ -181,7 +181,7 @@ InitJumble(void)
 {
 	JumbleState *jstate;
 
-	jstate = (JumbleState *) palloc(sizeof(JumbleState));
+	jstate = palloc_object(JumbleState);
 
 	/* Set up workspace for query jumbling */
 	jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE);
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 1f83d0d55f5..a2fa96317db 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -683,7 +683,7 @@ tbm_begin_private_iterate(TIDBitmap *tbm)
 	 * Create the TBMPrivateIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
+	iterator = palloc_object(TBMPrivateIterator);
 	iterator->tbm = tbm;
 
 	/*
@@ -1468,7 +1468,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
 	 * Create the TBMSharedIterator struct, with enough trailing space to
 	 * serve the needs of the TBMIterateResult sub-struct.
 	 */
-	iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
+	iterator = palloc0_object(TBMSharedIterator);
 
 	istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
 
diff --git a/src/backend/optimizer/geqo/geqo_erx.c b/src/backend/optimizer/geqo/geqo_erx.c
index af289f7eeb7..f11a59e4a28 100644
--- a/src/backend/optimizer/geqo/geqo_erx.c
+++ b/src/backend/optimizer/geqo/geqo_erx.c
@@ -62,7 +62,7 @@ alloc_edge_table(PlannerInfo *root, int num_gene)
 	 * directly; 0 will not be used
 	 */
 
-	edge_table = (Edge *) palloc((num_gene + 1) * sizeof(Edge));
+	edge_table = palloc_array(Edge, num_gene + 1);
 
 	return edge_table;
 }
diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c
index 8005754c8c6..c65a31d0679 100644
--- a/src/backend/optimizer/geqo/geqo_eval.c
+++ b/src/backend/optimizer/geqo/geqo_eval.c
@@ -191,7 +191,7 @@ gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
 										  cur_rel_index - 1);
 
 		/* Make it into a single-rel clump */
-		cur_clump = (Clump *) palloc(sizeof(Clump));
+		cur_clump = palloc_object(Clump);
 		cur_clump->joinrel = cur_rel;
 		cur_clump->size = 1;
 
diff --git a/src/backend/optimizer/geqo/geqo_pmx.c b/src/backend/optimizer/geqo/geqo_pmx.c
index 01d55711925..af1cb868391 100644
--- a/src/backend/optimizer/geqo/geqo_pmx.c
+++ b/src/backend/optimizer/geqo/geqo_pmx.c
@@ -48,10 +48,10 @@
 void
 pmx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene)
 {
-	int		   *failed = (int *) palloc((num_gene + 1) * sizeof(int));
-	int		   *from = (int *) palloc((num_gene + 1) * sizeof(int));
-	int		   *indx = (int *) palloc((num_gene + 1) * sizeof(int));
-	int		   *check_list = (int *) palloc((num_gene + 1) * sizeof(int));
+	int		   *failed = palloc_array(int, num_gene + 1);
+	int		   *from = palloc_array(int, num_gene + 1);
+	int		   *indx = palloc_array(int, num_gene + 1);
+	int		   *check_list = palloc_array(int, num_gene + 1);
 
 	int			left,
 				right,
diff --git a/src/backend/optimizer/geqo/geqo_pool.c b/src/backend/optimizer/geqo/geqo_pool.c
index 89e3d6a0277..d0f53d888ef 100644
--- a/src/backend/optimizer/geqo/geqo_pool.c
+++ b/src/backend/optimizer/geqo/geqo_pool.c
@@ -46,17 +46,17 @@ alloc_pool(PlannerInfo *root, int pool_size, int string_length)
 	int			i;
 
 	/* pool */
-	new_pool = (Pool *) palloc(sizeof(Pool));
+	new_pool = palloc_object(Pool);
 	new_pool->size = pool_size;
 	new_pool->string_length = string_length;
 
 	/* all chromosome */
-	new_pool->data = (Chromosome *) palloc(pool_size * sizeof(Chromosome));
+	new_pool->data = palloc_array(Chromosome, pool_size);
 
 	/* all gene */
 	chromo = (Chromosome *) new_pool->data; /* vector of all chromos */
 	for (i = 0; i < pool_size; i++)
-		chromo[i].string = palloc((string_length + 1) * sizeof(Gene));
+		chromo[i].string = palloc_array(Gene, string_length + 1);
 
 	return new_pool;
 }
@@ -163,8 +163,8 @@ alloc_chromo(PlannerInfo *root, int string_length)
 {
 	Chromosome *chromo;
 
-	chromo = (Chromosome *) palloc(sizeof(Chromosome));
-	chromo->string = (Gene *) palloc((string_length + 1) * sizeof(Gene));
+	chromo = palloc_object(Chromosome);
+	chromo->string = palloc_array(Gene, string_length + 1);
 
 	return chromo;
 }
diff --git a/src/backend/optimizer/geqo/geqo_recombination.c b/src/backend/optimizer/geqo/geqo_recombination.c
index a5d3e47ad11..41d35c179e1 100644
--- a/src/backend/optimizer/geqo/geqo_recombination.c
+++ b/src/backend/optimizer/geqo/geqo_recombination.c
@@ -74,7 +74,7 @@ alloc_city_table(PlannerInfo *root, int num_gene)
 	 * palloc one extra location so that nodes numbered 1..n can be indexed
 	 * directly; 0 will not be used
 	 */
-	city_table = (City *) palloc((num_gene + 1) * sizeof(City));
+	city_table = palloc_array(City, num_gene + 1);
 
 	return city_table;
 }
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index d0f516b7645..eb9b7f3eabd 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -495,7 +495,7 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
 	}
 
 	/* No matching var found, so make a new clause-pair data structure */
-	rqelem = (RangeQueryClause *) palloc(sizeof(RangeQueryClause));
+	rqelem = palloc_object(RangeQueryClause);
 	rqelem->var = var;
 	if (is_lobound)
 	{
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 5a7283bd2f5..a39cc793b4d 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -2179,7 +2179,7 @@ append_nonpartial_cost(List *subpaths, int numpaths, int parallel_workers)
 	 * whichever is less.
 	 */
 	arrlen = Min(parallel_workers, numpaths);
-	costarr = (Cost *) palloc(sizeof(Cost) * arrlen);
+	costarr = palloc_array(Cost, arrlen);
 
 	/* The first few paths will each be claimed by a different worker. */
 	path_index = 0;
@@ -4137,7 +4137,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey)
 	/* Cache the result in suitably long-lived workspace */
 	oldcontext = MemoryContextSwitchTo(root->planner_cxt);
 
-	cache = (MergeScanSelCache *) palloc(sizeof(MergeScanSelCache));
+	cache = palloc_object(MergeScanSelCache);
 	cache->opfamily = pathkey->pk_opfamily;
 	cache->collation = pathkey->pk_eclass->ec_collation;
 	cache->cmptype = pathkey->pk_cmptype;
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 2654c59c4c6..5d4f81ee77e 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -1291,7 +1291,7 @@ group_similar_or_args(PlannerInfo *root, RelOptInfo *rel, RestrictInfo *rinfo)
 	 * which will be used to sort these arguments at the next step.
 	 */
 	i = -1;
-	matches = (OrArgIndexMatch *) palloc(sizeof(OrArgIndexMatch) * n);
+	matches = palloc_array(OrArgIndexMatch, n);
 	foreach(lc, orargs)
 	{
 		Node	   *arg = lfirst(lc);
@@ -1853,8 +1853,7 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
 	 * same set of clauses; keep only the cheapest-to-scan of any such groups.
 	 * The surviving paths are put into an array for qsort'ing.
 	 */
-	pathinfoarray = (PathClauseUsage **)
-		palloc(npaths * sizeof(PathClauseUsage *));
+	pathinfoarray = palloc_array(PathClauseUsage *, npaths);
 	clauselist = NIL;
 	npaths = 0;
 	foreach(l, paths)
@@ -2090,7 +2089,7 @@ classify_index_clause_usage(Path *path, List **clauselist)
 	Bitmapset  *clauseids;
 	ListCell   *lc;
 
-	result = (PathClauseUsage *) palloc(sizeof(PathClauseUsage));
+	result = palloc_object(PathClauseUsage);
 	result->path = path;
 
 	/* Recursively find the quals and preds used by the path */
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 5d1fc3899da..8827b9a5245 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -1990,8 +1990,7 @@ compute_partition_bounds(PlannerInfo *root, RelOptInfo *rel1,
 		Assert(nparts > 0);
 		joinrel->boundinfo = boundinfo;
 		joinrel->nparts = nparts;
-		joinrel->part_rels =
-			(RelOptInfo **) palloc0(sizeof(RelOptInfo *) * nparts);
+		joinrel->part_rels = palloc0_array(RelOptInfo *, nparts);
 	}
 	else
 	{
diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index e592e1ac3d1..a6af61f929c 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -2358,8 +2358,7 @@ remove_self_joins_recurse(PlannerInfo *root, List *joinlist, Relids toRemove)
 	 * In order to find relations with the same oid we first build an array of
 	 * candidates and then sort it by oid.
 	 */
-	candidates = (SelfJoinCandidate *) palloc(sizeof(SelfJoinCandidate) *
-											  numRels);
+	candidates = palloc_array(SelfJoinCandidate, numRels);
 	i = -1;
 	j = 0;
 	while ((i = bms_next_member(relids, i)) >= 0)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 8af091ba647..bc417f93840 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -2207,7 +2207,7 @@ remap_groupColIdx(PlannerInfo *root, List *groupClause)
 
 	Assert(grouping_map);
 
-	new_grpColIdx = palloc0(sizeof(AttrNumber) * list_length(groupClause));
+	new_grpColIdx = palloc0_array(AttrNumber, list_length(groupClause));
 
 	i = 0;
 	foreach(lc, groupClause)
@@ -2496,9 +2496,9 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
 	 * Convert SortGroupClause lists into arrays of attr indexes and equality
 	 * operators, as wanted by executor.
 	 */
-	partColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numPart);
-	partOperators = (Oid *) palloc(sizeof(Oid) * numPart);
-	partCollations = (Oid *) palloc(sizeof(Oid) * numPart);
+	partColIdx = palloc_array(AttrNumber, numPart);
+	partOperators = palloc_array(Oid, numPart);
+	partCollations = palloc_array(Oid, numPart);
 
 	partNumCols = 0;
 	foreach(lc, wc->partitionClause)
@@ -2513,9 +2513,9 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
 		partNumCols++;
 	}
 
-	ordColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numOrder);
-	ordOperators = (Oid *) palloc(sizeof(Oid) * numOrder);
-	ordCollations = (Oid *) palloc(sizeof(Oid) * numOrder);
+	ordColIdx = palloc_array(AttrNumber, numOrder);
+	ordOperators = palloc_array(Oid, numOrder);
+	ordCollations = palloc_array(Oid, numOrder);
 
 	ordNumCols = 0;
 	foreach(lc, wc->orderClause)
@@ -5862,9 +5862,9 @@ make_recursive_union(List *tlist,
 		Oid		   *dupCollations;
 		ListCell   *slitem;
 
-		dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
-		dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
-		dupCollations = (Oid *) palloc(sizeof(Oid) * numCols);
+		dupColIdx = palloc_array(AttrNumber, numCols);
+		dupOperators = palloc_array(Oid, numCols);
+		dupCollations = palloc_array(Oid, numCols);
 
 		foreach(slitem, distinctList)
 		{
@@ -6694,9 +6694,9 @@ make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols,
 	 * prepare_sort_from_pathkeys ... maybe unify sometime?
 	 */
 	Assert(numCols >= 0 && numCols <= list_length(pathkeys));
-	uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
-	uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
-	uniqCollations = (Oid *) palloc(sizeof(Oid) * numCols);
+	uniqColIdx = palloc_array(AttrNumber, numCols);
+	uniqOperators = palloc_array(Oid, numCols);
+	uniqCollations = palloc_array(Oid, numCols);
 
 	foreach(lc, pathkeys)
 	{
@@ -6831,10 +6831,10 @@ make_setop(SetOpCmd cmd, SetOpStrategy strategy,
 	 * convert SortGroupClause list into arrays of attr indexes and comparison
 	 * operators, as wanted by executor
 	 */
-	cmpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
-	cmpOperators = (Oid *) palloc(sizeof(Oid) * numCols);
-	cmpCollations = (Oid *) palloc(sizeof(Oid) * numCols);
-	cmpNullsFirst = (bool *) palloc(sizeof(bool) * numCols);
+	cmpColIdx = palloc_array(AttrNumber, numCols);
+	cmpOperators = palloc_array(Oid, numCols);
+	cmpCollations = palloc_array(Oid, numCols);
+	cmpNullsFirst = palloc_array(bool, numCols);
 
 	foreach(slitem, groupList)
 	{
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 671c5cde8fc..f7f76469a2d 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -438,8 +438,7 @@ remove_useless_groupby_columns(PlannerInfo *root)
 	 * Fill groupbyattnos[k] with a bitmapset of the column attnos of RTE k
 	 * that are GROUP BY items.
 	 */
-	groupbyattnos = (Bitmapset **) palloc0(sizeof(Bitmapset *) *
-										   (list_length(parse->rtable) + 1));
+	groupbyattnos = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
 	foreach(lc, root->processed_groupClause)
 	{
 		SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
@@ -597,8 +596,7 @@ remove_useless_groupby_columns(PlannerInfo *root)
 			 * allocate the surplusvars[] array until we find something.
 			 */
 			if (surplusvars == NULL)
-				surplusvars = (Bitmapset **) palloc0(sizeof(Bitmapset *) *
-													 (list_length(parse->rtable) + 1));
+				surplusvars = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
 
 			/* Remember the attnos of the removable columns */
 			surplusvars[relid] = bms_difference(relattnos, best_keycolumns);
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index a2ac58d246e..1a35c269e04 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -336,7 +336,7 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo,
 	 * than before.  (This means that when we are done, there will be no Vars
 	 * of level 1, which is why the subquery can become an initplan.)
 	 */
-	subroot = (PlannerInfo *) palloc(sizeof(PlannerInfo));
+	subroot = palloc_object(PlannerInfo);
 	memcpy(subroot, root, sizeof(PlannerInfo));
 	subroot->query_level++;
 	subroot->parent_root = root;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 0e78628bf01..0048c5b8ebf 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -2213,7 +2213,7 @@ preprocess_grouping_sets(PlannerInfo *root)
 	List	   *sets;
 	int			maxref = 0;
 	ListCell   *lc_set;
-	grouping_sets_data *gd = palloc0(sizeof(grouping_sets_data));
+	grouping_sets_data *gd = palloc0_object(grouping_sets_data);
 
 	/*
 	 * We don't currently make any attempt to optimize the groupClause when
@@ -5977,8 +5977,7 @@ select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
 	List	   *result = NIL;
 	ListCell   *lc;
 	int			nActive = 0;
-	WindowClauseSortData *actives = palloc(sizeof(WindowClauseSortData)
-										   * list_length(windowClause));
+	WindowClauseSortData *actives = palloc_array(WindowClauseSortData, list_length(windowClause));
 
 	/* First, construct an array of the active windows */
 	foreach(lc, windowClause)
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index ccdc9bc264a..cd7ea1e6b58 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -312,7 +312,7 @@ set_plan_references(PlannerInfo *root, Plan *plan)
 			   root->simple_rte_array[rc->rti] != NULL);
 
 		/* flat copy is enough since all fields are scalars */
-		newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
+		newrc = palloc_object(PlanRowMark);
 		memcpy(newrc, rc, sizeof(PlanRowMark));
 
 		/* adjust indexes ... but *not* the rowmarkId */
@@ -545,7 +545,7 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos,
 	RangeTblEntry *newrte;
 
 	/* flat copy to duplicate all the scalar fields */
-	newrte = (RangeTblEntry *) palloc(sizeof(RangeTblEntry));
+	newrte = palloc_object(RangeTblEntry);
 	memcpy(newrte, rte, sizeof(RangeTblEntry));
 
 	/* zap unneeded sub-structure */
@@ -2028,7 +2028,7 @@ offset_relid_set(Relids relids, int rtoffset)
 static inline Var *
 copyVar(Var *var)
 {
-	Var		   *newvar = (Var *) palloc(sizeof(Var));
+	Var		   *newvar = palloc_object(Var);
 
 	*newvar = *var;
 	return newvar;
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 7581695647d..c3b726e93e7 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -741,7 +741,7 @@ pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
 		 * Make a modifiable copy of join node, but don't bother copying its
 		 * subnodes (yet).
 		 */
-		j = (JoinExpr *) palloc(sizeof(JoinExpr));
+		j = palloc_object(JoinExpr);
 		memcpy(j, jtnode, sizeof(JoinExpr));
 		jtlink = (Node *) j;
 
@@ -3240,8 +3240,7 @@ reduce_outer_joins_pass1(Node *jtnode)
 {
 	reduce_outer_joins_pass1_state *result;
 
-	result = (reduce_outer_joins_pass1_state *)
-		palloc(sizeof(reduce_outer_joins_pass1_state));
+	result = palloc_object(reduce_outer_joins_pass1_state);
 	result->relids = NULL;
 	result->contains_outer = false;
 	result->sub_states = NIL;
@@ -3593,7 +3592,7 @@ report_reduced_full_join(reduce_outer_joins_pass2_state *state2,
 {
 	reduce_outer_joins_partial_state *statep;
 
-	statep = palloc(sizeof(reduce_outer_joins_partial_state));
+	statep = palloc_object(reduce_outer_joins_partial_state);
 	statep->full_join_rti = rtindex;
 	statep->unreduced_side = relids;
 	state2->partial_reduced = lappend(state2->partial_reduced, statep);
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index f528f096a56..a01b02f3a7b 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -1629,7 +1629,7 @@ generate_append_tlist(List *colTypes, List *colCollations,
 	 * If the inputs all agree on type and typmod of a particular column, use
 	 * that typmod; else use -1.
 	 */
-	colTypmods = (int32 *) palloc(list_length(colTypes) * sizeof(int32));
+	colTypmods = palloc_array(int32, list_length(colTypes));
 
 	foreach(tlistl, input_tlists)
 	{
diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c
index 69b8b0c2ae0..271bb4e6828 100644
--- a/src/backend/optimizer/util/appendinfo.c
+++ b/src/backend/optimizer/util/appendinfo.c
@@ -808,8 +808,7 @@ find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
 	int			i;
 
 	/* Allocate an array that's certainly big enough */
-	appinfos = (AppendRelInfo **)
-		palloc(sizeof(AppendRelInfo *) * bms_num_members(relids));
+	appinfos = palloc_array(AppendRelInfo *, bms_num_members(relids));
 
 	i = -1;
 	while ((i = bms_next_member(relids, i)) >= 0)
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index bda4c4eb292..ddafc21c819 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -239,7 +239,7 @@ contain_window_function(Node *clause)
 WindowFuncLists *
 find_window_functions(Node *clause, Index maxWinRef)
 {
-	WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
+	WindowFuncLists *lists = palloc_object(WindowFuncLists);
 
 	lists->numWindowFuncs = 0;
 	lists->maxWinRef = maxWinRef;
@@ -5744,8 +5744,8 @@ make_SAOP_expr(Oid oper, Node *leftexpr, Oid coltype, Oid arraycollid,
 
 		get_typlenbyvalalign(coltype, &typlen, &typbyval, &typalign);
 
-		elems = (Datum *) palloc(sizeof(Datum) * list_length(exprs));
-		nulls = (bool *) palloc(sizeof(bool) * list_length(exprs));
+		elems = palloc_array(Datum, list_length(exprs));
+		nulls = palloc_array(bool, list_length(exprs));
 		foreach_node(Const, value, exprs)
 		{
 			elems[i] = value->constvalue;
diff --git a/src/backend/optimizer/util/extendplan.c b/src/backend/optimizer/util/extendplan.c
index 03d32277ba1..4e2f8d4dada 100644
--- a/src/backend/optimizer/util/extendplan.c
+++ b/src/backend/optimizer/util/extendplan.c
@@ -98,10 +98,7 @@ SetPlannerGlobalExtensionState(PlannerGlobal *glob, int extension_id,
 		int			i;
 
 		i = pg_nextpower2_32(extension_id + 1);
-		glob->extension_state = (void **)
-			repalloc0(glob->extension_state,
-					  glob->extension_state_allocated * sizeof(void *),
-					  i * sizeof(void *));
+		glob->extension_state = repalloc0_array(glob->extension_state, void *, glob->extension_state_allocated, i);
 		glob->extension_state_allocated = i;
 	}
 
@@ -134,10 +131,7 @@ SetPlannerInfoExtensionState(PlannerInfo *root, int extension_id,
 		int			i;
 
 		i = pg_nextpower2_32(extension_id + 1);
-		root->extension_state = (void **)
-			repalloc0(root->extension_state,
-					  root->extension_state_allocated * sizeof(void *),
-					  i * sizeof(void *));
+		root->extension_state = repalloc0_array(root->extension_state, void *, root->extension_state_allocated, i);
 		root->extension_state_allocated = i;
 	}
 
@@ -172,10 +166,7 @@ SetRelOptInfoExtensionState(RelOptInfo *rel, int extension_id,
 		int			i;
 
 		i = pg_nextpower2_32(extension_id + 1);
-		rel->extension_state = (void **)
-			repalloc0(rel->extension_state,
-					  rel->extension_state_allocated * sizeof(void *),
-					  i * sizeof(void *));
+		rel->extension_state = repalloc0_array(rel->extension_state, void *, rel->extension_state_allocated, i);
 		rel->extension_state_allocated = i;
 	}
 
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 07f92fac239..d771496de60 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -279,11 +279,11 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 			info->ncolumns = ncolumns = index->indnatts;
 			info->nkeycolumns = nkeycolumns = index->indnkeyatts;
 
-			info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
-			info->indexcollations = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
-			info->opfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
-			info->opcintype = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
-			info->canreturn = (bool *) palloc(sizeof(bool) * ncolumns);
+			info->indexkeys = palloc_array(int, ncolumns);
+			info->indexcollations = palloc_array(Oid, nkeycolumns);
+			info->opfamily = palloc_array(Oid, nkeycolumns);
+			info->opcintype = palloc_array(Oid, nkeycolumns);
+			info->canreturn = palloc_array(bool, ncolumns);
 
 			for (i = 0; i < ncolumns; i++)
 			{
@@ -336,8 +336,8 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 					Assert(amroutine->amcanorder);
 
 					info->sortopfamily = info->opfamily;
-					info->reverse_sort = (bool *) palloc(sizeof(bool) * nkeycolumns);
-					info->nulls_first = (bool *) palloc(sizeof(bool) * nkeycolumns);
+					info->reverse_sort = palloc_array(bool, nkeycolumns);
+					info->nulls_first = palloc_array(bool, nkeycolumns);
 
 					for (i = 0; i < nkeycolumns; i++)
 					{
@@ -356,13 +356,13 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 					 * order, this is a sufficient test.
 					 *
 					 * XXX This method is rather slow and complicated.  It'd
-					 * be better to have a way to explicitly declare the
-					 * corresponding btree opfamily for each opfamily of the
-					 * other index type.
+					* be better to have a way to explicitly declare the
+					* corresponding btree opfamily for each opfamily of the
+					* other index type.
 					 */
-					info->sortopfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
-					info->reverse_sort = (bool *) palloc(sizeof(bool) * nkeycolumns);
-					info->nulls_first = (bool *) palloc(sizeof(bool) * nkeycolumns);
+					info->sortopfamily = palloc_array(Oid, nkeycolumns);
+					info->reverse_sort = palloc_array(bool, nkeycolumns);
+					info->nulls_first = palloc_array(bool, nkeycolumns);
 
 					for (i = 0; i < nkeycolumns; i++)
 					{
@@ -2737,32 +2737,31 @@ find_partition_scheme(PlannerInfo *root, Relation relation)
 	 * array since the relcache entry may not survive after we have closed the
 	 * relation.
 	 */
-	part_scheme = (PartitionScheme) palloc0(sizeof(PartitionSchemeData));
+	part_scheme = palloc0_object(PartitionSchemeData);
 	part_scheme->strategy = partkey->strategy;
 	part_scheme->partnatts = partkey->partnatts;
 
-	part_scheme->partopfamily = (Oid *) palloc(sizeof(Oid) * partnatts);
+	part_scheme->partopfamily = palloc_array(Oid, partnatts);
 	memcpy(part_scheme->partopfamily, partkey->partopfamily,
 		   sizeof(Oid) * partnatts);
 
-	part_scheme->partopcintype = (Oid *) palloc(sizeof(Oid) * partnatts);
+	part_scheme->partopcintype = palloc_array(Oid, partnatts);
 	memcpy(part_scheme->partopcintype, partkey->partopcintype,
 		   sizeof(Oid) * partnatts);
 
-	part_scheme->partcollation = (Oid *) palloc(sizeof(Oid) * partnatts);
+	part_scheme->partcollation = palloc_array(Oid, partnatts);
 	memcpy(part_scheme->partcollation, partkey->partcollation,
 		   sizeof(Oid) * partnatts);
 
-	part_scheme->parttyplen = (int16 *) palloc(sizeof(int16) * partnatts);
+	part_scheme->parttyplen = palloc_array(int16, partnatts);
 	memcpy(part_scheme->parttyplen, partkey->parttyplen,
 		   sizeof(int16) * partnatts);
 
-	part_scheme->parttypbyval = (bool *) palloc(sizeof(bool) * partnatts);
+	part_scheme->parttypbyval = palloc_array(bool, partnatts);
 	memcpy(part_scheme->parttypbyval, partkey->parttypbyval,
 		   sizeof(bool) * partnatts);
 
-	part_scheme->partsupfunc = (FmgrInfo *)
-		palloc(sizeof(FmgrInfo) * partnatts);
+	part_scheme->partsupfunc = palloc_array(FmgrInfo, partnatts);
 	for (i = 0; i < partnatts; i++)
 		fmgr_info_copy(&part_scheme->partsupfunc[i], &partkey->partsupfunc[i],
 					   CurrentMemoryContext);
@@ -2796,7 +2795,7 @@ set_baserel_partition_key_exprs(Relation relation,
 	Assert(partkey != NULL);
 
 	partnatts = partkey->partnatts;
-	partexprs = (List **) palloc(sizeof(List *) * partnatts);
+	partexprs = palloc_array(List *, partnatts);
 	lc = list_head(partkey->partexprs);
 
 	for (cnt = 0; cnt < partnatts; cnt++)
@@ -2837,7 +2836,7 @@ set_baserel_partition_key_exprs(Relation relation,
 	 * expression lists to keep partition key expression handling code simple.
 	 * See build_joinrel_partition_info() and match_expr_to_partition_keys().
 	 */
-	rel->nullable_partexprs = (List **) palloc0(sizeof(List *) * partnatts);
+	rel->nullable_partexprs = palloc0_array(List *, partnatts);
 }
 
 /*
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index ac28573cd0a..0a14658ed7d 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -967,7 +967,7 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info)
 	char		elmalign;
 
 	/* Create working state struct */
-	state = (ArrayConstIterState *) palloc(sizeof(ArrayConstIterState));
+	state = palloc_object(ArrayConstIterState);
 	info->state = state;
 
 	/* Deconstruct the array literal */
@@ -1046,7 +1046,7 @@ arrayexpr_startup_fn(Node *clause, PredIterInfo info)
 	ArrayExpr  *arrayexpr;
 
 	/* Create working state struct */
-	state = (ArrayExprIterState *) palloc(sizeof(ArrayExprIterState));
+	state = palloc_object(ArrayExprIterState);
 	info->state = state;
 
 	/* Set up a dummy OpExpr to return as the per-item node */
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 1158bc194c3..2f423fc42b1 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -120,11 +120,11 @@ setup_simple_rel_arrays(PlannerInfo *root)
 	 * exist yet.  It'll be filled by later calls to build_simple_rel().
 	 */
 	root->simple_rel_array = (RelOptInfo **)
-		palloc0(size * sizeof(RelOptInfo *));
+		palloc0_array(RelOptInfo *, size);
 
 	/* simple_rte_array is an array equivalent of the rtable list */
 	root->simple_rte_array = (RangeTblEntry **)
-		palloc0(size * sizeof(RangeTblEntry *));
+		palloc0_array(RangeTblEntry *, size);
 	rti = 1;
 	foreach(lc, root->parse->rtable)
 	{
@@ -141,7 +141,7 @@ setup_simple_rel_arrays(PlannerInfo *root)
 	}
 
 	root->append_rel_array = (AppendRelInfo **)
-		palloc0(size * sizeof(AppendRelInfo *));
+		palloc0_array(AppendRelInfo *, size);
 
 	/*
 	 * append_rel_array is filled with any already-existing AppendRelInfos,
@@ -373,9 +373,9 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
 			rel->min_attr = 0;
 			rel->max_attr = list_length(rte->eref->colnames);
 			rel->attr_needed = (Relids *)
-				palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
+				palloc0_array(Relids, rel->max_attr - rel->min_attr + 1);
 			rel->attr_widths = (int32 *)
-				palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
+				palloc0_array(int32, rel->max_attr - rel->min_attr + 1);
 			break;
 		case RTE_RESULT:
 			/* RTE_RESULT has no columns, nor could it have whole-row Var */
@@ -2486,9 +2486,9 @@ set_joinrel_partition_key_exprs(RelOptInfo *joinrel,
 	PartitionScheme part_scheme = joinrel->part_scheme;
 	int			partnatts = part_scheme->partnatts;
 
-	joinrel->partexprs = (List **) palloc0(sizeof(List *) * partnatts);
+	joinrel->partexprs = (List **) palloc0_array(List *, partnatts);
 	joinrel->nullable_partexprs =
-		(List **) palloc0(sizeof(List *) * partnatts);
+		(List **) palloc0_array(List *, partnatts);
 
 	/*
 	 * The joinrel's partition expressions are the same as those of the input
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index d2b4ecc5e51..af7b19be5c7 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -467,7 +467,7 @@ extract_grouping_ops(List *groupClause)
 	Oid		   *groupOperators;
 	ListCell   *glitem;
 
-	groupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
+	groupOperators = palloc_array(Oid, numCols);
 
 	foreach(glitem, groupClause)
 	{
@@ -493,7 +493,7 @@ extract_grouping_collations(List *groupClause, List *tlist)
 	Oid		   *grpCollations;
 	ListCell   *glitem;
 
-	grpCollations = (Oid *) palloc(sizeof(Oid) * numCols);
+	grpCollations = palloc_array(Oid, numCols);
 
 	foreach(glitem, groupClause)
 	{
@@ -518,7 +518,7 @@ extract_grouping_cols(List *groupClause, List *tlist)
 	int			colno = 0;
 	ListCell   *glitem;
 
-	grpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
+	grpColIdx = palloc_array(AttrNumber, numCols);
 
 	foreach(glitem, groupClause)
 	{
@@ -1089,7 +1089,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
 	 */
 	if (list_member(context->input_target_exprs, node))
 	{
-		split_pathtarget_item *item = palloc(sizeof(split_pathtarget_item));
+		split_pathtarget_item *item = palloc_object(split_pathtarget_item);
 
 		item->expr = node;
 		item->sortgroupref = context->current_sgref;
@@ -1109,7 +1109,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
 		IsA(node, GroupingFunc) ||
 		IsA(node, WindowFunc))
 	{
-		split_pathtarget_item *item = palloc(sizeof(split_pathtarget_item));
+		split_pathtarget_item *item = palloc_object(split_pathtarget_item);
 
 		item->expr = node;
 		item->sortgroupref = context->current_sgref;
@@ -1124,7 +1124,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
 	 */
 	if (IS_SRF_CALL(node))
 	{
-		split_pathtarget_item *item = palloc(sizeof(split_pathtarget_item));
+		split_pathtarget_item *item = palloc_object(split_pathtarget_item);
 		List	   *save_input_vars = context->current_input_vars;
 		List	   *save_input_srfs = context->current_input_srfs;
 		int			save_current_depth = context->current_depth;
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 05314e7e76b..92be345d9a8 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -2641,8 +2641,7 @@ addNSItemForReturning(ParseState *pstate, const char *aliasname,
 	colnames = pstate->p_target_nsitem->p_rte->eref->colnames;
 	numattrs = list_length(colnames);
 
-	nscolumns = (ParseNamespaceColumn *)
-		palloc(numattrs * sizeof(ParseNamespaceColumn));
+	nscolumns = palloc_array(ParseNamespaceColumn, numattrs);
 
 	memcpy(nscolumns, pstate->p_target_nsitem->p_nscolumns,
 		   numattrs * sizeof(ParseNamespaceColumn));
@@ -2652,7 +2651,7 @@ addNSItemForReturning(ParseState *pstate, const char *aliasname,
 		nscolumns[i].p_varreturningtype = returning_type;
 
 	/* build the nsitem, copying most fields from the target relation */
-	nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+	nsitem = palloc_object(ParseNamespaceItem);
 	nsitem->p_names = makeAlias(aliasname, colnames);
 	nsitem->p_rte = pstate->p_target_nsitem->p_rte;
 	nsitem->p_rtindex = pstate->p_target_nsitem->p_rtindex;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c3a0a354a9c..7856ce9d78f 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -4555,19 +4555,19 @@ OptWhereClause:
 key_actions:
 			key_update
 				{
-					KeyActions *n = palloc(sizeof(KeyActions));
+					KeyActions *n = palloc_object(KeyActions);
 
 					n->updateAction = $1;
-					n->deleteAction = palloc(sizeof(KeyAction));
+					n->deleteAction = palloc_object(KeyAction);
 					n->deleteAction->action = FKCONSTR_ACTION_NOACTION;
 					n->deleteAction->cols = NIL;
 					$$ = n;
 				}
 			| key_delete
 				{
-					KeyActions *n = palloc(sizeof(KeyActions));
+					KeyActions *n = palloc_object(KeyActions);
 
-					n->updateAction = palloc(sizeof(KeyAction));
+					n->updateAction = palloc_object(KeyAction);
 					n->updateAction->action = FKCONSTR_ACTION_NOACTION;
 					n->updateAction->cols = NIL;
 					n->deleteAction = $1;
@@ -4575,7 +4575,7 @@ key_actions:
 				}
 			| key_update key_delete
 				{
-					KeyActions *n = palloc(sizeof(KeyActions));
+					KeyActions *n = palloc_object(KeyActions);
 
 					n->updateAction = $1;
 					n->deleteAction = $2;
@@ -4583,7 +4583,7 @@ key_actions:
 				}
 			| key_delete key_update
 				{
-					KeyActions *n = palloc(sizeof(KeyActions));
+					KeyActions *n = palloc_object(KeyActions);
 
 					n->updateAction = $2;
 					n->deleteAction = $1;
@@ -4591,12 +4591,12 @@ key_actions:
 				}
 			| /*EMPTY*/
 				{
-					KeyActions *n = palloc(sizeof(KeyActions));
+					KeyActions *n = palloc_object(KeyActions);
 
-					n->updateAction = palloc(sizeof(KeyAction));
+					n->updateAction = palloc_object(KeyAction);
 					n->updateAction->action = FKCONSTR_ACTION_NOACTION;
 					n->updateAction->cols = NIL;
-					n->deleteAction = palloc(sizeof(KeyAction));
+					n->deleteAction = palloc_object(KeyAction);
 					n->deleteAction->action = FKCONSTR_ACTION_NOACTION;
 					n->deleteAction->cols = NIL;
 					$$ = n;
@@ -4624,7 +4624,7 @@ key_delete: ON DELETE_P key_action
 key_action:
 			NO ACTION
 				{
-					KeyAction *n = palloc(sizeof(KeyAction));
+					KeyAction *n = palloc_object(KeyAction);
 
 					n->action = FKCONSTR_ACTION_NOACTION;
 					n->cols = NIL;
@@ -4632,7 +4632,7 @@ key_action:
 				}
 			| RESTRICT
 				{
-					KeyAction *n = palloc(sizeof(KeyAction));
+					KeyAction *n = palloc_object(KeyAction);
 
 					n->action = FKCONSTR_ACTION_RESTRICT;
 					n->cols = NIL;
@@ -4640,7 +4640,7 @@ key_action:
 				}
 			| CASCADE
 				{
-					KeyAction *n = palloc(sizeof(KeyAction));
+					KeyAction *n = palloc_object(KeyAction);
 
 					n->action = FKCONSTR_ACTION_CASCADE;
 					n->cols = NIL;
@@ -4648,7 +4648,7 @@ key_action:
 				}
 			| SET NULL_P opt_column_list
 				{
-					KeyAction *n = palloc(sizeof(KeyAction));
+					KeyAction *n = palloc_object(KeyAction);
 
 					n->action = FKCONSTR_ACTION_SETNULL;
 					n->cols = $3;
@@ -4656,7 +4656,7 @@ key_action:
 				}
 			| SET DEFAULT opt_column_list
 				{
-					KeyAction *n = palloc(sizeof(KeyAction));
+					KeyAction *n = palloc_object(KeyAction);
 
 					n->action = FKCONSTR_ACTION_SETDEFAULT;
 					n->cols = $3;
@@ -5853,7 +5853,7 @@ import_qualification_type:
 import_qualification:
 		import_qualification_type '(' relation_expr_list ')'
 			{
-				ImportQual *n = (ImportQual *) palloc(sizeof(ImportQual));
+				ImportQual *n = palloc_object(ImportQual);
 
 				n->type = $1;
 				n->table_names = $3;
@@ -5861,7 +5861,7 @@ import_qualification:
 			}
 		| /*EMPTY*/
 			{
-				ImportQual *n = (ImportQual *) palloc(sizeof(ImportQual));
+				ImportQual *n = palloc_object(ImportQual);
 				n->type = FDW_IMPORT_SCHEMA_ALL;
 				n->table_names = NIL;
 				$$ = n;
@@ -7914,7 +7914,7 @@ parameter_name:
 privilege_target:
 			qualified_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_TABLE;
@@ -7923,7 +7923,7 @@ privilege_target:
 				}
 			| TABLE qualified_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_TABLE;
@@ -7932,7 +7932,7 @@ privilege_target:
 				}
 			| SEQUENCE qualified_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_SEQUENCE;
@@ -7941,7 +7941,7 @@ privilege_target:
 				}
 			| FOREIGN DATA_P WRAPPER name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_FDW;
@@ -7950,7 +7950,7 @@ privilege_target:
 				}
 			| FOREIGN SERVER name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_FOREIGN_SERVER;
@@ -7959,7 +7959,7 @@ privilege_target:
 				}
 			| FUNCTION function_with_argtypes_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_FUNCTION;
@@ -7968,7 +7968,7 @@ privilege_target:
 				}
 			| PROCEDURE function_with_argtypes_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_PROCEDURE;
@@ -7977,7 +7977,7 @@ privilege_target:
 				}
 			| ROUTINE function_with_argtypes_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_ROUTINE;
@@ -7986,7 +7986,7 @@ privilege_target:
 				}
 			| DATABASE name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_DATABASE;
@@ -7995,7 +7995,7 @@ privilege_target:
 				}
 			| DOMAIN_P any_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_DOMAIN;
@@ -8004,7 +8004,7 @@ privilege_target:
 				}
 			| LANGUAGE name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_LANGUAGE;
@@ -8013,7 +8013,7 @@ privilege_target:
 				}
 			| LARGE_P OBJECT_P NumericOnly_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_LARGEOBJECT;
@@ -8022,7 +8022,7 @@ privilege_target:
 				}
 			| PARAMETER parameter_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_PARAMETER_ACL;
 					n->objs = $2;
@@ -8030,7 +8030,7 @@ privilege_target:
 				}
 			| SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_SCHEMA;
@@ -8039,7 +8039,7 @@ privilege_target:
 				}
 			| TABLESPACE name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_TABLESPACE;
@@ -8048,7 +8048,7 @@ privilege_target:
 				}
 			| TYPE_P any_name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_OBJECT;
 					n->objtype = OBJECT_TYPE;
@@ -8057,7 +8057,7 @@ privilege_target:
 				}
 			| ALL TABLES IN_P SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
 					n->objtype = OBJECT_TABLE;
@@ -8066,7 +8066,7 @@ privilege_target:
 				}
 			| ALL SEQUENCES IN_P SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
 					n->objtype = OBJECT_SEQUENCE;
@@ -8075,7 +8075,7 @@ privilege_target:
 				}
 			| ALL FUNCTIONS IN_P SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
 					n->objtype = OBJECT_FUNCTION;
@@ -8084,7 +8084,7 @@ privilege_target:
 				}
 			| ALL PROCEDURES IN_P SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
 					n->objtype = OBJECT_PROCEDURE;
@@ -8093,7 +8093,7 @@ privilege_target:
 				}
 			| ALL ROUTINES IN_P SCHEMA name_list
 				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+					PrivTarget *n = palloc_object(PrivTarget);
 
 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
 					n->objtype = OBJECT_ROUTINE;
@@ -13393,7 +13393,7 @@ select_limit:
 				}
 			| offset_clause
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = $1;
 					n->limitCount = NULL;
@@ -13413,7 +13413,7 @@ opt_select_limit:
 limit_clause:
 			LIMIT select_limit_value
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = NULL;
 					n->limitCount = $2;
@@ -13441,7 +13441,7 @@ limit_clause:
 			 */
 			| FETCH first_or_next select_fetch_first_value row_or_rows ONLY
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = NULL;
 					n->limitCount = $3;
@@ -13453,7 +13453,7 @@ limit_clause:
 				}
 			| FETCH first_or_next select_fetch_first_value row_or_rows WITH TIES
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = NULL;
 					n->limitCount = $3;
@@ -13465,7 +13465,7 @@ limit_clause:
 				}
 			| FETCH first_or_next row_or_rows ONLY
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = NULL;
 					n->limitCount = makeIntConst(1, -1);
@@ -13477,7 +13477,7 @@ limit_clause:
 				}
 			| FETCH first_or_next row_or_rows WITH TIES
 				{
-					SelectLimit *n = (SelectLimit *) palloc(sizeof(SelectLimit));
+					SelectLimit *n = palloc_object(SelectLimit);
 
 					n->limitOffset = NULL;
 					n->limitCount = makeIntConst(1, -1);
@@ -13572,7 +13572,7 @@ first_or_next: FIRST_P								{ $$ = 0; }
 group_clause:
 			GROUP_P BY set_quantifier group_by_list
 				{
-					GroupClause *n = (GroupClause *) palloc(sizeof(GroupClause));
+					GroupClause *n = palloc_object(GroupClause);
 
 					n->distinct = $3 == SET_QUANTIFIER_DISTINCT;
 					n->all = false;
@@ -13581,7 +13581,7 @@ group_clause:
 				}
 			| GROUP_P BY ALL
 				{
-					GroupClause *n = (GroupClause *) palloc(sizeof(GroupClause));
+					GroupClause *n = palloc_object(GroupClause);
 					n->distinct = false;
 					n->all = true;
 					n->list = NIL;
@@ -13589,7 +13589,7 @@ group_clause:
 				}
 			| /*EMPTY*/
 				{
-					GroupClause *n = (GroupClause *) palloc(sizeof(GroupClause));
+					GroupClause *n = palloc_object(GroupClause);
 
 					n->distinct = false;
 					n->all = false;
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index ca26f6f61f2..944482207f3 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -733,7 +733,7 @@ transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf)
 	tf->ordinalitycol = -1;
 
 	/* Process column specs */
-	names = palloc(sizeof(char *) * list_length(rtf->columns));
+	names = palloc_array(char *, list_length(rtf->columns));
 
 	colno = 0;
 	foreach(col, rtf->columns)
@@ -1573,7 +1573,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
 		{
 			ParseNamespaceItem *jnsitem;
 
-			jnsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+			jnsitem = palloc_object(ParseNamespaceItem);
 			jnsitem->p_names = j->join_using_alias;
 			jnsitem->p_rte = nsitem->p_rte;
 			jnsitem->p_rtindex = nsitem->p_rtindex;
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 4524e49c326..6b8fa15fca3 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -2906,7 +2906,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
 	 * operators, and see which interpretations (cmptypes) exist for each
 	 * operator.
 	 */
-	opinfo_lists = (List **) palloc(nopers * sizeof(List *));
+	opinfo_lists = palloc_array(List *, nopers);
 	cmptypes = NULL;
 	i = 0;
 	foreach(l, opexprs)
@@ -3241,7 +3241,7 @@ getJsonEncodingConst(JsonFormat *format)
 {
 	JsonEncoding encoding;
 	const char *enc;
-	Name		encname = palloc(sizeof(NameData));
+	Name		encname = palloc_object(NameData);
 
 	if (!format ||
 		format->format_type == JS_FORMAT_DEFAULT ||
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 203b7a32178..cafeb87217c 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -40,7 +40,7 @@ make_parsestate(ParseState *parentParseState)
 {
 	ParseState *pstate;
 
-	pstate = palloc0(sizeof(ParseState));
+	pstate = palloc0_object(ParseState);
 
 	pstate->parentParseState = parentParseState;
 
diff --git a/src/backend/parser/parse_param.c b/src/backend/parser/parse_param.c
index 930921626b6..772f3e3c1d8 100644
--- a/src/backend/parser/parse_param.c
+++ b/src/backend/parser/parse_param.c
@@ -68,7 +68,7 @@ void
 setup_parse_fixed_parameters(ParseState *pstate,
 							 const Oid *paramTypes, int numParams)
 {
-	FixedParamState *parstate = palloc(sizeof(FixedParamState));
+	FixedParamState *parstate = palloc_object(FixedParamState);
 
 	parstate->paramTypes = paramTypes;
 	parstate->numParams = numParams;
@@ -84,7 +84,7 @@ void
 setup_parse_variable_parameters(ParseState *pstate,
 								Oid **paramTypes, int *numParams)
 {
-	VarParamState *parstate = palloc(sizeof(VarParamState));
+	VarParamState *parstate = palloc_object(VarParamState);
 
 	parstate->paramTypes = paramTypes;
 	parstate->numParams = numParams;
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index d544a69fc80..dd64f45478a 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -964,7 +964,7 @@ searchRangeTableForCol(ParseState *pstate, const char *alias, const char *colnam
 					   int location)
 {
 	ParseState *orig_pstate = pstate;
-	FuzzyAttrMatchState *fuzzystate = palloc(sizeof(FuzzyAttrMatchState));
+	FuzzyAttrMatchState *fuzzystate = palloc_object(FuzzyAttrMatchState);
 
 	fuzzystate->distance = MAX_FUZZY_DISTANCE + 1;
 	fuzzystate->rfirst = NULL;
@@ -1336,7 +1336,7 @@ buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex,
 	}
 
 	/* ... and build the nsitem */
-	nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+	nsitem = palloc_object(ParseNamespaceItem);
 	nsitem->p_names = rte->eref;
 	nsitem->p_rte = rte;
 	nsitem->p_rtindex = rtindex;
@@ -1400,7 +1400,7 @@ buildNSItemFromLists(RangeTblEntry *rte, Index rtindex,
 	}
 
 	/* ... and build the nsitem */
-	nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+	nsitem = palloc_object(ParseNamespaceItem);
 	nsitem->p_names = rte->eref;
 	nsitem->p_rte = rte;
 	nsitem->p_rtindex = rtindex;
@@ -1791,7 +1791,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
 	rte->eref = eref;
 
 	/* Process each function ... */
-	functupdescs = (TupleDesc *) palloc(nfuncs * sizeof(TupleDesc));
+	functupdescs = palloc_array(TupleDesc, nfuncs);
 
 	totalatts = 0;
 	funcno = 0;
@@ -2302,7 +2302,7 @@ addRangeTableEntryForJoin(ParseState *pstate,
 	 * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
 	 * list --- caller must do that if appropriate.
 	 */
-	nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+	nsitem = palloc_object(ParseNamespaceItem);
 	nsitem->p_names = rte->eref;
 	nsitem->p_rte = rte;
 	nsitem->p_perminfo = NULL;
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 7713bdc6af0..c7335ad9db1 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -369,7 +369,7 @@ typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ)
 	 * Currently, we allow simple numeric constants, string literals, and
 	 * identifiers; possibly this list could be extended.
 	 */
-	datums = (Datum *) palloc(list_length(typeName->typmods) * sizeof(Datum));
+	datums = palloc_array(Datum, list_length(typeName->typmods));
 	n = 0;
 	foreach(l, typeName->typmods)
 	{
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 8ba038c5ef4..687a337320e 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -319,7 +319,7 @@ partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts,
 	 * Initialize mapping array with invalid values, this is filled within
 	 * each sub-routine below depending on the bound type.
 	 */
-	*mapping = (int *) palloc(sizeof(int) * nparts);
+	*mapping = palloc_array(int, nparts);
 	for (i = 0; i < nparts; i++)
 		(*mapping)[i] = -1;
 
@@ -353,8 +353,7 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	int			greatest_modulus;
 	Datum	   *boundDatums;
 
-	boundinfo = (PartitionBoundInfoData *)
-		palloc0(sizeof(PartitionBoundInfoData));
+	boundinfo = palloc0_object(PartitionBoundInfoData);
 	boundinfo->strategy = key->strategy;
 	/* No special hash partitions. */
 	boundinfo->null_index = -1;
@@ -384,7 +383,7 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	greatest_modulus = hbounds[nparts - 1].modulus;
 
 	boundinfo->ndatums = nparts;
-	boundinfo->datums = (Datum **) palloc0(nparts * sizeof(Datum *));
+	boundinfo->datums = (Datum **) palloc0_array(Datum *, nparts);
 	boundinfo->kind = NULL;
 	boundinfo->interleaved_parts = NULL;
 	boundinfo->nindexes = greatest_modulus;
@@ -472,8 +471,7 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	int			null_index = -1;
 	Datum	   *boundDatums;
 
-	boundinfo = (PartitionBoundInfoData *)
-		palloc0(sizeof(PartitionBoundInfoData));
+	boundinfo = palloc0_object(PartitionBoundInfoData);
 	boundinfo->strategy = key->strategy;
 	/* Will be set correctly below. */
 	boundinfo->null_index = -1;
@@ -533,7 +531,7 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
 			  qsort_partition_list_value_cmp, key);
 
 	boundinfo->ndatums = ndatums;
-	boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
+	boundinfo->datums = (Datum **) palloc0_array(Datum *, ndatums);
 	boundinfo->kind = NULL;
 	boundinfo->interleaved_parts = NULL;
 	boundinfo->nindexes = ndatums;
@@ -690,8 +688,7 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	Datum	   *boundDatums;
 	PartitionRangeDatumKind *boundKinds;
 
-	boundinfo = (PartitionBoundInfoData *)
-		palloc0(sizeof(PartitionBoundInfoData));
+	boundinfo = palloc0_object(PartitionBoundInfoData);
 	boundinfo->strategy = key->strategy;
 	/* There is no special null-accepting range partition. */
 	boundinfo->null_index = -1;
@@ -699,7 +696,7 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	boundinfo->default_index = -1;
 
 	all_bounds = (PartitionRangeBound **)
-		palloc0(2 * nparts * sizeof(PartitionRangeBound *));
+		palloc0_array(PartitionRangeBound *, 2 * nparts);
 
 	/* Create a unified list of range bounds across all the partitions. */
 	ndatums = 0;
@@ -803,7 +800,7 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	 * bound.
 	 */
 	boundinfo->ndatums = ndatums;
-	boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
+	boundinfo->datums = (Datum **) palloc0_array(Datum *, ndatums);
 	boundinfo->kind = (PartitionRangeDatumKind **)
 		palloc(ndatums *
 			   sizeof(PartitionRangeDatumKind *));
@@ -1008,7 +1005,7 @@ partition_bounds_copy(PartitionBoundInfo src,
 	int			nindexes;
 	int			partnatts;
 
-	dest = (PartitionBoundInfo) palloc(sizeof(PartitionBoundInfoData));
+	dest = (PartitionBoundInfo) palloc_object(PartitionBoundInfoData);
 
 	dest->strategy = src->strategy;
 	ndatums = dest->ndatums = src->ndatums;
@@ -1018,7 +1015,7 @@ partition_bounds_copy(PartitionBoundInfo src,
 	/* List partitioned tables have only a single partition key. */
 	Assert(key->strategy != PARTITION_STRATEGY_LIST || partnatts == 1);
 
-	dest->datums = (Datum **) palloc(sizeof(Datum *) * ndatums);
+	dest->datums = palloc_array(Datum *, ndatums);
 
 	if (src->kind != NULL && ndatums > 0)
 	{
@@ -1092,7 +1089,7 @@ partition_bounds_copy(PartitionBoundInfo src,
 		}
 	}
 
-	dest->indexes = (int *) palloc(sizeof(int) * nindexes);
+	dest->indexes = palloc_array(int, nindexes);
 	memcpy(dest->indexes, src->indexes, sizeof(int) * nindexes);
 
 	dest->null_index = src->null_index;
@@ -1815,10 +1812,10 @@ init_partition_map(RelOptInfo *rel, PartitionMap *map)
 	int			i;
 
 	map->nparts = nparts;
-	map->merged_indexes = (int *) palloc(sizeof(int) * nparts);
-	map->merged = (bool *) palloc(sizeof(bool) * nparts);
+	map->merged_indexes = palloc_array(int, nparts);
+	map->merged = palloc_array(bool, nparts);
 	map->did_remapping = false;
-	map->old_indexes = (int *) palloc(sizeof(int) * nparts);
+	map->old_indexes = palloc_array(int, nparts);
 	for (i = 0; i < nparts; i++)
 	{
 		map->merged_indexes[i] = map->old_indexes[i] = -1;
@@ -2393,7 +2390,7 @@ fix_merged_indexes(PartitionMap *outer_map, PartitionMap *inner_map,
 
 	Assert(nmerged > 0);
 
-	new_indexes = (int *) palloc(sizeof(int) * nmerged);
+	new_indexes = palloc_array(int, nmerged);
 	for (i = 0; i < nmerged; i++)
 		new_indexes[i] = -1;
 
@@ -2453,8 +2450,8 @@ generate_matching_part_pairs(RelOptInfo *outer_rel, RelOptInfo *inner_rel,
 	Assert(*outer_parts == NIL);
 	Assert(*inner_parts == NIL);
 
-	outer_indexes = (int *) palloc(sizeof(int) * nmerged);
-	inner_indexes = (int *) palloc(sizeof(int) * nmerged);
+	outer_indexes = palloc_array(int, nmerged);
+	inner_indexes = palloc_array(int, nmerged);
 	for (i = 0; i < nmerged; i++)
 		outer_indexes[i] = inner_indexes[i] = -1;
 
@@ -2525,11 +2522,11 @@ build_merged_partition_bounds(char strategy, List *merged_datums,
 	int			pos;
 	ListCell   *lc;
 
-	merged_bounds = (PartitionBoundInfo) palloc(sizeof(PartitionBoundInfoData));
+	merged_bounds = (PartitionBoundInfo) palloc_object(PartitionBoundInfoData);
 	merged_bounds->strategy = strategy;
 	merged_bounds->ndatums = ndatums;
 
-	merged_bounds->datums = (Datum **) palloc(sizeof(Datum *) * ndatums);
+	merged_bounds->datums = palloc_array(Datum *, ndatums);
 	pos = 0;
 	foreach(lc, merged_datums)
 		merged_bounds->datums[pos++] = (Datum *) lfirst(lc);
@@ -2537,8 +2534,7 @@ build_merged_partition_bounds(char strategy, List *merged_datums,
 	if (strategy == PARTITION_STRATEGY_RANGE)
 	{
 		Assert(list_length(merged_kinds) == ndatums);
-		merged_bounds->kind = (PartitionRangeDatumKind **)
-			palloc(sizeof(PartitionRangeDatumKind *) * ndatums);
+		merged_bounds->kind = palloc_array(PartitionRangeDatumKind *, ndatums);
 		pos = 0;
 		foreach(lc, merged_kinds)
 			merged_bounds->kind[pos++] = (PartitionRangeDatumKind *) lfirst(lc);
@@ -2559,7 +2555,7 @@ build_merged_partition_bounds(char strategy, List *merged_datums,
 
 	Assert(list_length(merged_indexes) == ndatums);
 	merged_bounds->nindexes = ndatums;
-	merged_bounds->indexes = (int *) palloc(sizeof(int) * ndatums);
+	merged_bounds->indexes = palloc_array(int, ndatums);
 	pos = 0;
 	foreach(lc, merged_indexes)
 		merged_bounds->indexes[pos++] = lfirst_int(lc);
@@ -3434,11 +3430,10 @@ make_one_partition_rbound(PartitionKey key, int index, List *datums, bool lower)
 
 	Assert(datums != NIL);
 
-	bound = (PartitionRangeBound *) palloc0(sizeof(PartitionRangeBound));
+	bound = palloc0_object(PartitionRangeBound);
 	bound->index = index;
-	bound->datums = (Datum *) palloc0(key->partnatts * sizeof(Datum));
-	bound->kind = (PartitionRangeDatumKind *) palloc0(key->partnatts *
-													  sizeof(PartitionRangeDatumKind));
+	bound->datums = palloc0_array(Datum, key->partnatts);
+	bound->kind = palloc0_array(PartitionRangeDatumKind, key->partnatts);
 	bound->lower = lower;
 
 	i = 0;
diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c
index 328b4d450e4..5624f503fec 100644
--- a/src/backend/partitioning/partdesc.c
+++ b/src/backend/partitioning/partdesc.c
@@ -426,7 +426,7 @@ CreatePartitionDirectory(MemoryContext mcxt, bool omit_detached)
 	PartitionDirectory pdir;
 	HASHCTL		ctl;
 
-	pdir = palloc(sizeof(PartitionDirectoryData));
+	pdir = palloc_object(PartitionDirectoryData);
 	pdir->pdir_mcxt = mcxt;
 
 	ctl.keysize = sizeof(Oid);
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 1c38488f2cb..ed3e7255442 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -1865,7 +1865,7 @@ get_database_list(void)
 		 */
 		oldcxt = MemoryContextSwitchTo(resultcxt);
 
-		avdb = (avw_dbase *) palloc(sizeof(avw_dbase));
+		avdb = palloc_object(avw_dbase);
 
 		avdb->adw_datid = pgdatabase->oid;
 		avdb->adw_name = pstrdup(NameStr(pgdatabase->datname));
@@ -2753,7 +2753,7 @@ extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
 	if (relopts == NULL)
 		return NULL;
 
-	av = palloc(sizeof(AutoVacOpts));
+	av = palloc_object(AutoVacOpts);
 	memcpy(av, &(((StdRdOptions *) relopts)->autovacuum), sizeof(AutoVacOpts));
 	pfree(relopts);
 
@@ -2857,7 +2857,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
-		tab = palloc(sizeof(autovac_table));
+		tab = palloc_object(autovac_table);
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
 
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 142a02eb5e9..8e1068969ae 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -1132,7 +1132,7 @@ RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
 	 */
 	if (success && handle)
 	{
-		*handle = palloc(sizeof(BackgroundWorkerHandle));
+		*handle = palloc_object(BackgroundWorkerHandle);
 		(*handle)->slot = slotno;
 		(*handle)->generation = generation;
 	}
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index e84e8663e96..f9d1d5ec93c 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -1316,7 +1316,7 @@ CompactCheckpointerRequestQueue(void)
 	num_requests = CheckpointerShmem->num_requests;
 
 	/* Initialize skip_slot array */
-	skip_slot = palloc0(sizeof(bool) * max_requests);
+	skip_slot = palloc0_array(bool, max_requests);
 
 	head = CheckpointerShmem->head;
 
diff --git a/src/backend/postmaster/launch_backend.c b/src/backend/postmaster/launch_backend.c
index 976638a58ac..98f7c4848c9 100644
--- a/src/backend/postmaster/launch_backend.c
+++ b/src/backend/postmaster/launch_backend.c
@@ -258,7 +258,7 @@ postmaster_child_launch(BackendType child_type, int child_slot,
 		MyPMChildSlot = child_slot;
 		if (client_sock)
 		{
-			MyClientSocket = palloc(sizeof(ClientSocket));
+			MyClientSocket = palloc_object(ClientSocket);
 			memcpy(MyClientSocket, client_sock, sizeof(ClientSocket));
 		}
 
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index ce6b5299324..3a65d841725 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -257,7 +257,7 @@ PgArchiverMain(const void *startup_data, size_t startup_data_len)
 	PgArch->pgprocno = MyProcNumber;
 
 	/* Create workspace for pgarch_readyXlog() */
-	arch_files = palloc(sizeof(struct arch_files_state));
+	arch_files = palloc_object(struct arch_files_state);
 	arch_files->arch_files_size = 0;
 
 	/* Initialize our max-heap for prioritizing files to archive. */
@@ -945,7 +945,7 @@ LoadArchiveLibrary(void)
 		ereport(ERROR,
 				(errmsg("archive modules must register an archive callback")));
 
-	archive_module_state = (ArchiveModuleState *) palloc0(sizeof(ArchiveModuleState));
+	archive_module_state = palloc0_object(ArchiveModuleState);
 	if (ArchiveCallbacks->startup_cb != NULL)
 		ArchiveCallbacks->startup_cb(archive_module_state);
 
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index a956db4ad27..7dd3a201b1c 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4562,7 +4562,7 @@ pgwin32_register_deadchild_callback(HANDLE procHandle, DWORD procId)
 {
 	win32_deadchild_waitinfo *childinfo;
 
-	childinfo = palloc(sizeof(win32_deadchild_waitinfo));
+	childinfo = palloc_object(win32_deadchild_waitinfo);
 	childinfo->procHandle = procHandle;
 	childinfo->procId = procId;
 
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 50c2edec1f6..526ad053a45 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -960,7 +960,7 @@ process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
 						 * Need a free slot, but there isn't one in the list,
 						 * so create a new one and extend the list with it.
 						 */
-						free_slot = palloc(sizeof(save_buffer));
+						free_slot = palloc_object(save_buffer);
 						buffer_list = lappend(buffer_list, free_slot);
 						buffer_lists[p.pid % NBUFFER_LISTS] = buffer_list;
 					}
diff --git a/src/backend/postmaster/walsummarizer.c b/src/backend/postmaster/walsummarizer.c
index c4a888a081c..e7e4d652f97 100644
--- a/src/backend/postmaster/walsummarizer.c
+++ b/src/backend/postmaster/walsummarizer.c
@@ -920,8 +920,7 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact,
 	bool		fast_forward = true;
 
 	/* Initialize private data for xlogreader. */
-	private_data = (SummarizerReadLocalXLogPrivate *)
-		palloc0(sizeof(SummarizerReadLocalXLogPrivate));
+	private_data = palloc0_object(SummarizerReadLocalXLogPrivate);
 	private_data->tli = tli;
 	private_data->historic = XLogRecPtrIsValid(switch_lsn);
 	private_data->read_upto = maximum_lsn;
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 239641bfbb6..5ddc9e812e7 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -211,7 +211,7 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
 
 	Assert(i < lengthof(keys));
 
-	conn = palloc0(sizeof(WalReceiverConn));
+	conn = palloc0_object(WalReceiverConn);
 	conn->streamConn =
 		libpqsrv_connect_params(keys, vals,
 								 /* expand_dbname = */ true,
@@ -1102,7 +1102,7 @@ libpqrcv_exec(WalReceiverConn *conn, const char *query,
 			  const int nRetTypes, const Oid *retTypes)
 {
 	PGresult   *pgres = NULL;
-	WalRcvExecResult *walres = palloc0(sizeof(WalRcvExecResult));
+	WalRcvExecResult *walres = palloc0_object(WalRcvExecResult);
 	char	   *diag_sqlstate;
 
 	if (MyDatabaseId == InvalidOid)
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index baa68c1ab6c..43bea31f177 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -425,7 +425,7 @@ pa_launch_parallel_worker(void)
 	 */
 	oldcontext = MemoryContextSwitchTo(ApplyContext);
 
-	winfo = (ParallelApplyWorkerInfo *) palloc0(sizeof(ParallelApplyWorkerInfo));
+	winfo = palloc0_object(ParallelApplyWorkerInfo);
 
 	/* Setup shared memory. */
 	if (!pa_setup_dsm(winfo))
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index fdf1ccad462..3991e1495d4 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -147,7 +147,7 @@ get_subscription_list(void)
 		 */
 		oldcxt = MemoryContextSwitchTo(resultcxt);
 
-		sub = (Subscription *) palloc0(sizeof(Subscription));
+		sub = palloc0_object(Subscription);
 		sub->oid = subform->oid;
 		sub->dbid = subform->subdbid;
 		sub->owner = subform->subowner;
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index 866f92cf799..1b11ed63dc6 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -172,7 +172,7 @@ StartupDecodingContext(List *output_plugin_options,
 									"Logical decoding context",
 									ALLOCSET_DEFAULT_SIZES);
 	old_context = MemoryContextSwitchTo(context);
-	ctx = palloc0(sizeof(LogicalDecodingContext));
+	ctx = palloc0_object(LogicalDecodingContext);
 
 	ctx->context = context;
 
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
index 25b2b795925..cf77ee28dfe 100644
--- a/src/backend/replication/logical/logicalfuncs.c
+++ b/src/backend/replication/logical/logicalfuncs.c
@@ -140,7 +140,7 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
 	arr = PG_GETARG_ARRAYTYPE_P(3);
 
 	/* state to write output to */
-	p = palloc0(sizeof(DecodingOutputState));
+	p = palloc0_object(DecodingOutputState);
 
 	p->binary_output = binary;
 
diff --git a/src/backend/replication/logical/proto.c b/src/backend/replication/logical/proto.c
index f0a913892b9..27ad74fd759 100644
--- a/src/backend/replication/logical/proto.c
+++ b/src/backend/replication/logical/proto.c
@@ -697,7 +697,7 @@ logicalrep_write_rel(StringInfo out, TransactionId xid, Relation rel,
 LogicalRepRelation *
 logicalrep_read_rel(StringInfo in)
 {
-	LogicalRepRelation *rel = palloc(sizeof(LogicalRepRelation));
+	LogicalRepRelation *rel = palloc_object(LogicalRepRelation);
 
 	rel->remoteid = pq_getmsgint(in, 4);
 
@@ -871,7 +871,7 @@ logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple)
 
 	/* Allocate space for per-column values; zero out unused StringInfoDatas */
 	tuple->colvalues = (StringInfoData *) palloc0(natts * sizeof(StringInfoData));
-	tuple->colstatus = (char *) palloc(natts * sizeof(char));
+	tuple->colstatus = palloc_array(char, natts);
 	tuple->ncols = natts;
 
 	/* Read the data */
@@ -994,8 +994,8 @@ logicalrep_read_attrs(StringInfo in, LogicalRepRelation *rel)
 	Bitmapset  *attkeys = NULL;
 
 	natts = pq_getmsgint(in, 2);
-	attnames = palloc(natts * sizeof(char *));
-	atttyps = palloc(natts * sizeof(Oid));
+	attnames = palloc_array(char *, natts);
+	atttyps = palloc_array(Oid, natts);
 
 	/* read the attributes */
 	for (i = 0; i < natts; i++)
diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c
index 10b3d0d9b82..2c8485b881f 100644
--- a/src/backend/replication/logical/relation.c
+++ b/src/backend/replication/logical/relation.c
@@ -188,8 +188,8 @@ logicalrep_relmap_update(LogicalRepRelation *remoterel)
 	entry->remoterel.nspname = pstrdup(remoterel->nspname);
 	entry->remoterel.relname = pstrdup(remoterel->relname);
 	entry->remoterel.natts = remoterel->natts;
-	entry->remoterel.attnames = palloc(remoterel->natts * sizeof(char *));
-	entry->remoterel.atttyps = palloc(remoterel->natts * sizeof(Oid));
+	entry->remoterel.attnames = palloc_array(char *, remoterel->natts);
+	entry->remoterel.atttyps = palloc_array(Oid, remoterel->natts);
 	for (i = 0; i < remoterel->natts; i++)
 	{
 		entry->remoterel.attnames[i] = pstrdup(remoterel->attnames[i]);
@@ -704,8 +704,8 @@ logicalrep_partition_open(LogicalRepRelMapEntry *root,
 		entry->remoterel.nspname = pstrdup(remoterel->nspname);
 		entry->remoterel.relname = pstrdup(remoterel->relname);
 		entry->remoterel.natts = remoterel->natts;
-		entry->remoterel.attnames = palloc(remoterel->natts * sizeof(char *));
-		entry->remoterel.atttyps = palloc(remoterel->natts * sizeof(Oid));
+		entry->remoterel.attnames = palloc_array(char *, remoterel->natts);
+		entry->remoterel.atttyps = palloc_array(Oid, remoterel->natts);
 		for (i = 0; i < remoterel->natts; i++)
 		{
 			entry->remoterel.attnames[i] = pstrdup(remoterel->attnames[i]);
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index eb6a84554b7..f18c6fb52b5 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -3489,8 +3489,7 @@ ReorderBufferQueueInvalidations(ReorderBuffer *rb, TransactionId xid,
 	change = ReorderBufferAllocChange(rb);
 	change->action = REORDER_BUFFER_CHANGE_INVALIDATION;
 	change->data.inval.ninvalidations = nmsgs;
-	change->data.inval.invalidations = (SharedInvalidationMessage *)
-		palloc(sizeof(SharedInvalidationMessage) * nmsgs);
+	change->data.inval.invalidations = palloc_array(SharedInvalidationMessage, nmsgs);
 	memcpy(change->data.inval.invalidations, msgs,
 		   sizeof(SharedInvalidationMessage) * nmsgs);
 
@@ -3511,8 +3510,7 @@ ReorderBufferAccumulateInvalidations(SharedInvalidationMessage **invals_out,
 	if (*ninvals_out == 0)
 	{
 		*ninvals_out = nmsgs_new;
-		*invals_out = (SharedInvalidationMessage *)
-			palloc(sizeof(SharedInvalidationMessage) * nmsgs_new);
+		*invals_out = palloc_array(SharedInvalidationMessage, nmsgs_new);
 		memcpy(*invals_out, msgs_new, sizeof(SharedInvalidationMessage) * nmsgs_new);
 	}
 	else
@@ -3701,8 +3699,7 @@ ReorderBufferGetCatalogChangesXacts(ReorderBuffer *rb)
 		return NULL;
 
 	/* Initialize XID array */
-	xids = (TransactionId *) palloc(sizeof(TransactionId) *
-									dclist_count(&rb->catchange_txns));
+	xids = palloc_array(TransactionId, dclist_count(&rb->catchange_txns));
 	dclist_foreach(iter, &rb->catchange_txns)
 	{
 		ReorderBufferTXN *txn = dclist_container(ReorderBufferTXN,
@@ -5124,9 +5121,9 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
 	toast_desc = RelationGetDescr(toast_rel);
 
 	/* should we allocate from stack instead? */
-	attrs = palloc0(sizeof(Datum) * desc->natts);
-	isnull = palloc0(sizeof(bool) * desc->natts);
-	free = palloc0(sizeof(bool) * desc->natts);
+	attrs = palloc0_array(Datum, desc->natts);
+	isnull = palloc0_array(bool, desc->natts);
+	free = palloc0_array(bool, desc->natts);
 
 	newtup = change->data.tp.newtuple;
 
@@ -5531,7 +5528,7 @@ UpdateLogicalMappings(HTAB *tuplecid_data, Oid relid, Snapshot snapshot)
 			continue;
 
 		/* ok, relevant, queue for apply */
-		f = palloc(sizeof(RewriteMappingFile));
+		f = palloc_object(RewriteMappingFile);
 		f->lsn = f_lsn;
 		strcpy(f->fname, mapping_de->d_name);
 		files = lappend(files, f);
diff --git a/src/backend/replication/logical/slotsync.c b/src/backend/replication/logical/slotsync.c
index 53c7d629239..fbebc628af5 100644
--- a/src/backend/replication/logical/slotsync.c
+++ b/src/backend/replication/logical/slotsync.c
@@ -919,7 +919,7 @@ synchronize_slots(WalReceiverConn *wrconn)
 	while (tuplestore_gettupleslot(res->tuplestore, true, false, tupslot))
 	{
 		bool		isnull;
-		RemoteSlot *remote_slot = palloc0(sizeof(RemoteSlot));
+		RemoteSlot *remote_slot = palloc0_object(RemoteSlot);
 		Datum		d;
 		int			col = 0;
 
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index 6e18baa33cb..d6ab1e017eb 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -199,7 +199,7 @@ AllocateSnapshotBuilder(ReorderBuffer *reorder,
 									ALLOCSET_DEFAULT_SIZES);
 	oldcontext = MemoryContextSwitchTo(context);
 
-	builder = palloc0(sizeof(SnapBuild));
+	builder = palloc0_object(SnapBuild);
 
 	builder->state = SNAPBUILD_START;
 	builder->context = context;
@@ -486,8 +486,7 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
 	MyProc->xmin = snap->xmin;
 
 	/* allocate in transaction context */
-	newxip = (TransactionId *)
-		palloc(sizeof(TransactionId) * GetMaxSnapshotXidCount());
+	newxip = palloc_array(TransactionId, GetMaxSnapshotXidCount());
 
 	/*
 	 * snapbuild.c builds transactions in an "inverted" manner, which means it
diff --git a/src/backend/replication/logical/syncutils.c b/src/backend/replication/logical/syncutils.c
index a696b1f2dc0..332819804be 100644
--- a/src/backend/replication/logical/syncutils.c
+++ b/src/backend/replication/logical/syncutils.c
@@ -243,7 +243,7 @@ FetchRelationStates(bool *has_pending_subtables,
 				has_subsequences_non_ready = true;
 			else
 			{
-				rstate = palloc(sizeof(SubscriptionRelState));
+				rstate = palloc_object(SubscriptionRelState);
 				memcpy(rstate, subrel, sizeof(SubscriptionRelState));
 				table_states_not_ready = lappend(table_states_not_ready,
 												 rstate);
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 93970c6af29..ffde284dd3c 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -875,7 +875,7 @@ create_edata_for_relation(LogicalRepRelMapEntry *rel)
 	List	   *perminfos = NIL;
 	ResultRelInfo *resultRelInfo;
 
-	edata = (ApplyExecutionData *) palloc0(sizeof(ApplyExecutionData));
+	edata = palloc0_object(ApplyExecutionData);
 	edata->targetRel = rel;
 
 	edata->estate = estate = CreateExecutorState();
@@ -1702,7 +1702,7 @@ stream_start_internal(TransactionId xid, bool first_segment)
 
 		oldctx = MemoryContextSwitchTo(ApplyContext);
 
-		MyLogicalRepWorker->stream_fileset = palloc(sizeof(FileSet));
+		MyLogicalRepWorker->stream_fileset = palloc_object(FileSet);
 		FileSetInit(MyLogicalRepWorker->stream_fileset);
 
 		MemoryContextSwitchTo(oldctx);
@@ -3951,7 +3951,7 @@ store_flush_position(XLogRecPtr remote_lsn, XLogRecPtr local_lsn)
 	MemoryContextSwitchTo(ApplyContext);
 
 	/* Track commit lsn  */
-	flushpos = (FlushPosition *) palloc(sizeof(FlushPosition));
+	flushpos = palloc_object(FlushPosition);
 	flushpos->local_end = local_lsn;
 	flushpos->remote_end = remote_lsn;
 
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 942e1abdb58..787998abb8a 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -447,7 +447,7 @@ static void
 pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 				 bool is_init)
 {
-	PGOutputData *data = palloc0(sizeof(PGOutputData));
+	PGOutputData *data = palloc0_object(PGOutputData);
 	static bool publication_callback_registered = false;
 	MemoryContextCallback *mcallback;
 
@@ -468,7 +468,7 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 	 * Ensure to cleanup RelationSyncCache even when logical decoding invoked
 	 * via SQL interface ends up with an error.
 	 */
-	mcallback = palloc0(sizeof(MemoryContextCallback));
+	mcallback = palloc0_object(MemoryContextCallback);
 	mcallback->func = pgoutput_memory_context_reset;
 	MemoryContextRegisterResetCallback(ctx->context, mcallback);
 
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index a0c79958fd5..298a3766d76 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -705,9 +705,9 @@ SyncRepGetNthLatestSyncRecPtr(XLogRecPtr *writePtr,
 	/* Should have enough candidates, or somebody messed up */
 	Assert(nth > 0 && nth <= num_standbys);
 
-	write_array = (XLogRecPtr *) palloc(sizeof(XLogRecPtr) * num_standbys);
-	flush_array = (XLogRecPtr *) palloc(sizeof(XLogRecPtr) * num_standbys);
-	apply_array = (XLogRecPtr *) palloc(sizeof(XLogRecPtr) * num_standbys);
+	write_array = palloc_array(XLogRecPtr, num_standbys);
+	flush_array = palloc_array(XLogRecPtr, num_standbys);
+	apply_array = palloc_array(XLogRecPtr, num_standbys);
 
 	for (i = 0; i < num_standbys; i++)
 	{
@@ -757,8 +757,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys)
 	int			n;
 
 	/* Create result array */
-	*standbys = (SyncRepStandbyData *)
-		palloc(max_wal_senders * sizeof(SyncRepStandbyData));
+	*standbys = palloc_array(SyncRepStandbyData, max_wal_senders);
 
 	/* Quick exit if sync replication is not requested */
 	if (SyncRepConfig == NULL)
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 4217fc54e2e..3ac48a847b3 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -1450,8 +1450,8 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS)
 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
 		elog(ERROR, "return type must be a row type");
 
-	values = palloc0(sizeof(Datum) * tupdesc->natts);
-	nulls = palloc0(sizeof(bool) * tupdesc->natts);
+	values = palloc0_array(Datum, tupdesc->natts);
+	nulls = palloc0_array(bool, tupdesc->natts);
 
 	/* Fetch values */
 	values[0] = Int32GetDatum(pid);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index a1b4301a4ee..e2d07786281 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -3973,7 +3973,7 @@ WalSndGetStateString(WalSndState state)
 static Interval *
 offset_to_interval(TimeOffset offset)
 {
-	Interval   *result = palloc(sizeof(Interval));
+	Interval   *result = palloc_object(Interval);
 
 	result->month = 0;
 	result->day = 0;
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index ffcf2ff1fe2..688dcd09ca6 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -4287,7 +4287,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events, int orig_rt_length,
 									RelationGetRelationName(rt_entry_relation))));
 			}
 
-			rev = (rewrite_event *) palloc(sizeof(rewrite_event));
+			rev = palloc_object(rewrite_event);
 			rev->relation = RelationGetRelid(rt_entry_relation);
 			rev->event = event;
 			rewrite_events = lappend(rewrite_events, rev);
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index 0fcd1fbd14e..f3c2886ed54 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -1590,7 +1590,7 @@ map_variable_attnos_mutator(Node *node,
 			var->varlevelsup == context->sublevels_up)
 		{
 			/* Found a matching variable, make the substitution */
-			Var		   *newvar = (Var *) palloc(sizeof(Var));
+			Var		   *newvar = palloc_object(Var);
 			int			attno = var->varattno;
 
 			*newvar = *var;		/* initially copy all fields of the Var */
@@ -1661,7 +1661,7 @@ map_variable_attnos_mutator(Node *node,
 			context->to_rowtype != var->vartype)
 		{
 			ConvertRowtypeExpr *newnode;
-			Var		   *newvar = (Var *) palloc(sizeof(Var));
+			Var		   *newvar = palloc_object(Var);
 
 			/* whole-row variable, warn caller */
 			*(context->found_whole_row) = true;
@@ -1674,7 +1674,7 @@ map_variable_attnos_mutator(Node *node,
 			/* Var itself is changed to the requested type. */
 			newvar->vartype = context->to_rowtype;
 
-			newnode = (ConvertRowtypeExpr *) palloc(sizeof(ConvertRowtypeExpr));
+			newnode = palloc_object(ConvertRowtypeExpr);
 			*newnode = *r;		/* initially copy all fields of the CRE */
 			newnode->arg = (Expr *) newvar;
 
diff --git a/src/backend/snowball/dict_snowball.c b/src/backend/snowball/dict_snowball.c
index e2b811a3806..d3c022ae548 100644
--- a/src/backend/snowball/dict_snowball.c
+++ b/src/backend/snowball/dict_snowball.c
@@ -229,7 +229,7 @@ dsnowball_init(PG_FUNCTION_ARGS)
 	bool		stoploaded = false;
 	ListCell   *l;
 
-	d = (DictSnowball *) palloc0(sizeof(DictSnowball));
+	d = palloc0_object(DictSnowball);
 
 	foreach(l, dictoptions)
 	{
@@ -278,7 +278,7 @@ dsnowball_lexize(PG_FUNCTION_ARGS)
 	char	   *in = (char *) PG_GETARG_POINTER(1);
 	int32		len = PG_GETARG_INT32(2);
 	char	   *txt = str_tolower(in, len, DEFAULT_COLLATION_OID);
-	TSLexeme   *res = palloc0(sizeof(TSLexeme) * 2);
+	TSLexeme   *res = palloc0_array(TSLexeme, 2);
 
 	/*
 	 * Do not pass strings exceeding 1000 bytes to the stemmer, as they're
diff --git a/src/backend/statistics/dependencies.c b/src/backend/statistics/dependencies.c
index d7bf6b7e846..2aed867d5e7 100644
--- a/src/backend/statistics/dependencies.c
+++ b/src/backend/statistics/dependencies.c
@@ -150,7 +150,7 @@ generate_dependencies_recurse(DependencyGenerator state, int index,
 static void
 generate_dependencies(DependencyGenerator state)
 {
-	AttrNumber *current = (AttrNumber *) palloc0(sizeof(AttrNumber) * state->k);
+	AttrNumber *current = palloc0_array(AttrNumber, state->k);
 
 	generate_dependencies_recurse(state, 0, 0, current);
 
@@ -171,8 +171,8 @@ DependencyGenerator_init(int n, int k)
 	Assert((n >= k) && (k > 0));
 
 	/* allocate the DependencyGenerator state */
-	state = (DependencyGenerator) palloc0(sizeof(DependencyGeneratorData));
-	state->dependencies = (AttrNumber *) palloc(k * sizeof(AttrNumber));
+	state = palloc0_object(DependencyGeneratorData);
+	state->dependencies = palloc_array(AttrNumber, k);
 
 	state->ndependencies = 0;
 	state->current = 0;
@@ -237,7 +237,7 @@ dependency_degree(StatsBuildData *data, int k, AttrNumber *dependency)
 	 * Translate the array of indexes to regular attnums for the dependency
 	 * (we will need this to identify the columns in StatsBuildData).
 	 */
-	attnums_dep = (AttrNumber *) palloc(k * sizeof(AttrNumber));
+	attnums_dep = palloc_array(AttrNumber, k);
 	for (i = 0; i < k; i++)
 		attnums_dep[i] = data->attnums[dependency[i]];
 
@@ -402,8 +402,7 @@ statext_dependencies_build(StatsBuildData *data)
 			/* initialize the list of dependencies */
 			if (dependencies == NULL)
 			{
-				dependencies
-					= (MVDependencies *) palloc0(sizeof(MVDependencies));
+				dependencies = palloc0_object(MVDependencies);
 
 				dependencies->magic = STATS_DEPS_MAGIC;
 				dependencies->type = STATS_DEPS_TYPE_BASIC;
@@ -505,7 +504,7 @@ statext_dependencies_deserialize(bytea *data)
 			 VARSIZE_ANY_EXHDR(data), SizeOfHeader);
 
 	/* read the MVDependencies header */
-	dependencies = (MVDependencies *) palloc0(sizeof(MVDependencies));
+	dependencies = palloc0_object(MVDependencies);
 
 	/* initialize pointer to the data part (skip the varlena header) */
 	tmp = VARDATA_ANY(data);
@@ -959,7 +958,7 @@ clauselist_apply_dependencies(PlannerInfo *root, List *clauses,
 	 * and mark all the corresponding clauses as estimated.
 	 */
 	nattrs = bms_num_members(attnums);
-	attr_sel = (Selectivity *) palloc(sizeof(Selectivity) * nattrs);
+	attr_sel = palloc_array(Selectivity, nattrs);
 
 	attidx = 0;
 	i = -1;
@@ -1306,8 +1305,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
 	if (!has_stats_of_kind(rel->statlist, STATS_EXT_DEPENDENCIES))
 		return 1.0;
 
-	list_attnums = (AttrNumber *) palloc(sizeof(AttrNumber) *
-										 list_length(clauses));
+	list_attnums = palloc_array(AttrNumber, list_length(clauses));
 
 	/*
 	 * We allocate space as if every clause was a unique expression, although
@@ -1315,7 +1313,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
 	 * we'll translate to attnums, and there might be duplicates. But it's
 	 * easier and cheaper to just do one allocation than repalloc later.
 	 */
-	unique_exprs = (Node **) palloc(sizeof(Node *) * list_length(clauses));
+	unique_exprs = palloc_array(Node *, list_length(clauses));
 	unique_exprs_cnt = 0;
 
 	/*
@@ -1468,8 +1466,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
 	 * make it just the right size, but it's likely wasteful anyway thanks to
 	 * moving the freed chunks to freelists etc.
 	 */
-	func_dependencies = (MVDependencies **) palloc(sizeof(MVDependencies *) *
-												   list_length(rel->statlist));
+	func_dependencies = palloc_array(MVDependencies *, list_length(rel->statlist));
 	nfunc_dependencies = 0;
 	total_ndeps = 0;
 
@@ -1692,8 +1689,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
 	 * Work out which dependencies we can apply, starting with the
 	 * widest/strongest ones, and proceeding to smaller/weaker ones.
 	 */
-	dependencies = (MVDependency **) palloc(sizeof(MVDependency *) *
-											total_ndeps);
+	dependencies = palloc_array(MVDependency *, total_ndeps);
 	ndependencies = 0;
 
 	while (true)
diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c
index f003d7b4a73..19778b773d2 100644
--- a/src/backend/statistics/extended_stats.c
+++ b/src/backend/statistics/extended_stats.c
@@ -446,7 +446,7 @@ fetch_statentries_for_relation(Relation pg_statext, Oid relid)
 		Form_pg_statistic_ext staForm;
 		List	   *exprs = NIL;
 
-		entry = palloc0(sizeof(StatExtEntry));
+		entry = palloc0_object(StatExtEntry);
 		staForm = (Form_pg_statistic_ext) GETSTRUCT(htup);
 		entry->statOid = staForm->oid;
 		entry->schema = get_namespace_name(staForm->stxnamespace);
@@ -532,7 +532,7 @@ examine_attribute(Node *expr)
 	/*
 	 * Create the VacAttrStats struct.
 	 */
-	stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
+	stats = palloc0_object(VacAttrStats);
 	stats->attstattarget = -1;
 
 	/*
@@ -613,7 +613,7 @@ examine_expression(Node *expr, int stattarget)
 	/*
 	 * Create the VacAttrStats struct.
 	 */
-	stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
+	stats = palloc0_object(VacAttrStats);
 
 	/*
 	 * We can't have statistics target specified for the expression, so we
@@ -946,7 +946,7 @@ build_attnums_array(Bitmapset *attrs, int nexprs, int *numattrs)
 		*numattrs = num;
 
 	/* build attnums from the bitmapset */
-	attnums = (AttrNumber *) palloc(sizeof(AttrNumber) * num);
+	attnums = palloc_array(AttrNumber, num);
 	i = 0;
 	j = -1;
 	while ((j = bms_next_member(attrs, j)) >= 0)
@@ -1028,7 +1028,7 @@ build_sorted_items(StatsBuildData *data, int *nitems,
 	}
 
 	/* build a local cache of typlen for all attributes */
-	typlen = (int *) palloc(sizeof(int) * data->nattnums);
+	typlen = palloc_array(int, data->nattnums);
 	for (i = 0; i < data->nattnums; i++)
 		typlen[i] = get_typlen(data->stats[i]->attrtypid);
 
@@ -1707,11 +1707,10 @@ statext_mcv_clauselist_selectivity(PlannerInfo *root, List *clauses, int varReli
 	if (!has_stats_of_kind(rel->statlist, STATS_EXT_MCV))
 		return sel;
 
-	list_attnums = (Bitmapset **) palloc(sizeof(Bitmapset *) *
-										 list_length(clauses));
+	list_attnums = palloc_array(Bitmapset *, list_length(clauses));
 
 	/* expressions extracted from complex expressions */
-	list_exprs = (List **) palloc(sizeof(Node *) * list_length(clauses));
+	list_exprs = palloc_array(List *, list_length(clauses));
 
 	/*
 	 * Pre-process the clauses list to extract the attnums and expressions
diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c
index 28f925f397e..70eeb8412ce 100644
--- a/src/backend/statistics/mcv.c
+++ b/src/backend/statistics/mcv.c
@@ -270,7 +270,7 @@ statext_mcv_build(StatsBuildData *data, double totalrows, int stattarget)
 										+ sizeof(SortSupportData));
 
 		/* compute frequencies for values in each column */
-		nfreqs = (int *) palloc0(sizeof(int) * numattrs);
+		nfreqs = (int *) palloc0_array(int, numattrs);
 		freqs = build_column_frequencies(groups, ngroups, mss, nfreqs);
 
 		/*
@@ -294,8 +294,8 @@ statext_mcv_build(StatsBuildData *data, double totalrows, int stattarget)
 			/* just point to the proper place in the list */
 			MCVItem    *item = &mcvlist->items[i];
 
-			item->values = (Datum *) palloc(sizeof(Datum) * numattrs);
-			item->isnull = (bool *) palloc(sizeof(bool) * numattrs);
+			item->values = palloc_array(Datum, numattrs);
+			item->isnull = palloc_array(bool, numattrs);
 
 			/* copy values for the group */
 			memcpy(item->values, groups[i].values, sizeof(Datum) * numattrs);
@@ -635,8 +635,8 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
 	char	   *endptr PG_USED_FOR_ASSERTS_ONLY;
 
 	/* values per dimension (and number of non-NULL values) */
-	Datum	  **values = (Datum **) palloc0(sizeof(Datum *) * ndims);
-	int		   *counts = (int *) palloc0(sizeof(int) * ndims);
+	Datum	  **values = (Datum **) palloc0_array(Datum *, ndims);
+	int		   *counts = (int *) palloc0_array(int, ndims);
 
 	/*
 	 * We'll include some rudimentary information about the attribute types
@@ -646,10 +646,10 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
 	 * the statistics gets dropped automatically.  We need to store the info
 	 * about the arrays of deduplicated values anyway.
 	 */
-	info = (DimensionInfo *) palloc0(sizeof(DimensionInfo) * ndims);
+	info = (DimensionInfo *) palloc0_array(DimensionInfo, ndims);
 
 	/* sort support data for all attributes included in the MCV list */
-	ssup = (SortSupport) palloc0(sizeof(SortSupportData) * ndims);
+	ssup = (SortSupport) palloc0_array(SortSupportData, ndims);
 
 	/* collect and deduplicate values for each dimension (attribute) */
 	for (dim = 0; dim < ndims; dim++)
@@ -668,7 +668,7 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
 		info[dim].typbyval = stats[dim]->attrtype->typbyval;
 
 		/* allocate space for values in the attribute and collect them */
-		values[dim] = (Datum *) palloc0(sizeof(Datum) * mcvlist->nitems);
+		values[dim] = (Datum *) palloc0_array(Datum, mcvlist->nitems);
 
 		for (i = 0; i < mcvlist->nitems; i++)
 		{
@@ -1134,11 +1134,11 @@ statext_mcv_deserialize(bytea *data)
 	 * original values (it might go away).
 	 */
 	datalen = 0;				/* space for by-ref data */
-	map = (Datum **) palloc(ndims * sizeof(Datum *));
+	map = palloc_array(Datum *, ndims);
 
 	for (dim = 0; dim < ndims; dim++)
 	{
-		map[dim] = (Datum *) palloc(sizeof(Datum) * info[dim].nvalues);
+		map[dim] = palloc_array(Datum, info[dim].nvalues);
 
 		/* space needed for a copy of data for by-ref types */
 		datalen += info[dim].nbytes_aligned;
@@ -1609,7 +1609,7 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
 	Assert(mcvlist->nitems > 0);
 	Assert(mcvlist->nitems <= STATS_MCVLIST_MAX_ITEMS);
 
-	matches = palloc(sizeof(bool) * mcvlist->nitems);
+	matches = palloc_array(bool, mcvlist->nitems);
 	memset(matches, !is_or, sizeof(bool) * mcvlist->nitems);
 
 	/*
@@ -2134,7 +2134,7 @@ mcv_clause_selectivity_or(PlannerInfo *root, StatisticExtInfo *stat,
 
 	/* build the OR-matches bitmap, if not built already */
 	if (*or_matches == NULL)
-		*or_matches = palloc0(sizeof(bool) * mcv->nitems);
+		*or_matches = palloc0_array(bool, mcv->nitems);
 
 	/* build the match bitmap for the new clause */
 	new_matches = mcv_get_match_bitmap(root, list_make1(clause), stat->keys,
diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c
index 366d70d38a1..4e520065ae0 100644
--- a/src/backend/storage/file/buffile.c
+++ b/src/backend/storage/file/buffile.c
@@ -117,7 +117,7 @@ static File MakeNewFileSetSegment(BufFile *buffile, int segment);
 static BufFile *
 makeBufFileCommon(int nfiles)
 {
-	BufFile    *file = (BufFile *) palloc(sizeof(BufFile));
+	BufFile    *file = palloc_object(BufFile);
 
 	file->numFiles = nfiles;
 	file->isInterXact = false;
@@ -140,7 +140,7 @@ makeBufFile(File firstfile)
 {
 	BufFile    *file = makeBufFileCommon(1);
 
-	file->files = (File *) palloc(sizeof(File));
+	file->files = palloc_object(File);
 	file->files[0] = firstfile;
 	file->readOnly = false;
 	file->fileset = NULL;
@@ -271,7 +271,7 @@ BufFileCreateFileSet(FileSet *fileset, const char *name)
 	file = makeBufFileCommon(1);
 	file->fileset = fileset;
 	file->name = pstrdup(name);
-	file->files = (File *) palloc(sizeof(File));
+	file->files = palloc_object(File);
 	file->files[0] = MakeNewFileSetSegment(file, 0);
 	file->readOnly = false;
 
@@ -297,7 +297,7 @@ BufFileOpenFileSet(FileSet *fileset, const char *name, int mode,
 	File	   *files;
 	int			nfiles = 0;
 
-	files = palloc(sizeof(File) * capacity);
+	files = palloc_array(File, capacity);
 
 	/*
 	 * We don't know how many segments there are, so we'll probe the
@@ -309,7 +309,7 @@ BufFileOpenFileSet(FileSet *fileset, const char *name, int mode,
 		if (nfiles + 1 > capacity)
 		{
 			capacity *= 2;
-			files = repalloc(files, sizeof(File) * capacity);
+			files = repalloc_array(files, File, capacity);
 		}
 		/* Try to load a segment. */
 		FileSetSegmentName(segment_name, name, nfiles);
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 200f72c6e25..f3a1603204e 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -1162,7 +1162,7 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
 	 * Allocate a temporary array to avoid modifying the array passed as
 	 * argument.
 	 */
-	xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
+	xids = palloc_array(TransactionId, running->xcnt + running->subxcnt);
 
 	/*
 	 * Add to the temp array any xids which have not already completed.
@@ -3012,8 +3012,7 @@ GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
 	Assert(type != 0);
 
 	/* allocate what's certainly enough result space */
-	vxids = (VirtualTransactionId *)
-		palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
+	vxids = palloc_array(VirtualTransactionId, arrayP->maxProcs);
 
 	LWLockAcquire(ProcArrayLock, LW_SHARED);
 
@@ -3293,8 +3292,7 @@ GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0,
 	int			index;
 
 	/* allocate what's certainly enough result space */
-	vxids = (VirtualTransactionId *)
-		palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
+	vxids = palloc_array(VirtualTransactionId, arrayP->maxProcs);
 
 	LWLockAcquire(ProcArrayLock, LW_SHARED);
 
diff --git a/src/backend/storage/ipc/shm_mq.c b/src/backend/storage/ipc/shm_mq.c
index 2c79a649f46..9c888d3eb78 100644
--- a/src/backend/storage/ipc/shm_mq.c
+++ b/src/backend/storage/ipc/shm_mq.c
@@ -289,7 +289,7 @@ shm_mq_get_sender(shm_mq *mq)
 shm_mq_handle *
 shm_mq_attach(shm_mq *mq, dsm_segment *seg, BackgroundWorkerHandle *handle)
 {
-	shm_mq_handle *mqh = palloc(sizeof(shm_mq_handle));
+	shm_mq_handle *mqh = palloc_object(shm_mq_handle);
 
 	Assert(mq->mq_receiver == MyProc || mq->mq_sender == MyProc);
 	mqh->mqh_queue = mq;
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index ee3408df301..7b63c7dc90a 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -599,7 +599,7 @@ pg_get_shmem_allocations_numa(PG_FUNCTION_ARGS)
 	InitMaterializedSRF(fcinfo, 0);
 
 	max_nodes = pg_numa_get_max_node();
-	nodes = palloc(sizeof(Size) * (max_nodes + 1));
+	nodes = palloc_array(Size, max_nodes + 1);
 
 	/*
 	 * Shared memory allocations can vary in size and may not align with OS
@@ -624,8 +624,8 @@ pg_get_shmem_allocations_numa(PG_FUNCTION_ARGS)
 	 * them using only fraction of the total pages.
 	 */
 	shm_total_page_count = (ShmemSegHdr->totalsize / os_page_size) + 1;
-	page_ptrs = palloc0(sizeof(void *) * shm_total_page_count);
-	pages_status = palloc(sizeof(int) * shm_total_page_count);
+	page_ptrs = palloc0_array(void *, shm_total_page_count);
+	pages_status = palloc_array(int, shm_total_page_count);
 
 	if (firstNumaTouch)
 		elog(DEBUG1, "NUMA: page-faulting shared memory segments for proper NUMA readouts");
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 9cb78ead105..9015ba3caf7 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -3100,9 +3100,7 @@ GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
 								   (MaxBackends + max_prepared_xacts + 1));
 	}
 	else
-		vxids = (VirtualTransactionId *)
-			palloc0(sizeof(VirtualTransactionId) *
-					(MaxBackends + max_prepared_xacts + 1));
+		vxids = palloc0_array(VirtualTransactionId, (MaxBackends + max_prepared_xacts + 1));
 
 	/* Compute hash code and partition lock, and look up conflicting modes. */
 	hashcode = LockTagHashCode(locktag);
@@ -3801,12 +3799,12 @@ GetLockStatusData(void)
 	int			el;
 	int			i;
 
-	data = (LockData *) palloc(sizeof(LockData));
+	data = palloc_object(LockData);
 
 	/* Guess how much space we'll need. */
 	els = MaxBackends;
 	el = 0;
-	data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * els);
+	data->locks = palloc_array(LockInstanceData, els);
 
 	/*
 	 * First, we iterate through the per-backend fast-path arrays, locking
@@ -4001,7 +3999,7 @@ GetBlockerStatusData(int blocked_pid)
 	PGPROC	   *proc;
 	int			i;
 
-	data = (BlockedProcsData *) palloc(sizeof(BlockedProcsData));
+	data = palloc_object(BlockedProcsData);
 
 	/*
 	 * Guess how much space we'll need, and preallocate.  Most of the time
@@ -4011,9 +4009,9 @@ GetBlockerStatusData(int blocked_pid)
 	 */
 	data->nprocs = data->nlocks = data->npids = 0;
 	data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
-	data->procs = (BlockedProcData *) palloc(sizeof(BlockedProcData) * data->maxprocs);
-	data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * data->maxlocks);
-	data->waiter_pids = (int *) palloc(sizeof(int) * data->maxpids);
+	data->procs = palloc_array(BlockedProcData, data->maxprocs);
+	data->locks = palloc_array(LockInstanceData, data->maxlocks);
+	data->waiter_pids = palloc_array(int, data->maxpids);
 
 	/*
 	 * In order to search the ProcArray for blocked_pid and assume that that
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index f12f8f77aad..149c69a1873 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -1451,7 +1451,7 @@ GetPredicateLockStatusData(void)
 	HASH_SEQ_STATUS seqstat;
 	PREDICATELOCK *predlock;
 
-	data = (PredicateLockData *) palloc(sizeof(PredicateLockData));
+	data = palloc_object(PredicateLockData);
 
 	/*
 	 * To ensure consistency, take simultaneous locks on all partition locks
@@ -1464,10 +1464,8 @@ GetPredicateLockStatusData(void)
 	/* Get number of locks and allocate appropriately-sized arrays. */
 	els = hash_get_num_entries(PredicateLockHash);
 	data->nelements = els;
-	data->locktags = (PREDICATELOCKTARGETTAG *)
-		palloc(sizeof(PREDICATELOCKTARGETTAG) * els);
-	data->xacts = (SERIALIZABLEXACT *)
-		palloc(sizeof(SERIALIZABLEXACT) * els);
+	data->locktags = palloc_array(PREDICATELOCKTARGETTAG, els);
+	data->xacts = palloc_array(SERIALIZABLEXACT, els);
 
 
 	/* Scan through PredicateLockHash and copy contents */
diff --git a/src/backend/storage/smgr/bulk_write.c b/src/backend/storage/smgr/bulk_write.c
index b958be15716..d43c30da48e 100644
--- a/src/backend/storage/smgr/bulk_write.c
+++ b/src/backend/storage/smgr/bulk_write.c
@@ -101,7 +101,7 @@ smgr_bulk_start_smgr(SMgrRelation smgr, ForkNumber forknum, bool use_wal)
 {
 	BulkWriteState *state;
 
-	state = palloc(sizeof(BulkWriteState));
+	state = palloc_object(BulkWriteState);
 	state->smgr = smgr;
 	state->forknum = forknum;
 	state->use_wal = use_wal;
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index e3f335a8340..71bcdeb6601 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -1599,7 +1599,7 @@ DropRelationFiles(RelFileLocator *delrels, int ndelrels, bool isRedo)
 	SMgrRelation *srels;
 	int			i;
 
-	srels = palloc(sizeof(SMgrRelation) * ndelrels);
+	srels = palloc_array(SMgrRelation, ndelrels);
 	for (i = 0; i < ndelrels; i++)
 	{
 		SMgrRelation srel = smgropen(delrels[i], INVALID_PROC_NUMBER);
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index bce37a36d51..f9066ab8c49 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -561,7 +561,7 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
 	 * create an array which contains all relations to be dropped, and close
 	 * each relation's forks at the smgr level while at it
 	 */
-	rlocators = palloc(sizeof(RelFileLocatorBackend) * nrels);
+	rlocators = palloc_array(RelFileLocatorBackend, nrels);
 	for (i = 0; i < nrels; i++)
 	{
 		RelFileLocatorBackend rlocator = rels[i]->smgr_rlocator;
diff --git a/src/backend/storage/sync/sync.c b/src/backend/storage/sync/sync.c
index fc16db90133..9d4c5eae5f6 100644
--- a/src/backend/storage/sync/sync.c
+++ b/src/backend/storage/sync/sync.c
@@ -531,7 +531,7 @@ RememberSyncRequest(const FileTag *ftag, SyncRequestType type)
 		MemoryContext oldcxt = MemoryContextSwitchTo(pendingOpsCxt);
 		PendingUnlinkEntry *entry;
 
-		entry = palloc(sizeof(PendingUnlinkEntry));
+		entry = palloc_object(PendingUnlinkEntry);
 		entry->tag = *ftag;
 		entry->cycle_ctr = checkpoint_cycle_ctr;
 		entry->canceled = false;
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index fde78c55160..6dd64726f06 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -74,7 +74,7 @@ CreateQueryDesc(PlannedStmt *plannedstmt,
 				QueryEnvironment *queryEnv,
 				int instrument_options)
 {
-	QueryDesc  *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
+	QueryDesc  *qd = palloc_object(QueryDesc);
 
 	qd->operation = plannedstmt->commandType;	/* operation */
 	qd->plannedstmt = plannedstmt;	/* plan */
diff --git a/src/backend/tsearch/dict.c b/src/backend/tsearch/dict.c
index eb968858683..d0725108b80 100644
--- a/src/backend/tsearch/dict.c
+++ b/src/backend/tsearch/dict.c
@@ -61,7 +61,7 @@ ts_lexize(PG_FUNCTION_ARGS)
 	ptr = res;
 	while (ptr->lexeme)
 		ptr++;
-	da = (Datum *) palloc(sizeof(Datum) * (ptr - res));
+	da = (Datum *) palloc_array(Datum, ptr - res); 
 	ptr = res;
 	while (ptr->lexeme)
 	{
diff --git a/src/backend/tsearch/dict_ispell.c b/src/backend/tsearch/dict_ispell.c
index debfbf956cc..14e5da486e0 100644
--- a/src/backend/tsearch/dict_ispell.c
+++ b/src/backend/tsearch/dict_ispell.c
@@ -37,7 +37,7 @@ dispell_init(PG_FUNCTION_ARGS)
 				stoploaded = false;
 	ListCell   *l;
 
-	d = (DictISpell *) palloc0(sizeof(DictISpell));
+	d = palloc0_object(DictISpell);
 
 	NIStartBuild(&(d->obj));
 
diff --git a/src/backend/tsearch/dict_simple.c b/src/backend/tsearch/dict_simple.c
index 2c972fc0538..f6639ac7c97 100644
--- a/src/backend/tsearch/dict_simple.c
+++ b/src/backend/tsearch/dict_simple.c
@@ -31,7 +31,7 @@ Datum
 dsimple_init(PG_FUNCTION_ARGS)
 {
 	List	   *dictoptions = (List *) PG_GETARG_POINTER(0);
-	DictSimple *d = (DictSimple *) palloc0(sizeof(DictSimple));
+	DictSimple *d = palloc0_object(DictSimple);
 	bool		stoploaded = false,
 				acceptloaded = false;
 	ListCell   *l;
@@ -87,13 +87,13 @@ dsimple_lexize(PG_FUNCTION_ARGS)
 	{
 		/* reject as stopword */
 		pfree(txt);
-		res = palloc0(sizeof(TSLexeme) * 2);
+		res = palloc0_array(TSLexeme, 2);
 		PG_RETURN_POINTER(res);
 	}
 	else if (d->accept)
 	{
 		/* accept */
-		res = palloc0(sizeof(TSLexeme) * 2);
+		res = palloc0_array(TSLexeme, 2);
 		res[0].lexeme = txt;
 		PG_RETURN_POINTER(res);
 	}
diff --git a/src/backend/tsearch/dict_synonym.c b/src/backend/tsearch/dict_synonym.c
index c2773eb01ad..e076660b5ec 100644
--- a/src/backend/tsearch/dict_synonym.c
+++ b/src/backend/tsearch/dict_synonym.c
@@ -134,7 +134,7 @@ dsynonym_init(PG_FUNCTION_ARGS)
 				 errmsg("could not open synonym file \"%s\": %m",
 						filename)));
 
-	d = (DictSyn *) palloc0(sizeof(DictSyn));
+	d = palloc0_object(DictSyn);
 
 	while ((line = tsearch_readline(&trst)) != NULL)
 	{
@@ -169,12 +169,12 @@ dsynonym_init(PG_FUNCTION_ARGS)
 			if (d->len == 0)
 			{
 				d->len = 64;
-				d->syn = (Syn *) palloc(sizeof(Syn) * d->len);
+				d->syn = palloc_array(Syn, d->len);
 			}
 			else
 			{
 				d->len *= 2;
-				d->syn = (Syn *) repalloc(d->syn, sizeof(Syn) * d->len);
+				d->syn = repalloc_array(d->syn, Syn, d->len);
 			}
 		}
 
@@ -236,7 +236,7 @@ dsynonym_lexize(PG_FUNCTION_ARGS)
 	if (!found)
 		PG_RETURN_POINTER(NULL);
 
-	res = palloc0(sizeof(TSLexeme) * 2);
+	res = palloc0_array(TSLexeme, 2);
 	res[0].lexeme = pnstrdup(found->out, found->outlen);
 	res[0].flags = found->flags;
 
diff --git a/src/backend/tsearch/dict_thesaurus.c b/src/backend/tsearch/dict_thesaurus.c
index 1e6bbde1ca7..6a3d3369858 100644
--- a/src/backend/tsearch/dict_thesaurus.c
+++ b/src/backend/tsearch/dict_thesaurus.c
@@ -78,12 +78,12 @@ newLexeme(DictThesaurus *d, char *b, char *e, uint32 idsubst, uint16 posinsubst)
 		if (d->ntwrds == 0)
 		{
 			d->ntwrds = 16;
-			d->wrds = (TheLexeme *) palloc(sizeof(TheLexeme) * d->ntwrds);
+			d->wrds = palloc_array(TheLexeme, d->ntwrds);
 		}
 		else
 		{
 			d->ntwrds *= 2;
-			d->wrds = (TheLexeme *) repalloc(d->wrds, sizeof(TheLexeme) * d->ntwrds);
+			d->wrds = repalloc_array(d->wrds, TheLexeme, d->ntwrds);
 		}
 	}
 
@@ -95,7 +95,7 @@ newLexeme(DictThesaurus *d, char *b, char *e, uint32 idsubst, uint16 posinsubst)
 	memcpy(ptr->lexeme, b, e - b);
 	ptr->lexeme[e - b] = '\0';
 
-	ptr->entries = (LexemeInfo *) palloc(sizeof(LexemeInfo));
+	ptr->entries = palloc_object(LexemeInfo);
 
 	ptr->entries->nextentry = NULL;
 	ptr->entries->idsubst = idsubst;
@@ -118,12 +118,12 @@ addWrd(DictThesaurus *d, char *b, char *e, uint32 idsubst, uint16 nwrd, uint16 p
 			if (d->nsubst == 0)
 			{
 				d->nsubst = 16;
-				d->subst = (TheSubstitute *) palloc(sizeof(TheSubstitute) * d->nsubst);
+				d->subst = palloc_array(TheSubstitute, d->nsubst);
 			}
 			else
 			{
 				d->nsubst *= 2;
-				d->subst = (TheSubstitute *) repalloc(d->subst, sizeof(TheSubstitute) * d->nsubst);
+				d->subst = repalloc_array(d->subst, TheSubstitute, d->nsubst);
 			}
 		}
 	}
@@ -137,12 +137,12 @@ addWrd(DictThesaurus *d, char *b, char *e, uint32 idsubst, uint16 nwrd, uint16 p
 		if (ntres == 0)
 		{
 			ntres = 2;
-			ptr->res = (TSLexeme *) palloc(sizeof(TSLexeme) * ntres);
+			ptr->res = palloc_array(TSLexeme, ntres);
 		}
 		else
 		{
 			ntres *= 2;
-			ptr->res = (TSLexeme *) repalloc(ptr->res, sizeof(TSLexeme) * ntres);
+			ptr->res = repalloc_array(ptr->res, TSLexeme, ntres);
 		}
 	}
 
@@ -309,7 +309,7 @@ addCompiledLexeme(TheLexeme *newwrds, int *nnw, int *tnm, TSLexeme *lexeme, Lexe
 		newwrds = (TheLexeme *) repalloc(newwrds, sizeof(TheLexeme) * *tnm);
 	}
 
-	newwrds[*nnw].entries = (LexemeInfo *) palloc(sizeof(LexemeInfo));
+	newwrds[*nnw].entries = palloc_object(LexemeInfo);
 
 	if (lexeme && lexeme->lexeme)
 	{
@@ -394,7 +394,7 @@ compileTheLexeme(DictThesaurus *d)
 	int			i,
 				nnw = 0,
 				tnm = 16;
-	TheLexeme  *newwrds = (TheLexeme *) palloc(sizeof(TheLexeme) * tnm),
+	TheLexeme  *newwrds = palloc_array(TheLexeme, tnm),
 			   *ptrwrds;
 
 	for (i = 0; i < d->nwrds; i++)
@@ -511,7 +511,7 @@ compileTheSubstitute(DictThesaurus *d)
 				   *inptr;
 		int			n = 2;
 
-		outptr = d->subst[i].res = (TSLexeme *) palloc(sizeof(TSLexeme) * n);
+		outptr = d->subst[i].res = palloc_array(TSLexeme, n);
 		outptr->lexeme = NULL;
 		inptr = rem;
 
@@ -603,7 +603,7 @@ thesaurus_init(PG_FUNCTION_ARGS)
 	List	   *namelist;
 	ListCell   *l;
 
-	d = (DictThesaurus *) palloc0(sizeof(DictThesaurus));
+	d = palloc0_object(DictThesaurus);
 
 	foreach(l, dictoptions)
 	{
@@ -756,7 +756,7 @@ copyTSLexeme(TheSubstitute *ts)
 	TSLexeme   *res;
 	uint16		i;
 
-	res = (TSLexeme *) palloc(sizeof(TSLexeme) * (ts->reslen + 1));
+	res = palloc_array(TSLexeme, ts->reslen + 1);
 	for (i = 0; i < ts->reslen; i++)
 	{
 		res[i] = ts->res[i];
@@ -834,7 +834,7 @@ thesaurus_lexize(PG_FUNCTION_ARGS)
 				ptr++;
 			}
 
-			infos = (LexemeInfo **) palloc(sizeof(LexemeInfo *) * nlex);
+			infos = palloc_array(LexemeInfo *, nlex);
 			for (i = 0; i < nlex; i++)
 				if ((infos[i] = findTheLexeme(d, basevar[i].lexeme)) == NULL)
 					break;
diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c
index 146801885d7..79c333e6945 100644
--- a/src/backend/tsearch/spell.c
+++ b/src/backend/tsearch/spell.c
@@ -691,7 +691,7 @@ NIAddAffix(IspellDict *Conf, const char *flag, char flagflags, const char *mask,
 		else
 		{
 			Conf->maffixes = 16;
-			Conf->Affix = (AFFIX *) palloc(Conf->maffixes * sizeof(AFFIX));
+			Conf->Affix = palloc_array(AFFIX, Conf->maffixes);
 		}
 	}
 
@@ -737,7 +737,7 @@ NIAddAffix(IspellDict *Conf, const char *flag, char flagflags, const char *mask,
 		 * allocated in the dictionary's memory context, and will be freed
 		 * automatically when it is destroyed.
 		 */
-		Affix->reg.pregex = palloc(sizeof(regex_t));
+		Affix->reg.pregex = palloc_object(regex_t);
 		err = pg_regcomp(Affix->reg.pregex, wmask, wmasklen,
 						 REG_ADVANCED | REG_NOSUB,
 						 DEFAULT_COLLATION_OID);
@@ -1327,7 +1327,7 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename)
 				/* Also reserve place for empty flag set */
 				naffix++;
 
-				Conf->AffixData = (const char **) palloc0(naffix * sizeof(char *));
+				Conf->AffixData = (const char **) palloc0_array(char *, naffix);
 				Conf->lenAffixData = Conf->nAffixData = naffix;
 
 				/* Add empty flag set into AffixData */
@@ -1794,7 +1794,7 @@ NISortDictionary(IspellDict *Conf)
 		 * dictionary. Replace textual flag-field of Conf->Spell entries with
 		 * indexes into Conf->AffixData array.
 		 */
-		Conf->AffixData = (const char **) palloc0(naffix * sizeof(const char *));
+		Conf->AffixData = (const char **) palloc0_array(const char *, naffix);
 
 		curaffix = -1;
 		for (i = 0; i < Conf->nspell; i++)
@@ -1991,7 +1991,7 @@ NISortAffixes(IspellDict *Conf)
 	/* Store compound affixes in the Conf->CompoundAffix array */
 	if (Conf->naffixes > 1)
 		qsort(Conf->Affix, Conf->naffixes, sizeof(AFFIX), cmpaffix);
-	Conf->CompoundAffix = ptr = (CMPDAffix *) palloc(sizeof(CMPDAffix) * Conf->naffixes);
+	Conf->CompoundAffix = ptr = palloc_array(CMPDAffix, Conf->naffixes);
 	ptr->affix = NULL;
 
 	for (i = 0; i < Conf->naffixes; i++)
@@ -2147,7 +2147,7 @@ CheckAffix(const char *word, size_t len, AFFIX *Affix, int flagflags, char *neww
 
 		/* Convert data string to wide characters */
 		newword_len = strlen(newword);
-		data = (pg_wchar *) palloc((newword_len + 1) * sizeof(pg_wchar));
+		data = palloc_array(pg_wchar, newword_len + 1);
 		data_len = pg_mb2wchar_with_len(newword, data, newword_len);
 
 		if (pg_regexec(Affix->reg.pregex, data, data_len,
@@ -2197,7 +2197,7 @@ NormalizeSubWord(IspellDict *Conf, const char *word, int flag)
 
 	if (wrdlen > MAXNORMLEN)
 		return NULL;
-	cur = forms = (char **) palloc(MAX_NORM * sizeof(char *));
+	cur = forms = palloc_array(char *, MAX_NORM);
 	*cur = NULL;
 
 
@@ -2340,7 +2340,7 @@ CheckCompoundAffixes(CMPDAffix **ptr, const char *word, int len, bool CheckInPla
 static SplitVar *
 CopyVar(SplitVar *s, int makedup)
 {
-	SplitVar   *v = (SplitVar *) palloc(sizeof(SplitVar));
+	SplitVar   *v = palloc_object(SplitVar);
 
 	v->next = NULL;
 	if (s)
@@ -2348,7 +2348,7 @@ CopyVar(SplitVar *s, int makedup)
 		int			i;
 
 		v->lenstem = s->lenstem;
-		v->stem = (char **) palloc(sizeof(char *) * v->lenstem);
+		v->stem = palloc_array(char *, v->lenstem);
 		v->nstem = s->nstem;
 		for (i = 0; i < s->nstem; i++)
 			v->stem[i] = (makedup) ? pstrdup(s->stem[i]) : s->stem[i];
@@ -2356,7 +2356,7 @@ CopyVar(SplitVar *s, int makedup)
 	else
 	{
 		v->lenstem = 16;
-		v->stem = (char **) palloc(sizeof(char *) * v->lenstem);
+		v->stem = palloc_array(char *, v->lenstem);
 		v->nstem = 0;
 	}
 	return v;
@@ -2529,7 +2529,7 @@ static void
 addNorm(TSLexeme **lres, TSLexeme **lcur, char *word, int flags, uint16 NVariant)
 {
 	if (*lres == NULL)
-		*lcur = *lres = (TSLexeme *) palloc(MAX_NORM * sizeof(TSLexeme));
+		*lcur = *lres = palloc_array(TSLexeme, MAX_NORM);
 
 	if (*lcur - *lres < MAX_NORM - 1)
 	{
diff --git a/src/backend/tsearch/to_tsany.c b/src/backend/tsearch/to_tsany.c
index 4dfcc2cd3bd..b6efe108424 100644
--- a/src/backend/tsearch/to_tsany.c
+++ b/src/backend/tsearch/to_tsany.c
@@ -84,7 +84,7 @@ uniqueWORD(ParsedWord *a, int32 l)
 	{
 		tmppos = LIMITPOS(a->pos.pos);
 		a->alen = 2;
-		a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen);
+		a->pos.apos = palloc_array(uint16, a->alen);
 		a->pos.apos[0] = 1;
 		a->pos.apos[1] = tmppos;
 		return l;
@@ -103,7 +103,7 @@ uniqueWORD(ParsedWord *a, int32 l)
 	 */
 	tmppos = LIMITPOS(a->pos.pos);
 	a->alen = 2;
-	a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen);
+	a->pos.apos = palloc_array(uint16, a->alen);
 	a->pos.apos[0] = 1;
 	a->pos.apos[1] = tmppos;
 
@@ -123,7 +123,7 @@ uniqueWORD(ParsedWord *a, int32 l)
 			res->word = ptr->word;
 			tmppos = LIMITPOS(ptr->pos.pos);
 			res->alen = 2;
-			res->pos.apos = (uint16 *) palloc(sizeof(uint16) * res->alen);
+			res->pos.apos = palloc_array(uint16, res->alen);
 			res->pos.apos[0] = 1;
 			res->pos.apos[1] = tmppos;
 		}
@@ -141,7 +141,7 @@ uniqueWORD(ParsedWord *a, int32 l)
 				if (res->pos.apos[0] + 1 >= res->alen)
 				{
 					res->alen *= 2;
-					res->pos.apos = (uint16 *) repalloc(res->pos.apos, sizeof(uint16) * res->alen);
+					res->pos.apos = repalloc_array(res->pos.apos, uint16, res->alen);
 				}
 				if (res->pos.apos[0] == 0 || res->pos.apos[res->pos.apos[0]] != LIMITPOS(ptr->pos.pos))
 				{
@@ -255,7 +255,7 @@ to_tsvector_byid(PG_FUNCTION_ARGS)
 		prs.lenwords = MaxAllocSize / sizeof(ParsedWord);
 	prs.curwords = 0;
 	prs.pos = 0;
-	prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);
+	prs.words = palloc_array(ParsedWord, prs.lenwords);
 
 	parsetext(cfgId, &prs, VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
 
@@ -453,7 +453,7 @@ add_to_tsvector(void *_state, char *elem_value, int elem_len)
 		 * (parsetext() will realloc it bigger as needed.)
 		 */
 		prs->lenwords = 16;
-		prs->words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs->lenwords);
+		prs->words = palloc_array(ParsedWord, prs->lenwords);
 		prs->curwords = 0;
 		prs->pos = 0;
 	}
@@ -503,7 +503,7 @@ pushval_morph(Datum opaque, TSQueryParserState state, char *strval, int lenval,
 	prs.lenwords = 4;
 	prs.curwords = 0;
 	prs.pos = 0;
-	prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);
+	prs.words = palloc_array(ParsedWord, prs.lenwords);
 
 	parsetext(data->cfg_id, &prs, strval, lenval);
 
diff --git a/src/backend/tsearch/ts_parse.c b/src/backend/tsearch/ts_parse.c
index cba421892bf..6eebff6c467 100644
--- a/src/backend/tsearch/ts_parse.c
+++ b/src/backend/tsearch/ts_parse.c
@@ -99,7 +99,7 @@ LPLRemoveHead(ListParsedLex *list)
 static void
 LexizeAddLemm(LexizeData *ld, int type, char *lemm, int lenlemm)
 {
-	ParsedLex  *newpl = (ParsedLex *) palloc(sizeof(ParsedLex));
+	ParsedLex  *newpl = palloc_object(ParsedLex);
 
 	newpl->type = type;
 	newpl->lemm = lemm;
diff --git a/src/backend/tsearch/ts_selfuncs.c b/src/backend/tsearch/ts_selfuncs.c
index fb367ad74d2..63a6ecd3e2a 100644
--- a/src/backend/tsearch/ts_selfuncs.c
+++ b/src/backend/tsearch/ts_selfuncs.c
@@ -226,7 +226,7 @@ mcelem_tsquery_selec(TSQuery query, const Datum *mcelem, int nmcelem,
 	/*
 	 * Transpose the data into a single array so we can use bsearch().
 	 */
-	lookup = (TextFreq *) palloc(sizeof(TextFreq) * nmcelem);
+	lookup = palloc_array(TextFreq, nmcelem);
 	for (i = 0; i < nmcelem; i++)
 	{
 		/*
diff --git a/src/backend/tsearch/ts_typanalyze.c b/src/backend/tsearch/ts_typanalyze.c
index 93aab00a3ca..9b8b0995ab7 100644
--- a/src/backend/tsearch/ts_typanalyze.c
+++ b/src/backend/tsearch/ts_typanalyze.c
@@ -320,7 +320,7 @@ compute_tsvector_stats(VacAttrStats *stats,
 		cutoff_freq = 9 * lexeme_no / bucket_width;
 
 		i = hash_get_num_entries(lexemes_tab);	/* surely enough space */
-		sort_table = (TrackItem **) palloc(sizeof(TrackItem *) * i);
+		sort_table = palloc_array(TrackItem *, i);
 
 		hash_seq_init(&scan_status, lexemes_tab);
 		track_len = 0;
@@ -412,8 +412,8 @@ compute_tsvector_stats(VacAttrStats *stats,
 			 * create that for a tsvector column, since null elements aren't
 			 * possible.)
 			 */
-			mcelem_values = (Datum *) palloc(num_mcelem * sizeof(Datum));
-			mcelem_freqs = (float4 *) palloc((num_mcelem + 2) * sizeof(float4));
+			mcelem_values = palloc_array(Datum, num_mcelem);
+			mcelem_freqs = palloc_array(float4, num_mcelem + 2);
 
 			/*
 			 * See comments above about use of nonnull_cnt as the divisor for
diff --git a/src/backend/tsearch/ts_utils.c b/src/backend/tsearch/ts_utils.c
index 0b4a5786644..647e4649644 100644
--- a/src/backend/tsearch/ts_utils.c
+++ b/src/backend/tsearch/ts_utils.c
@@ -105,12 +105,12 @@ readstoplist(const char *fname, StopList *s, char *(*wordop) (const char *, size
 				if (reallen == 0)
 				{
 					reallen = 64;
-					stop = (char **) palloc(sizeof(char *) * reallen);
+					stop = palloc_array(char *, reallen);
 				}
 				else
 				{
 					reallen *= 2;
-					stop = (char **) repalloc(stop, sizeof(char *) * reallen);
+					stop = repalloc_array(stop, char *, reallen);
 				}
 			}
 
diff --git a/src/backend/tsearch/wparser.c b/src/backend/tsearch/wparser.c
index 55171aa8da1..9e53f57324f 100644
--- a/src/backend/tsearch/wparser.c
+++ b/src/backend/tsearch/wparser.c
@@ -58,7 +58,7 @@ tt_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
 
 	oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-	st = (TSTokenTypeStorage *) palloc(sizeof(TSTokenTypeStorage));
+	st = palloc_object(TSTokenTypeStorage);
 	st->cur = 0;
 	/* lextype takes one dummy argument */
 	st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
@@ -173,10 +173,10 @@ prs_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
 
 	oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-	st = (PrsStorage *) palloc(sizeof(PrsStorage));
+	st = palloc_object(PrsStorage);
 	st->cur = 0;
 	st->len = 16;
-	st->list = (LexemeEntry *) palloc(sizeof(LexemeEntry) * st->len);
+	st->list = palloc_array(LexemeEntry, st->len);
 
 	prsdata = DatumGetPointer(FunctionCall2(&prs->prsstart,
 											PointerGetDatum(VARDATA_ANY(txt)),
@@ -307,7 +307,7 @@ ts_headline_byid_opt(PG_FUNCTION_ARGS)
 
 	memset(&prs, 0, sizeof(HeadlineParsedText));
 	prs.lenwords = 32;
-	prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
+	prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
 
 	hlparsetext(cfg->cfgId, &prs, query,
 				VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
@@ -373,11 +373,11 @@ ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
 	Jsonb	   *out;
 	JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
 	HeadlineParsedText prs;
-	HeadlineJsonState *state = palloc0(sizeof(HeadlineJsonState));
+	HeadlineJsonState *state = palloc0_object(HeadlineJsonState);
 
 	memset(&prs, 0, sizeof(HeadlineParsedText));
 	prs.lenwords = 32;
-	prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
+	prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
 
 	state->prs = &prs;
 	state->cfg = lookup_ts_config_cache(tsconfig);
@@ -450,11 +450,11 @@ ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
 	JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
 
 	HeadlineParsedText prs;
-	HeadlineJsonState *state = palloc0(sizeof(HeadlineJsonState));
+	HeadlineJsonState *state = palloc0_object(HeadlineJsonState);
 
 	memset(&prs, 0, sizeof(HeadlineParsedText));
 	prs.lenwords = 32;
-	prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
+	prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
 
 	state->prs = &prs;
 	state->cfg = lookup_ts_config_cache(tsconfig);
diff --git a/src/backend/tsearch/wparser_def.c b/src/backend/tsearch/wparser_def.c
index 251a2ae6563..9fbeab47545 100644
--- a/src/backend/tsearch/wparser_def.c
+++ b/src/backend/tsearch/wparser_def.c
@@ -269,7 +269,7 @@ static bool TParserGet(TParser *prs);
 static TParserPosition *
 newTParserPosition(TParserPosition *prev)
 {
-	TParserPosition *res = (TParserPosition *) palloc(sizeof(TParserPosition));
+	TParserPosition *res = palloc_object(TParserPosition);
 
 	if (prev)
 		memcpy(res, prev, sizeof(TParserPosition));
@@ -286,12 +286,12 @@ newTParserPosition(TParserPosition *prev)
 static TParser *
 TParserInit(char *str, int len)
 {
-	TParser    *prs = (TParser *) palloc0(sizeof(TParser));
+	TParser    *prs = palloc0_object(TParser);
 
 	prs->charmaxlen = pg_database_encoding_max_length();
 	prs->str = str;
 	prs->lenstr = len;
-	prs->pgwstr = (pg_wchar *) palloc(sizeof(pg_wchar) * (prs->lenstr + 1));
+	prs->pgwstr = palloc_array(pg_wchar, prs->lenstr + 1);
 	pg_mb2wchar_with_len(prs->str, prs->pgwstr, prs->lenstr);
 
 	prs->state = newTParserPosition(NULL);
@@ -318,7 +318,7 @@ TParserInit(char *str, int len)
 static TParser *
 TParserCopyInit(const TParser *orig)
 {
-	TParser    *prs = (TParser *) palloc0(sizeof(TParser));
+	TParser    *prs = palloc0_object(TParser);
 
 	prs->charmaxlen = orig->charmaxlen;
 	prs->str = orig->str + orig->state->posbyte;
@@ -1832,7 +1832,7 @@ TParserGet(TParser *prs)
 Datum
 prsd_lextype(PG_FUNCTION_ARGS)
 {
-	LexDescr   *descr = (LexDescr *) palloc(sizeof(LexDescr) * (LASTNUM + 1));
+	LexDescr   *descr = palloc_array(LexDescr, LASTNUM + 1);
 	int			i;
 
 	for (i = 1; i <= LASTNUM; i++)
@@ -1949,7 +1949,7 @@ checkcondition_HL(void *opaque, QueryOperand *val, ExecPhraseData *data)
 
 			if (!data->pos)
 			{
-				data->pos = palloc(sizeof(WordEntryPos) * checkval->len);
+				data->pos = palloc_array(WordEntryPos, checkval->len);
 				data->allocated = true;
 				data->npos = 1;
 				data->pos[0] = checkval->words[i].pos;
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index 1de477cbeeb..b90754f8578 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -514,7 +514,7 @@ find_tabstat_entry(Oid rel_id)
 	}
 
 	tabentry = (PgStat_TableStatus *) entry_ref->pending;
-	tablestatus = palloc(sizeof(PgStat_TableStatus));
+	tablestatus = palloc_object(PgStat_TableStatus);
 	*tablestatus = *tabentry;
 
 	/*
diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c
index d9b8f34a355..e81b4f96a24 100644
--- a/src/backend/utils/activity/wait_event.c
+++ b/src/backend/utils/activity/wait_event.c
@@ -317,7 +317,7 @@ GetWaitEventCustomNames(uint32 classId, int *nwaitevents)
 	els = hash_get_num_entries(WaitEventCustomHashByName);
 
 	/* Allocate enough space for all entries */
-	waiteventnames = palloc(els * sizeof(char *));
+	waiteventnames = palloc_array(char *, els);
 
 	/* Now scan the hash table to copy the data */
 	hash_seq_init(&hash_seq, WaitEventCustomHashByName);
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index fbcd64a2609..05d48412f82 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -618,7 +618,7 @@ aclitemin(PG_FUNCTION_ARGS)
 	Node	   *escontext = fcinfo->context;
 	AclItem    *aip;
 
-	aip = (AclItem *) palloc(sizeof(AclItem));
+	aip = palloc_object(AclItem);
 
 	s = aclparse(s, aip, escontext);
 	if (s == NULL)
@@ -1661,7 +1661,7 @@ makeaclitem(PG_FUNCTION_ARGS)
 
 	priv = convert_any_priv_string(privtext, any_priv_map);
 
-	result = (AclItem *) palloc(sizeof(AclItem));
+	result = palloc_object(AclItem);
 
 	result->ai_grantee = grantee;
 	result->ai_grantor = grantor;
@@ -1821,7 +1821,7 @@ aclexplode(PG_FUNCTION_ARGS)
 		funcctx->tuple_desc = BlessTupleDesc(tupdesc);
 
 		/* allocate memory for user context */
-		idx = (int *) palloc(sizeof(int[2]));
+		idx = palloc_array(int, 2);
 		idx[0] = 0;				/* ACL array item index */
 		idx[1] = -1;			/* privilege type counter */
 		funcctx->user_fctx = idx;
diff --git a/src/backend/utils/adt/array_selfuncs.c b/src/backend/utils/adt/array_selfuncs.c
index 4dab35b0057..cd201461c17 100644
--- a/src/backend/utils/adt/array_selfuncs.c
+++ b/src/backend/utils/adt/array_selfuncs.c
@@ -759,7 +759,7 @@ mcelem_array_contained_selec(const Datum *mcelem, int nmcelem,
 	 * elem_selec is array of estimated frequencies for elements in the
 	 * constant.
 	 */
-	elem_selec = (float *) palloc(sizeof(float) * nitems);
+	elem_selec = palloc_array(float, nitems);
 
 	/* Scan mcelem and array in parallel. */
 	mcelem_index = 0;
@@ -936,7 +936,7 @@ calc_hist(const float4 *hist, int nhist, int n)
 				next_interval;
 	float		frac;
 
-	hist_part = (float *) palloc((n + 1) * sizeof(float));
+	hist_part = palloc_array(float, n + 1);
 
 	/*
 	 * frac is a probability contribution for each interval between histogram
@@ -1028,8 +1028,8 @@ calc_distr(const float *p, int n, int m, float rest)
 	 * Since we return only the last row of the matrix and need only the
 	 * current and previous row for calculations, allocate two rows.
 	 */
-	row = (float *) palloc((m + 1) * sizeof(float));
-	prev_row = (float *) palloc((m + 1) * sizeof(float));
+	row = palloc_array(float, m + 1);
+	prev_row = palloc_array(float, m + 1);
 
 	/* M[0,0] = 1 */
 	row[0] = 1.0f;
diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c
index 560b27f3ca7..61aedd31ff1 100644
--- a/src/backend/utils/adt/array_typanalyze.c
+++ b/src/backend/utils/adt/array_typanalyze.c
@@ -132,7 +132,7 @@ array_typanalyze(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(true);
 
 	/* Store our findings for use by compute_array_stats() */
-	extra_data = (ArrayAnalyzeExtraData *) palloc(sizeof(ArrayAnalyzeExtraData));
+	extra_data = palloc_object(ArrayAnalyzeExtraData);
 	extra_data->type_id = typentry->type_id;
 	extra_data->eq_opr = typentry->eq_opr;
 	extra_data->coll_id = stats->attrcollid;	/* collation we should use */
@@ -469,7 +469,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 		cutoff_freq = 9 * element_no / bucket_width;
 
 		i = hash_get_num_entries(elements_tab); /* surely enough space */
-		sort_table = (TrackItem **) palloc(sizeof(TrackItem *) * i);
+		sort_table = palloc_array(TrackItem *, i);
 
 		hash_seq_init(&scan_status, elements_tab);
 		track_len = 0;
@@ -606,8 +606,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 			 * Create an array of DECountItem pointers, and sort them into
 			 * increasing count order.
 			 */
-			sorted_count_items = (DECountItem **)
-				palloc(sizeof(DECountItem *) * count_items_count);
+			sorted_count_items = palloc_array(DECountItem *, count_items_count);
 			hash_seq_init(&scan_status, count_tab);
 			j = 0;
 			while ((count_item = (DECountItem *) hash_seq_search(&scan_status)) != NULL)
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index 8eb342e3382..c01bf466121 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -433,8 +433,8 @@ array_cat(PG_FUNCTION_ARGS)
 		 * themselves) of the input argument arrays
 		 */
 		ndims = ndims1;
-		dims = (int *) palloc(ndims * sizeof(int));
-		lbs = (int *) palloc(ndims * sizeof(int));
+		dims = palloc_array(int, ndims);
+		lbs = palloc_array(int, ndims);
 
 		dims[0] = dims1[0] + dims2[0];
 		lbs[0] = lbs1[0];
@@ -459,8 +459,8 @@ array_cat(PG_FUNCTION_ARGS)
 		 * the first argument inserted at the front of the outer dimension
 		 */
 		ndims = ndims2;
-		dims = (int *) palloc(ndims * sizeof(int));
-		lbs = (int *) palloc(ndims * sizeof(int));
+		dims = palloc_array(int, ndims);
+		lbs = palloc_array(int, ndims);
 		memcpy(dims, dims2, ndims * sizeof(int));
 		memcpy(lbs, lbs2, ndims * sizeof(int));
 
@@ -487,8 +487,8 @@ array_cat(PG_FUNCTION_ARGS)
 		 * second argument appended to the end of the outer dimension
 		 */
 		ndims = ndims1;
-		dims = (int *) palloc(ndims * sizeof(int));
-		lbs = (int *) palloc(ndims * sizeof(int));
+		dims = palloc_array(int, ndims);
+		lbs = palloc_array(int, ndims);
 		memcpy(dims, dims1, ndims * sizeof(int));
 		memcpy(lbs, lbs1, ndims * sizeof(int));
 
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 5a1b8483bea..d01fcf9cc7f 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -3582,7 +3582,7 @@ construct_empty_array(Oid elmtype)
 {
 	ArrayType  *result;
 
-	result = (ArrayType *) palloc0(sizeof(ArrayType));
+	result = (ArrayType *) palloc0_object(ArrayType);
 	SET_VARSIZE(result, sizeof(ArrayType));
 	result->ndim = 0;
 	result->dataoffset = 0;
@@ -3647,7 +3647,7 @@ deconstruct_array(const ArrayType *array,
 	nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
 	*elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
 	if (nullsp)
-		*nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
+		*nullsp = nulls = (bool *) palloc0_array(bool, nelems);
 	else
 		nulls = NULL;
 	*nelemsp = nelems;
@@ -4209,7 +4209,7 @@ hash_array(PG_FUNCTION_ARGS)
 			 * modify typentry, since that points directly into the type
 			 * cache.
 			 */
-			record_typentry = palloc0(sizeof(*record_typentry));
+			record_typentry = palloc0_object(TypeCacheEntry);
 			record_typentry->type_id = element_type;
 
 			/* fill in what we need below */
@@ -4597,7 +4597,7 @@ arraycontained(PG_FUNCTION_ARGS)
 ArrayIterator
 array_create_iterator(ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
 {
-	ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
+	ArrayIterator iterator = palloc0_object(ArrayIteratorData);
 
 	/*
 	 * Sanity-check inputs --- caller should have got this right already
@@ -5944,7 +5944,7 @@ generate_subscripts(PG_FUNCTION_ARGS)
 		 * switch to memory context appropriate for multiple function calls
 		 */
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
-		fctx = (generate_subscripts_fctx *) palloc(sizeof(generate_subscripts_fctx));
+		fctx = palloc_object(generate_subscripts_fctx);
 
 		lb = AARR_LBOUND(v);
 		dimv = AARR_DIMS(v);
@@ -6291,7 +6291,7 @@ array_unnest(PG_FUNCTION_ARGS)
 		arr = PG_GETARG_ANY_ARRAY_P(0);
 
 		/* allocate memory for user context */
-		fctx = (array_unnest_fctx *) palloc(sizeof(array_unnest_fctx));
+		fctx = palloc_object(array_unnest_fctx);
 
 		/* initialize state */
 		array_iter_setup(&fctx->iter, arr);
diff --git a/src/backend/utils/adt/arraysubs.c b/src/backend/utils/adt/arraysubs.c
index 2940fb8e8d7..71ca181fba8 100644
--- a/src/backend/utils/adt/arraysubs.c
+++ b/src/backend/utils/adt/arraysubs.c
@@ -497,7 +497,7 @@ array_exec_setup(const SubscriptingRef *sbsref,
 	/*
 	 * Allocate type-specific workspace.
 	 */
-	workspace = (ArraySubWorkspace *) palloc(sizeof(ArraySubWorkspace));
+	workspace = palloc_object(ArraySubWorkspace);
 	sbsrefstate->workspace = workspace;
 
 	/*
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index c4b8125dd66..421ccc306f6 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -358,7 +358,7 @@ GetSQLCurrentTime(int32 typmod)
 
 	GetCurrentTimeUsec(tm, &fsec, &tz);
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 	tm2timetz(tm, fsec, tz, result);
 	AdjustTimeForTypmod(&(result->time), typmod);
 	return result;
@@ -2087,7 +2087,7 @@ time_interval(PG_FUNCTION_ARGS)
 	TimeADT		time = PG_GETARG_TIMEADT(0);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	result->time = time;
 	result->day = 0;
@@ -2132,7 +2132,7 @@ time_mi_time(PG_FUNCTION_ARGS)
 	TimeADT		time2 = PG_GETARG_TIMEADT(1);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	result->month = 0;
 	result->day = 0;
@@ -2399,7 +2399,7 @@ timetz_in(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 	}
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 	tm2timetz(tm, fsec, tz, result);
 	AdjustTimeForTypmod(&(result->time), typmod);
 
@@ -2438,7 +2438,7 @@ timetz_recv(PG_FUNCTION_ARGS)
 	int32		typmod = PG_GETARG_INT32(2);
 	TimeTzADT  *result;
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = pq_getmsgint64(buf);
 
@@ -2524,7 +2524,7 @@ timetz_scale(PG_FUNCTION_ARGS)
 	int32		typmod = PG_GETARG_INT32(1);
 	TimeTzADT  *result;
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = time->time;
 	result->zone = time->zone;
@@ -2700,7 +2700,7 @@ timetz_pl_interval(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("cannot add infinite interval to time")));
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = time->time + span->time;
 	result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
@@ -2727,7 +2727,7 @@ timetz_mi_interval(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("cannot subtract infinite interval from time")));
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = time->time - span->time;
 	result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
@@ -2934,7 +2934,7 @@ time_timetz(PG_FUNCTION_ARGS)
 	time2tm(time, tm, &fsec);
 	tz = DetermineTimeZoneOffset(tm, session_timezone);
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = time;
 	result->zone = tz;
@@ -2964,7 +2964,7 @@ timestamptz_timetz(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("timestamp out of range")));
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	tm2timetz(tm, fsec, tz, result);
 
@@ -3197,7 +3197,7 @@ timetz_zone(PG_FUNCTION_ARGS)
 					 errmsg("timestamp out of range")));
 	}
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
 	/* C99 modulo has the wrong sign convention for negative input */
@@ -3238,7 +3238,7 @@ timetz_izone(PG_FUNCTION_ARGS)
 
 	tz = -(zone->time / USECS_PER_SEC);
 
-	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = palloc_object(TimeTzADT);
 
 	result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
 	/* C99 modulo has the wrong sign convention for negative input */
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 680fee2a844..e3a099eaa67 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -5152,7 +5152,7 @@ pg_timezone_abbrevs_zone(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		pindex = (int *) palloc(sizeof(int));
+		pindex = palloc_object(int);
 		*pindex = 0;
 		funcctx->user_fctx = pindex;
 
@@ -5187,7 +5187,7 @@ pg_timezone_abbrevs_zone(PG_FUNCTION_ARGS)
 		/* Convert offset (in seconds) to an interval; can't overflow */
 		MemSet(&itm_in, 0, sizeof(struct pg_itm_in));
 		itm_in.tm_usec = (int64) gmtoff * USECS_PER_SEC;
-		resInterval = (Interval *) palloc(sizeof(Interval));
+		resInterval = palloc_object(Interval);
 		(void) itmin2interval(&itm_in, resInterval);
 		values[1] = IntervalPGetDatum(resInterval);
 
@@ -5239,7 +5239,7 @@ pg_timezone_abbrevs_abbrevs(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		pindex = (int *) palloc(sizeof(int));
+		pindex = palloc_object(int);
 		*pindex = 0;
 		funcctx->user_fctx = pindex;
 
@@ -5310,7 +5310,7 @@ pg_timezone_abbrevs_abbrevs(PG_FUNCTION_ARGS)
 	/* Convert offset (in seconds) to an interval; can't overflow */
 	MemSet(&itm_in, 0, sizeof(struct pg_itm_in));
 	itm_in.tm_usec = (int64) gmtoffset * USECS_PER_SEC;
-	resInterval = (Interval *) palloc(sizeof(Interval));
+	resInterval = palloc_object(Interval);
 	(void) itmin2interval(&itm_in, resInterval);
 	values[1] = IntervalPGetDatum(resInterval);
 
@@ -5378,7 +5378,7 @@ pg_timezone_names(PG_FUNCTION_ARGS)
 		/* Convert tzoff to an interval; can't overflow */
 		MemSet(&itm_in, 0, sizeof(struct pg_itm_in));
 		itm_in.tm_usec = (int64) -tzoff * USECS_PER_SEC;
-		resInterval = (Interval *) palloc(sizeof(Interval));
+		resInterval = palloc_object(Interval);
 		(void) itmin2interval(&itm_in, resInterval);
 		values[2] = IntervalPGetDatum(resInterval);
 
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 5bfeda2ffde..a9fa209e345 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -4263,7 +4263,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 	{
 		if (flags & DCH_ZONED)
 		{
-			TimeTzADT  *result = palloc(sizeof(TimeTzADT));
+			TimeTzADT  *result = palloc_object(TimeTzADT);
 
 			if (ftz.has_tz)
 			{
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 9101a720744..43b7eb43a79 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -423,7 +423,7 @@ box_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	Node	   *escontext = fcinfo->context;
-	BOX		   *box = (BOX *) palloc(sizeof(BOX));
+	BOX		   *box = palloc_object(BOX);
 	bool		isopen;
 	float8		x,
 				y;
@@ -470,7 +470,7 @@ box_recv(PG_FUNCTION_ARGS)
 	float8		x,
 				y;
 
-	box = (BOX *) palloc(sizeof(BOX));
+	box = palloc_object(BOX);
 
 	box->high.x = pq_getmsgfloat8(buf);
 	box->high.y = pq_getmsgfloat8(buf);
@@ -849,7 +849,7 @@ Datum
 box_center(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
-	Point	   *result = (Point *) palloc(sizeof(Point));
+	Point	   *result = palloc_object(Point);
 
 	box_cn(result, box);
 
@@ -914,7 +914,7 @@ box_intersect(PG_FUNCTION_ARGS)
 	if (!box_ov(box1, box2))
 		PG_RETURN_NULL();
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	result->high.x = float8_min(box1->high.x, box2->high.x);
 	result->low.x = float8_max(box1->low.x, box2->low.x);
@@ -933,7 +933,7 @@ Datum
 box_diagonal(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
-	LSEG	   *result = (LSEG *) palloc(sizeof(LSEG));
+	LSEG	   *result = palloc_object(LSEG);
 
 	statlseg_construct(result, &box->high, &box->low);
 
@@ -980,7 +980,7 @@ line_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	Node	   *escontext = fcinfo->context;
-	LINE	   *line = (LINE *) palloc(sizeof(LINE));
+	LINE	   *line = palloc_object(LINE);
 	LSEG		lseg;
 	bool		isopen;
 	char	   *s;
@@ -1040,7 +1040,7 @@ line_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	LINE	   *line;
 
-	line = (LINE *) palloc(sizeof(LINE));
+	line = palloc_object(LINE);
 
 	line->A = pq_getmsgfloat8(buf);
 	line->B = pq_getmsgfloat8(buf);
@@ -1116,7 +1116,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
-	LINE	   *result = (LINE *) palloc(sizeof(LINE));
+	LINE	   *result = palloc_object(LINE);
 
 	if (point_eq_point(pt1, pt2))
 		ereport(ERROR,
@@ -1289,7 +1289,7 @@ line_interpt(PG_FUNCTION_ARGS)
 	LINE	   *l2 = PG_GETARG_LINE_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (!line_interpt_line(result, l1, l2))
 		PG_RETURN_NULL();
@@ -1831,7 +1831,7 @@ Datum
 point_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
-	Point	   *point = (Point *) palloc(sizeof(Point));
+	Point	   *point = palloc_object(Point);
 
 	/* Ignore failure from pair_decode, since our return value won't matter */
 	pair_decode(str, &point->x, &point->y, NULL, "point", str, fcinfo->context);
@@ -1855,7 +1855,7 @@ point_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	Point	   *point;
 
-	point = (Point *) palloc(sizeof(Point));
+	point = palloc_object(Point);
 	point->x = pq_getmsgfloat8(buf);
 	point->y = pq_getmsgfloat8(buf);
 	PG_RETURN_POINT_P(point);
@@ -2066,7 +2066,7 @@ lseg_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	Node	   *escontext = fcinfo->context;
-	LSEG	   *lseg = (LSEG *) palloc(sizeof(LSEG));
+	LSEG	   *lseg = palloc_object(LSEG);
 	bool		isopen;
 
 	if (!path_decode(str, true, 2, &lseg->p[0], &isopen, NULL, "lseg", str,
@@ -2094,7 +2094,7 @@ lseg_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	LSEG	   *lseg;
 
-	lseg = (LSEG *) palloc(sizeof(LSEG));
+	lseg = palloc_object(LSEG);
 
 	lseg->p[0].x = pq_getmsgfloat8(buf);
 	lseg->p[0].y = pq_getmsgfloat8(buf);
@@ -2130,7 +2130,7 @@ lseg_construct(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
-	LSEG	   *result = (LSEG *) palloc(sizeof(LSEG));
+	LSEG	   *result = palloc_object(LSEG);
 
 	statlseg_construct(result, pt1, pt2);
 
@@ -2318,7 +2318,7 @@ lseg_center(PG_FUNCTION_ARGS)
 	LSEG	   *lseg = PG_GETARG_LSEG_P(0);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	result->x = float8_div(float8_pl(lseg->p[0].x, lseg->p[1].x), 2.0);
 	result->y = float8_div(float8_pl(lseg->p[0].y, lseg->p[1].y), 2.0);
@@ -2364,7 +2364,7 @@ lseg_interpt(PG_FUNCTION_ARGS)
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (!lseg_interpt_lseg(result, l1, l2))
 		PG_RETURN_NULL();
@@ -2753,7 +2753,7 @@ close_pl(PG_FUNCTION_ARGS)
 	LINE	   *line = PG_GETARG_LINE_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(line_closept_point(result, line, pt)))
 		PG_RETURN_NULL();
@@ -2794,7 +2794,7 @@ close_ps(PG_FUNCTION_ARGS)
 	LSEG	   *lseg = PG_GETARG_LSEG_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(lseg_closept_point(result, lseg, pt)))
 		PG_RETURN_NULL();
@@ -2859,7 +2859,7 @@ close_lseg(PG_FUNCTION_ARGS)
 	if (lseg_sl(l1) == lseg_sl(l2))
 		PG_RETURN_NULL();
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(lseg_closept_lseg(result, l2, l1)))
 		PG_RETURN_NULL();
@@ -2936,7 +2936,7 @@ close_pb(PG_FUNCTION_ARGS)
 	BOX		   *box = PG_GETARG_BOX_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(box_closept_point(result, box, pt)))
 		PG_RETURN_NULL();
@@ -2994,7 +2994,7 @@ close_ls(PG_FUNCTION_ARGS)
 	if (lseg_sl(lseg) == line_sl(line))
 		PG_RETURN_NULL();
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(lseg_closept_line(result, lseg, line)))
 		PG_RETURN_NULL();
@@ -3066,7 +3066,7 @@ close_sb(PG_FUNCTION_ARGS)
 	BOX		   *box = PG_GETARG_BOX_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	if (isnan(box_closept_lseg(result, box, lseg)))
 		PG_RETURN_NULL();
@@ -4099,7 +4099,7 @@ construct_point(PG_FUNCTION_ARGS)
 	float8		y = PG_GETARG_FLOAT8(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	point_construct(result, x, y);
 
@@ -4122,7 +4122,7 @@ point_add(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	point_add_point(result, p1, p2);
 
@@ -4145,7 +4145,7 @@ point_sub(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	point_sub_point(result, p1, p2);
 
@@ -4170,7 +4170,7 @@ point_mul(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	point_mul_point(result, p1, p2);
 
@@ -4199,7 +4199,7 @@ point_div(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	point_div_point(result, p1, p2);
 
@@ -4220,7 +4220,7 @@ points_box(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 	BOX		   *result;
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	box_construct(result, p1, p2);
 
@@ -4234,7 +4234,7 @@ box_add(PG_FUNCTION_ARGS)
 	Point	   *p = PG_GETARG_POINT_P(1);
 	BOX		   *result;
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	point_add_point(&result->high, &box->high, p);
 	point_add_point(&result->low, &box->low, p);
@@ -4249,7 +4249,7 @@ box_sub(PG_FUNCTION_ARGS)
 	Point	   *p = PG_GETARG_POINT_P(1);
 	BOX		   *result;
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	point_sub_point(&result->high, &box->high, p);
 	point_sub_point(&result->low, &box->low, p);
@@ -4266,7 +4266,7 @@ box_mul(PG_FUNCTION_ARGS)
 	Point		high,
 				low;
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	point_mul_point(&high, &box->high, p);
 	point_mul_point(&low, &box->low, p);
@@ -4285,7 +4285,7 @@ box_div(PG_FUNCTION_ARGS)
 	Point		high,
 				low;
 
-	result = (BOX *) palloc(sizeof(BOX));
+	result = palloc_object(BOX);
 
 	point_div_point(&high, &box->high, p);
 	point_div_point(&low, &box->low, p);
@@ -4304,7 +4304,7 @@ point_box(PG_FUNCTION_ARGS)
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	BOX		   *box;
 
-	box = (BOX *) palloc(sizeof(BOX));
+	box = palloc_object(BOX);
 
 	box->high.x = pt->x;
 	box->low.x = pt->x;
@@ -4324,7 +4324,7 @@ boxes_bound_box(PG_FUNCTION_ARGS)
 			   *box2 = PG_GETARG_BOX_P(1),
 			   *container;
 
-	container = (BOX *) palloc(sizeof(BOX));
+	container = palloc_object(BOX);
 
 	container->high.x = float8_max(box1->high.x, box2->high.x);
 	container->low.x = float8_min(box1->low.x, box2->low.x);
@@ -4506,7 +4506,7 @@ poly_center(PG_FUNCTION_ARGS)
 	Point	   *result;
 	CIRCLE		circle;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 
 	poly_to_circle(&circle, poly);
 	*result = circle.center;
@@ -4521,7 +4521,7 @@ poly_box(PG_FUNCTION_ARGS)
 	POLYGON    *poly = PG_GETARG_POLYGON_P(0);
 	BOX		   *box;
 
-	box = (BOX *) palloc(sizeof(BOX));
+	box = palloc_object(BOX);
 	*box = poly->boundbox;
 
 	PG_RETURN_BOX_P(box);
@@ -4612,7 +4612,7 @@ circle_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	Node	   *escontext = fcinfo->context;
-	CIRCLE	   *circle = (CIRCLE *) palloc(sizeof(CIRCLE));
+	CIRCLE	   *circle = palloc_object(CIRCLE);
 	char	   *s,
 			   *cp;
 	int			depth = 0;
@@ -4705,7 +4705,7 @@ circle_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	CIRCLE	   *circle;
 
-	circle = (CIRCLE *) palloc(sizeof(CIRCLE));
+	circle = palloc_object(CIRCLE);
 
 	circle->center.x = pq_getmsgfloat8(buf);
 	circle->center.y = pq_getmsgfloat8(buf);
@@ -4968,7 +4968,7 @@ circle_add_pt(PG_FUNCTION_ARGS)
 	Point	   *point = PG_GETARG_POINT_P(1);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	point_add_point(&result->center, &circle->center, point);
 	result->radius = circle->radius;
@@ -4983,7 +4983,7 @@ circle_sub_pt(PG_FUNCTION_ARGS)
 	Point	   *point = PG_GETARG_POINT_P(1);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	point_sub_point(&result->center, &circle->center, point);
 	result->radius = circle->radius;
@@ -5002,7 +5002,7 @@ circle_mul_pt(PG_FUNCTION_ARGS)
 	Point	   *point = PG_GETARG_POINT_P(1);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	point_mul_point(&result->center, &circle->center, point);
 	result->radius = float8_mul(circle->radius, hypot(point->x, point->y));
@@ -5017,7 +5017,7 @@ circle_div_pt(PG_FUNCTION_ARGS)
 	Point	   *point = PG_GETARG_POINT_P(1);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	point_div_point(&result->center, &circle->center, point);
 	result->radius = float8_div(circle->radius, hypot(point->x, point->y));
@@ -5145,7 +5145,7 @@ circle_center(PG_FUNCTION_ARGS)
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	result = palloc_object(Point);
 	result->x = circle->center.x;
 	result->y = circle->center.y;
 
@@ -5173,7 +5173,7 @@ cr_circle(PG_FUNCTION_ARGS)
 	float8		radius = PG_GETARG_FLOAT8(1);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	result->center.x = center->x;
 	result->center.y = center->y;
@@ -5189,7 +5189,7 @@ circle_box(PG_FUNCTION_ARGS)
 	BOX		   *box;
 	float8		delta;
 
-	box = (BOX *) palloc(sizeof(BOX));
+	box = palloc_object(BOX);
 
 	delta = float8_div(circle->radius, sqrt(2.0));
 
@@ -5210,7 +5210,7 @@ box_circle(PG_FUNCTION_ARGS)
 	BOX		   *box = PG_GETARG_BOX_P(0);
 	CIRCLE	   *circle;
 
-	circle = (CIRCLE *) palloc(sizeof(CIRCLE));
+	circle = palloc_object(CIRCLE);
 
 	circle->center.x = float8_div(float8_pl(box->high.x, box->low.x), 2.0);
 	circle->center.y = float8_div(float8_pl(box->high.y, box->low.y), 2.0);
@@ -5309,7 +5309,7 @@ poly_circle(PG_FUNCTION_ARGS)
 	POLYGON    *poly = PG_GETARG_POLYGON_P(0);
 	CIRCLE	   *result;
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
+	result = palloc_object(CIRCLE);
 
 	poly_to_circle(result, poly);
 
diff --git a/src/backend/utils/adt/geo_spgist.c b/src/backend/utils/adt/geo_spgist.c
index 4308a3065cd..94d351d4786 100644
--- a/src/backend/utils/adt/geo_spgist.c
+++ b/src/backend/utils/adt/geo_spgist.c
@@ -156,7 +156,7 @@ getQuadrant(BOX *centroid, BOX *inBox)
 static RangeBox *
 getRangeBox(BOX *box)
 {
-	RangeBox   *range_box = (RangeBox *) palloc(sizeof(RangeBox));
+	RangeBox   *range_box = palloc_object(RangeBox);
 
 	range_box->left.low = box->low.x;
 	range_box->left.high = box->high.x;
@@ -176,7 +176,7 @@ getRangeBox(BOX *box)
 static RectBox *
 initRectBox(void)
 {
-	RectBox    *rect_box = (RectBox *) palloc(sizeof(RectBox));
+	RectBox    *rect_box = palloc_object(RectBox);
 	float8		infinity = get_float8_infinity();
 
 	rect_box->range_box_x.left.low = -infinity;
@@ -204,7 +204,7 @@ initRectBox(void)
 static RectBox *
 nextRectBox(RectBox *rect_box, RangeBox *centroid, uint8 quadrant)
 {
-	RectBox    *next_rect_box = (RectBox *) palloc(sizeof(RectBox));
+	RectBox    *next_rect_box = palloc_object(RectBox);
 
 	memcpy(next_rect_box, rect_box, sizeof(RectBox));
 
@@ -445,10 +445,10 @@ spg_box_quad_picksplit(PG_FUNCTION_ARGS)
 	BOX		   *centroid;
 	int			median,
 				i;
-	float8	   *lowXs = palloc(sizeof(float8) * in->nTuples);
-	float8	   *highXs = palloc(sizeof(float8) * in->nTuples);
-	float8	   *lowYs = palloc(sizeof(float8) * in->nTuples);
-	float8	   *highYs = palloc(sizeof(float8) * in->nTuples);
+	float8	   *lowXs = palloc_array(float8, in->nTuples);
+	float8	   *highXs = palloc_array(float8, in->nTuples);
+	float8	   *lowYs = palloc_array(float8, in->nTuples);
+	float8	   *highYs = palloc_array(float8, in->nTuples);
 
 	/* Calculate median of all 4D coordinates */
 	for (i = 0; i < in->nTuples; i++)
@@ -468,7 +468,7 @@ spg_box_quad_picksplit(PG_FUNCTION_ARGS)
 
 	median = in->nTuples / 2;
 
-	centroid = palloc(sizeof(BOX));
+	centroid = palloc_object(BOX);
 
 	centroid->low.x = lowXs[median];
 	centroid->high.x = highXs[median];
@@ -482,8 +482,8 @@ spg_box_quad_picksplit(PG_FUNCTION_ARGS)
 	out->nNodes = 16;
 	out->nodeLabels = NULL;		/* We don't need node labels. */
 
-	out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	/*
 	 * Assign ranges to corresponding nodes according to quadrants relative to
@@ -574,13 +574,13 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
 	{
 		/* Report that all nodes should be visited */
 		out->nNodes = in->nNodes;
-		out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
+		out->nodeNumbers = palloc_array(int, in->nNodes);
 		for (i = 0; i < in->nNodes; i++)
 			out->nodeNumbers[i] = i;
 
 		if (in->norderbys > 0 && in->nNodes > 0)
 		{
-			double	   *distances = palloc(sizeof(double) * in->norderbys);
+			double	   *distances = palloc_array(double, in->norderbys);
 			int			j;
 
 			for (j = 0; j < in->norderbys; j++)
@@ -590,12 +590,12 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
 				distances[j] = pointToRectBoxDistance(pt, rect_box);
 			}
 
-			out->distances = (double **) palloc(sizeof(double *) * in->nNodes);
+			out->distances = palloc_array(double *, in->nNodes);
 			out->distances[0] = distances;
 
 			for (i = 1; i < in->nNodes; i++)
 			{
-				out->distances[i] = palloc(sizeof(double) * in->norderbys);
+				out->distances[i] = palloc_array(double, in->norderbys);
 				memcpy(out->distances[i], distances,
 					   sizeof(double) * in->norderbys);
 			}
@@ -609,7 +609,7 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
 	 * following operations.
 	 */
 	centroid = getRangeBox(DatumGetBoxP(in->prefixDatum));
-	queries = (RangeBox **) palloc(in->nkeys * sizeof(RangeBox *));
+	queries = palloc_array(RangeBox *, in->nkeys);
 	for (i = 0; i < in->nkeys; i++)
 	{
 		BOX		   *box = spg_box_quad_get_scankey_bbox(&in->scankeys[i], NULL);
@@ -619,10 +619,10 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
 
 	/* Allocate enough memory for nodes */
 	out->nNodes = 0;
-	out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
-	out->traversalValues = (void **) palloc(sizeof(void *) * in->nNodes);
+	out->nodeNumbers = palloc_array(int, in->nNodes);
+	out->traversalValues = palloc_array(void *, in->nNodes);
 	if (in->norderbys > 0)
-		out->distances = (double **) palloc(sizeof(double *) * in->nNodes);
+		out->distances = palloc_array(double *, in->nNodes);
 
 	/*
 	 * We switch memory context, because we want to allocate memory for new
@@ -703,7 +703,7 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
 
 			if (in->norderbys > 0)
 			{
-				double	   *distances = palloc(sizeof(double) * in->norderbys);
+				double	   *distances = palloc_array(double, in->norderbys);
 				int			j;
 
 				out->distances[out->nNodes] = distances;
@@ -878,7 +878,7 @@ spg_poly_quad_compress(PG_FUNCTION_ARGS)
 	POLYGON    *polygon = PG_GETARG_POLYGON_P(0);
 	BOX		   *box;
 
-	box = (BOX *) palloc(sizeof(BOX));
+	box = palloc_object(BOX);
 	*box = polygon->boundbox;
 
 	PG_RETURN_BOX_P(box);
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index b5781989a64..60411ee024d 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -1537,7 +1537,7 @@ generate_series_step_int4(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
+		fctx = palloc_object(generate_series_fctx);
 
 		/*
 		 * Use fctx to keep state from call to call. Seed current with the
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 9cd420b4b9d..678f971508b 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -1411,7 +1411,7 @@ generate_series_step_int8(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
+		fctx = palloc_object(generate_series_fctx);
 
 		/*
 		 * Use fctx to keep state from call to call. Seed current with the
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 06dd62f0008..73cacf33e61 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -807,7 +807,7 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
 		 * use the right context to enlarge the object if necessary.
 		 */
 		oldcontext = MemoryContextSwitchTo(aggcontext);
-		state = (JsonAggState *) palloc(sizeof(JsonAggState));
+		state = palloc_object(JsonAggState);
 		state->str = makeStringInfo();
 		MemoryContextSwitchTo(oldcontext);
 
@@ -1029,7 +1029,7 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
 		 * sure they use the right context to enlarge the object if necessary.
 		 */
 		oldcontext = MemoryContextSwitchTo(aggcontext);
-		state = (JsonAggState *) palloc(sizeof(JsonAggState));
+		state = palloc_object(JsonAggState);
 		state->str = makeStringInfo();
 		if (unique_keys)
 			json_unique_builder_init(&state->unique_check);
@@ -1762,7 +1762,7 @@ json_unique_object_start(void *_state)
 		return JSON_SUCCESS;
 
 	/* push object entry to stack */
-	entry = palloc(sizeof(*entry));
+	entry = palloc_object(JsonUniqueStackEntry);
 	entry->object_id = state->id_counter++;
 	entry->parent = state->stack;
 	state->stack = entry;
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index 9399cdb491a..1cc650e717b 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -1478,7 +1478,7 @@ clone_parse_state(JsonbParseState *state)
 	if (state == NULL)
 		return NULL;
 
-	result = palloc(sizeof(JsonbParseState));
+	result = palloc_object(JsonbParseState);
 	icursor = state;
 	ocursor = result;
 	for (;;)
@@ -1490,7 +1490,7 @@ clone_parse_state(JsonbParseState *state)
 		icursor = icursor->next;
 		if (icursor == NULL)
 			break;
-		ocursor->next = palloc(sizeof(JsonbParseState));
+		ocursor->next = palloc_object(JsonbParseState);
 		ocursor = ocursor->next;
 	}
 	ocursor->next = NULL;
@@ -1531,8 +1531,8 @@ jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
 					 errmsg("could not determine input data type")));
 
 		oldcontext = MemoryContextSwitchTo(aggcontext);
-		state = palloc(sizeof(JsonbAggState));
-		result = palloc0(sizeof(JsonbInState));
+		state = palloc_object(JsonbAggState);
+		result = palloc0_object(JsonbInState);
 		state->res = result;
 		result->res = pushJsonbValue(&result->parseState,
 									 WJB_BEGIN_ARRAY, NULL);
@@ -1701,8 +1701,8 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
 		Oid			arg_type;
 
 		oldcontext = MemoryContextSwitchTo(aggcontext);
-		state = palloc(sizeof(JsonbAggState));
-		result = palloc0(sizeof(JsonbInState));
+		state = palloc_object(JsonbAggState);
+		result = palloc0_object(JsonbInState);
 		state->res = result;
 		result->res = pushJsonbValue(&result->parseState,
 									 WJB_BEGIN_OBJECT, NULL);
diff --git a/src/backend/utils/adt/jsonb_gin.c b/src/backend/utils/adt/jsonb_gin.c
index 9b56248cf0b..2190092b14f 100644
--- a/src/backend/utils/adt/jsonb_gin.c
+++ b/src/backend/utils/adt/jsonb_gin.c
@@ -163,7 +163,7 @@ static void
 init_gin_entries(GinEntries *entries, int preallocated)
 {
 	entries->allocated = preallocated;
-	entries->buf = preallocated ? palloc(sizeof(Datum) * preallocated) : NULL;
+	entries->buf = preallocated ? palloc_array(Datum, preallocated) : NULL;
 	entries->count = 0;
 }
 
@@ -178,13 +178,14 @@ add_gin_entry(GinEntries *entries, Datum entry)
 		if (entries->allocated)
 		{
 			entries->allocated *= 2;
-			entries->buf = repalloc(entries->buf,
-									sizeof(Datum) * entries->allocated);
+			entries->buf = repalloc_array(entries->buf,
+										 Datum,
+										 entries->allocated);
 		}
 		else
 		{
 			entries->allocated = 8;
-			entries->buf = palloc(sizeof(Datum) * entries->allocated);
+			entries->buf = palloc_array(Datum, entries->allocated);
 		}
 	}
 
@@ -307,7 +308,7 @@ jsonb_ops__add_path_item(JsonPathGinPath *path, JsonPathItem *jsp)
 			return false;
 	}
 
-	pentry = palloc(sizeof(*pentry));
+	pentry = palloc_object(JsonPathGinPathItem);
 
 	pentry->type = jsp->type;
 	pentry->keyName = keyName;
@@ -785,7 +786,7 @@ extract_jsp_query(JsonPath *jp, StrategyNumber strat, bool pathOps,
 	if (!*nentries)
 		return NULL;
 
-	*extra_data = palloc0(sizeof(**extra_data) * entries.count);
+	*extra_data = palloc0_array(Pointer, entries.count);
 	**extra_data = (Pointer) node;
 
 	return entries.buf;
@@ -869,7 +870,7 @@ gin_extract_jsonb_query(PG_FUNCTION_ARGS)
 		text	   *query = PG_GETARG_TEXT_PP(0);
 
 		*nentries = 1;
-		entries = (Datum *) palloc(sizeof(Datum));
+		entries = palloc_object(Datum);
 		entries[0] = make_text_key(JGINFLAG_KEY,
 								   VARDATA_ANY(query),
 								   VARSIZE_ANY_EXHDR(query));
@@ -887,7 +888,7 @@ gin_extract_jsonb_query(PG_FUNCTION_ARGS)
 
 		deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
 
-		entries = (Datum *) palloc(sizeof(Datum) * key_count);
+		entries = palloc_array(Datum, key_count);
 
 		for (i = 0, j = 0; i < key_count; i++)
 		{
@@ -1126,7 +1127,7 @@ gin_extract_jsonb_path(PG_FUNCTION_ARGS)
 			case WJB_BEGIN_OBJECT:
 				/* Push a stack level for this object */
 				parent = stack;
-				stack = (PathHashStack *) palloc(sizeof(PathHashStack));
+				stack = palloc_object(PathHashStack);
 
 				/*
 				 * We pass forward hashes from outer nesting levels so that
diff --git a/src/backend/utils/adt/jsonb_util.c b/src/backend/utils/adt/jsonb_util.c
index 82b807d067a..714b07a5555 100644
--- a/src/backend/utils/adt/jsonb_util.c
+++ b/src/backend/utils/adt/jsonb_util.c
@@ -356,7 +356,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
 
 	if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
 	{
-		JsonbValue *result = palloc(sizeof(JsonbValue));
+		JsonbValue *result = palloc_object(JsonbValue);
 		char	   *base_addr = (char *) (children + count);
 		uint32		offset = 0;
 		int			i;
@@ -439,7 +439,7 @@ getKeyJsonValueFromContainer(JsonbContainer *container,
 			int			index = stopMiddle + count;
 
 			if (!res)
-				res = palloc(sizeof(JsonbValue));
+				res = palloc_object(JsonbValue);
 
 			fillJsonbValue(container, index, baseAddr,
 						   getJsonbOffset(container, index),
@@ -481,7 +481,7 @@ getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
 	if (i >= nelements)
 		return NULL;
 
-	result = palloc(sizeof(JsonbValue));
+	result = palloc_object(JsonbValue);
 
 	fillJsonbValue(container, i, base_addr,
 				   getJsonbOffset(container, i),
@@ -663,8 +663,8 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
 			{
 				(*pstate)->size = 4;
 			}
-			(*pstate)->contVal.val.array.elems = palloc(sizeof(JsonbValue) *
-														(*pstate)->size);
+			(*pstate)->contVal.val.array.elems = palloc_array(JsonbValue,
+															(*pstate)->size);
 			break;
 		case WJB_BEGIN_OBJECT:
 			Assert(!scalarVal);
@@ -673,8 +673,8 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
 			(*pstate)->contVal.type = jbvObject;
 			(*pstate)->contVal.val.object.nPairs = 0;
 			(*pstate)->size = 4;
-			(*pstate)->contVal.val.object.pairs = palloc(sizeof(JsonbPair) *
-														 (*pstate)->size);
+			(*pstate)->contVal.val.object.pairs = palloc_array(JsonbPair,
+																 (*pstate)->size);
 			break;
 		case WJB_KEY:
 			Assert(scalarVal->type == jbvString);
@@ -731,7 +731,7 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
 static JsonbParseState *
 pushState(JsonbParseState **pstate)
 {
-	JsonbParseState *ns = palloc(sizeof(JsonbParseState));
+	JsonbParseState *ns = palloc_object(JsonbParseState);
 
 	ns->next = *pstate;
 	ns->unique_keys = false;
@@ -1010,7 +1010,7 @@ iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent)
 {
 	JsonbIterator *it;
 
-	it = palloc0(sizeof(JsonbIterator));
+	it = palloc0_object(JsonbIterator);
 	it->container = container;
 	it->parent = parent;
 	it->nElems = JsonContainerSize(container);
@@ -1256,7 +1256,7 @@ JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
 					uint32		j = 0;
 
 					/* Make room for all possible values */
-					lhsConts = palloc(sizeof(JsonbValue) * nLhsElems);
+					lhsConts = palloc_array(JsonbValue, nLhsElems);
 
 					for (i = 0; i < nLhsElems; i++)
 					{
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index de32e329975..ff2d8001fc7 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -593,12 +593,12 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
 		funcctx = SRF_FIRSTCALL_INIT();
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-		state = palloc(sizeof(OkeysState));
+		state = palloc_object(OkeysState);
 
 		state->result_size = JB_ROOT_COUNT(jb);
 		state->result_count = 0;
 		state->sent_count = 0;
-		state->result = palloc(state->result_size * sizeof(char *));
+		state->result = palloc_array(char *, state->result_size);
 
 		it = JsonbIteratorInit(&jb->root);
 
@@ -744,14 +744,14 @@ json_object_keys(PG_FUNCTION_ARGS)
 		funcctx = SRF_FIRSTCALL_INIT();
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-		state = palloc(sizeof(OkeysState));
-		sem = palloc0(sizeof(JsonSemAction));
+		state = palloc_object(OkeysState);
+		sem = palloc0_object(JsonSemAction);
 
 		state->lex = makeJsonLexContext(&lex, json, true);
 		state->result_size = 256;
 		state->result_count = 0;
 		state->sent_count = 0;
-		state->result = palloc(256 * sizeof(char *));
+		state->result = palloc_array(char *, 256);
 
 		sem->semstate = state;
 		sem->array_start = okeys_array_start;
@@ -1045,8 +1045,8 @@ get_path_all(FunctionCallInfo fcinfo, bool as_text)
 
 	deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
 
-	tpath = palloc(npath * sizeof(char *));
-	ipath = palloc(npath * sizeof(int));
+	tpath = palloc_array(char *, npath);
+	ipath = palloc_array(int, npath);
 
 	for (i = 0; i < npath; i++)
 	{
@@ -1106,8 +1106,8 @@ get_worker(text *json,
 		   int npath,
 		   bool normalize_results)
 {
-	JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
-	GetState   *state = palloc0(sizeof(GetState));
+	JsonSemAction *sem = palloc0_object(JsonSemAction);
+	GetState   *state = palloc0_object(GetState);
 
 	Assert(npath >= 0);
 
@@ -1118,8 +1118,8 @@ get_worker(text *json,
 	state->npath = npath;
 	state->path_names = tpath;
 	state->path_indexes = ipath;
-	state->pathok = palloc0(sizeof(bool) * npath);
-	state->array_cur_index = palloc(sizeof(int) * npath);
+	state->pathok = palloc0_array(bool, npath);
+	state->array_cur_index = palloc_array(int, npath);
 
 	if (npath > 0)
 		state->pathok[0] = true;
@@ -1682,7 +1682,7 @@ jsonb_set_element(Jsonb *jb, const Datum *path, int path_len,
 	JsonbValue *res;
 	JsonbParseState *state = NULL;
 	JsonbIterator *it;
-	bool	   *path_nulls = palloc0(path_len * sizeof(bool));
+	bool	   *path_nulls = palloc0_array(bool, path_len);
 
 	if (newval->type == jbvArray && newval->val.array.rawScalar)
 		*newval = newval->val.array.elems[0];
@@ -1727,7 +1727,7 @@ push_path(JsonbParseState **st, int level, const Datum *path_elems,
 	 * it contains only information about path slice from level to the end,
 	 * the access index must be normalized by level.
 	 */
-	enum jbvType *tpath = palloc0((path_len - level) * sizeof(enum jbvType));
+	enum jbvType *tpath = palloc0_array(enum jbvType, path_len - level);
 	JsonbValue	newkey;
 
 	/*
@@ -1856,14 +1856,14 @@ json_array_length(PG_FUNCTION_ARGS)
 	JsonLexContext lex;
 	JsonSemAction *sem;
 
-	state = palloc0(sizeof(AlenState));
+	state = palloc0_object(AlenState);
 	state->lex = makeJsonLexContext(&lex, json, false);
 	/* palloc0 does this for us */
 #if 0
 	state->count = 0;
 #endif
 
-	sem = palloc0(sizeof(JsonSemAction));
+	sem = palloc0_object(JsonSemAction);
 	sem->semstate = state;
 	sem->object_start = alen_object_start;
 	sem->scalar = alen_scalar;
@@ -2063,8 +2063,8 @@ each_worker(FunctionCallInfo fcinfo, bool as_text)
 	ReturnSetInfo *rsi;
 	EachState  *state;
 
-	state = palloc0(sizeof(EachState));
-	sem = palloc0(sizeof(JsonSemAction));
+	state = palloc0_object(EachState);
+	sem = palloc0_object(JsonSemAction);
 
 	rsi = (ReturnSetInfo *) fcinfo->resultinfo;
 
@@ -2316,8 +2316,8 @@ elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 	/* elements only needs escaped strings when as_text */
 	makeJsonLexContext(&lex, json, as_text);
 
-	state = palloc0(sizeof(ElementsState));
-	sem = palloc0(sizeof(JsonSemAction));
+	state = palloc0_object(ElementsState);
+	sem = palloc0_object(JsonSemAction);
 
 	InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC | MAT_SRF_BLESS);
 	rsi = (ReturnSetInfo *) fcinfo->resultinfo;
@@ -2572,8 +2572,8 @@ populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
 	}
 
 	ctx->ndims = ndims;
-	ctx->dims = palloc(sizeof(int) * ndims);
-	ctx->sizes = palloc0(sizeof(int) * ndims);
+	ctx->dims = palloc_array(int, ndims);
+	ctx->sizes = palloc0_array(int, ndims);
 
 	for (i = 0; i < ndims; i++)
 		ctx->dims[i] = -1;		/* dimensions are unknown yet */
@@ -2958,7 +2958,7 @@ populate_array(ArrayIOData *aio,
 
 	Assert(ctx.ndims > 0);
 
-	lbs = palloc(sizeof(int) * ctx.ndims);
+	lbs = palloc_array(int, ctx.ndims);
 
 	for (i = 0; i < ctx.ndims; i++)
 		lbs[i] = 1;
@@ -3824,8 +3824,8 @@ get_json_object_as_hash(const char *json, int len, const char *funcname,
 					  &ctl,
 					  HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
 
-	state = palloc0(sizeof(JHashState));
-	sem = palloc0(sizeof(JsonSemAction));
+	state = palloc0_object(JHashState);
+	sem = palloc0_object(JsonSemAction);
 
 	state->function_name = funcname;
 	state->hash = tab;
@@ -4122,7 +4122,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
 	 */
 	update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
 
-	state = palloc0(sizeof(PopulateRecordsetState));
+	state = palloc0_object(PopulateRecordsetState);
 
 	/* make tuplestore in a sufficiently long-lived memory context */
 	old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
@@ -4141,7 +4141,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
 		JsonLexContext lex;
 		JsonSemAction *sem;
 
-		sem = palloc0(sizeof(JsonSemAction));
+		sem = palloc0_object(JsonSemAction);
 
 		makeJsonLexContext(&lex, json, true);
 
@@ -4511,8 +4511,8 @@ json_strip_nulls(PG_FUNCTION_ARGS)
 	JsonLexContext lex;
 	JsonSemAction *sem;
 
-	state = palloc0(sizeof(StripnullState));
-	sem = palloc0(sizeof(JsonSemAction));
+	state = palloc0_object(StripnullState);
+	sem = palloc0_object(JsonSemAction);
 	initStringInfo(&strbuf);
 
 	state->lex = makeJsonLexContext(&lex, json, true);
@@ -5734,8 +5734,8 @@ iterate_json_values(text *json, uint32 flags, void *action_state,
 					JsonIterateStringValuesAction action)
 {
 	JsonLexContext lex;
-	JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
-	IterateJsonStringValuesState *state = palloc0(sizeof(IterateJsonStringValuesState));
+	JsonSemAction *sem = palloc0_object(JsonSemAction);
+	IterateJsonStringValuesState *state = palloc0_object(IterateJsonStringValuesState);
 
 	state->lex = makeJsonLexContext(&lex, json, true);
 	state->action = action;
@@ -5855,8 +5855,8 @@ transform_json_string_values(text *json, void *action_state,
 							 JsonTransformStringValuesAction transform_action)
 {
 	JsonLexContext lex;
-	JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
-	TransformJsonStringValuesState *state = palloc0(sizeof(TransformJsonStringValuesState));
+	JsonSemAction *sem = palloc0_object(JsonSemAction);
+	TransformJsonStringValuesState *state = palloc0_object(TransformJsonStringValuesState);
 	StringInfoData strbuf;
 
 	initStringInfo(&strbuf);
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 8156695e97e..7aa5194be7a 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -775,7 +775,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 					break;
 				}
 
-				v = hasNext ? &vbuf : palloc(sizeof(*v));
+				v = hasNext ? &vbuf : palloc_object(JsonbValue);
 
 				baseObject = cxt->baseObject;
 				getJsonPathItem(cxt, jsp, v);
@@ -1088,7 +1088,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 
 		case jpiType:
 			{
-				JsonbValue *jbv = palloc(sizeof(*jbv));
+				JsonbValue *jbv = palloc_object(JsonbValue);
 
 				jbv->type = jbvString;
 				jbv->val.string.val = pstrdup(JsonbTypeName(jb));
@@ -1118,7 +1118,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 					size = 1;
 				}
 
-				jb = palloc(sizeof(*jb));
+				jb = palloc_object(JsonbValue);
 
 				jb->type = jbvNumeric;
 				jb->val.numeric = int64_to_numeric(size);
@@ -1249,7 +1249,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 
 				last = cxt->innermostArraySize - 1;
 
-				lastjbv = hasNext ? &tmpjbv : palloc(sizeof(*lastjbv));
+				lastjbv = hasNext ? &tmpjbv : palloc_object(JsonbValue);
 
 				lastjbv->type = jbvNumeric;
 				lastjbv->val.numeric = int64_to_numeric(last);
@@ -2162,7 +2162,7 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
 	if (!jspGetNext(jsp, &elem) && !found)
 		return jperOk;
 
-	lval = palloc(sizeof(*lval));
+	lval = palloc_object(JsonbValue);
 	lval->type = jbvNumeric;
 	lval->val.numeric = res;
 
@@ -2317,7 +2317,7 @@ executeNumericItemMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 	if (!jspGetNext(jsp, &next) && !found)
 		return jperOk;
 
-	jb = palloc(sizeof(*jb));
+	jb = palloc_object(JsonbValue);
 	jb->type = jbvNumeric;
 	jb->val.numeric = DatumGetNumeric(datum);
 
@@ -2783,7 +2783,7 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 	if (!hasNext && !found)
 		return res;
 
-	jb = hasNext ? &jbvbuf : palloc(sizeof(*jb));
+	jb = hasNext ? &jbvbuf : palloc_object(JsonbValue);
 
 	jb->type = jbvDatetime;
 	jb->val.datetime.value = value;
@@ -3018,7 +3018,7 @@ GetJsonPathVar(void *cxt, char *varName, int varNameLen,
 		return NULL;
 	}
 
-	result = palloc(sizeof(JsonbValue));
+	result = palloc_object(JsonbValue);
 	if (var->isnull)
 	{
 		*baseObjectId = 0;
@@ -3445,7 +3445,7 @@ compareNumeric(Numeric a, Numeric b)
 static JsonbValue *
 copyJsonbValue(JsonbValue *src)
 {
-	JsonbValue *dst = palloc(sizeof(*dst));
+	JsonbValue *dst = palloc_object(JsonbValue);
 
 	*dst = *src;
 
@@ -4119,7 +4119,7 @@ JsonTableInitOpaque(TableFuncScanState *state, int natts)
 	JsonExpr   *je = castNode(JsonExpr, tf->docexpr);
 	List	   *args = NIL;
 
-	cxt = palloc0(sizeof(JsonTableExecContext));
+	cxt = palloc0_object(JsonTableExecContext);
 	cxt->magic = JSON_TABLE_EXEC_CONTEXT_MAGIC;
 
 	/*
@@ -4138,7 +4138,7 @@ JsonTableInitOpaque(TableFuncScanState *state, int natts)
 		{
 			ExprState  *state = lfirst_node(ExprState, exprlc);
 			String	   *name = lfirst_node(String, namelc);
-			JsonPathVariable *var = palloc(sizeof(*var));
+			JsonPathVariable *var = palloc_object(JsonPathVariable);
 
 			var->name = pstrdup(name->sval);
 			var->namelen = strlen(var->name);
@@ -4156,8 +4156,7 @@ JsonTableInitOpaque(TableFuncScanState *state, int natts)
 		}
 	}
 
-	cxt->colplanstates = palloc(sizeof(JsonTablePlanState *) *
-								list_length(tf->colvalexprs));
+	cxt->colplanstates = palloc_array(JsonTablePlanState *, list_length(tf->colvalexprs));
 
 	/*
 	 * Initialize plan for the root path and, recursively, also any child
@@ -4195,7 +4194,7 @@ JsonTableInitPlan(JsonTableExecContext *cxt, JsonTablePlan *plan,
 				  JsonTablePlanState *parentstate,
 				  List *args, MemoryContext mcxt)
 {
-	JsonTablePlanState *planstate = palloc0(sizeof(*planstate));
+	JsonTablePlanState *planstate = palloc0_object(JsonTablePlanState);
 
 	planstate->plan = plan;
 	planstate->parent = parentstate;
diff --git a/src/backend/utils/adt/jsonpath_gram.y b/src/backend/utils/adt/jsonpath_gram.y
index 499745a8fef..411a8baf380 100644
--- a/src/backend/utils/adt/jsonpath_gram.y
+++ b/src/backend/utils/adt/jsonpath_gram.y
@@ -120,7 +120,7 @@ static bool makeItemLikeRegex(JsonPathParseItem *expr,
 
 result:
 	mode expr_or_predicate			{
-										*result = palloc(sizeof(JsonPathParseResult));
+										*result = palloc_object(JsonPathParseResult);
 										(*result)->expr = $2;
 										(*result)->lax = $1;
 										(void) yynerrs;
@@ -384,7 +384,7 @@ method:
 static JsonPathParseItem *
 makeItemType(JsonPathItemType type)
 {
-	JsonPathParseItem *v = palloc(sizeof(*v));
+	JsonPathParseItem *v = palloc_object(JsonPathParseItem);
 
 	CHECK_FOR_INTERRUPTS();
 
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index df938812dd3..bf38d68aa03 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -152,7 +152,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
 		 * Collect all the locking information that we will format and send
 		 * out as a result set.
 		 */
-		mystatus = (PG_Lock_Status *) palloc(sizeof(PG_Lock_Status));
+		mystatus = palloc_object(PG_Lock_Status);
 		funcctx->user_fctx = mystatus;
 
 		mystatus->lockData = GetLockStatusData();
diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c
index bb38ef2f5e4..35234e700ff 100644
--- a/src/backend/utils/adt/mac.c
+++ b/src/backend/utils/adt/mac.c
@@ -101,7 +101,7 @@ macaddr_in(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("invalid octet value in \"macaddr\" value: \"%s\"", str)));
 
-	result = (macaddr *) palloc(sizeof(macaddr));
+	result = palloc_object(macaddr);
 
 	result->a = a;
 	result->b = b;
@@ -142,7 +142,7 @@ macaddr_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	macaddr    *addr;
 
-	addr = (macaddr *) palloc(sizeof(macaddr));
+	addr = palloc_object(macaddr);
 
 	addr->a = pq_getmsgbyte(buf);
 	addr->b = pq_getmsgbyte(buf);
@@ -289,7 +289,7 @@ macaddr_not(PG_FUNCTION_ARGS)
 	macaddr    *addr = PG_GETARG_MACADDR_P(0);
 	macaddr    *result;
 
-	result = (macaddr *) palloc(sizeof(macaddr));
+	result = palloc_object(macaddr);
 	result->a = ~addr->a;
 	result->b = ~addr->b;
 	result->c = ~addr->c;
@@ -306,7 +306,7 @@ macaddr_and(PG_FUNCTION_ARGS)
 	macaddr    *addr2 = PG_GETARG_MACADDR_P(1);
 	macaddr    *result;
 
-	result = (macaddr *) palloc(sizeof(macaddr));
+	result = palloc_object(macaddr);
 	result->a = addr1->a & addr2->a;
 	result->b = addr1->b & addr2->b;
 	result->c = addr1->c & addr2->c;
@@ -323,7 +323,7 @@ macaddr_or(PG_FUNCTION_ARGS)
 	macaddr    *addr2 = PG_GETARG_MACADDR_P(1);
 	macaddr    *result;
 
-	result = (macaddr *) palloc(sizeof(macaddr));
+	result = palloc_object(macaddr);
 	result->a = addr1->a | addr2->a;
 	result->b = addr1->b | addr2->b;
 	result->c = addr1->c | addr2->c;
@@ -343,7 +343,7 @@ macaddr_trunc(PG_FUNCTION_ARGS)
 	macaddr    *addr = PG_GETARG_MACADDR_P(0);
 	macaddr    *result;
 
-	result = (macaddr *) palloc(sizeof(macaddr));
+	result = palloc_object(macaddr);
 
 	result->a = addr->a;
 	result->b = addr->b;
@@ -374,7 +374,7 @@ macaddr_sortsupport(PG_FUNCTION_ARGS)
 
 		oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
 
-		uss = palloc(sizeof(macaddr_sortsupport_state));
+		uss = palloc_object(macaddr_sortsupport_state);
 		uss->input_count = 0;
 		uss->estimating = true;
 		initHyperLogLog(&uss->abbr_card, 10);
diff --git a/src/backend/utils/adt/mac8.c b/src/backend/utils/adt/mac8.c
index 08e41ba4eea..ea715a7a0d4 100644
--- a/src/backend/utils/adt/mac8.c
+++ b/src/backend/utils/adt/mac8.c
@@ -207,7 +207,7 @@ macaddr8_in(PG_FUNCTION_ARGS)
 	else if (count != 8)
 		goto fail;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 
 	result->a = a;
 	result->b = b;
@@ -256,7 +256,7 @@ macaddr8_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	macaddr8   *addr;
 
-	addr = (macaddr8 *) palloc0(sizeof(macaddr8));
+	addr = palloc0_object(macaddr8);
 
 	addr->a = pq_getmsgbyte(buf);
 	addr->b = pq_getmsgbyte(buf);
@@ -417,7 +417,7 @@ macaddr8_not(PG_FUNCTION_ARGS)
 	macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 	result->a = ~addr->a;
 	result->b = ~addr->b;
 	result->c = ~addr->c;
@@ -437,7 +437,7 @@ macaddr8_and(PG_FUNCTION_ARGS)
 	macaddr8   *addr2 = PG_GETARG_MACADDR8_P(1);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 	result->a = addr1->a & addr2->a;
 	result->b = addr1->b & addr2->b;
 	result->c = addr1->c & addr2->c;
@@ -457,7 +457,7 @@ macaddr8_or(PG_FUNCTION_ARGS)
 	macaddr8   *addr2 = PG_GETARG_MACADDR8_P(1);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 	result->a = addr1->a | addr2->a;
 	result->b = addr1->b | addr2->b;
 	result->c = addr1->c | addr2->c;
@@ -479,7 +479,7 @@ macaddr8_trunc(PG_FUNCTION_ARGS)
 	macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 
 	result->a = addr->a;
 	result->b = addr->b;
@@ -502,7 +502,7 @@ macaddr8_set7bit(PG_FUNCTION_ARGS)
 	macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 
 	result->a = addr->a | 0x02;
 	result->b = addr->b;
@@ -526,7 +526,7 @@ macaddrtomacaddr8(PG_FUNCTION_ARGS)
 	macaddr    *addr6 = PG_GETARG_MACADDR_P(0);
 	macaddr8   *result;
 
-	result = (macaddr8 *) palloc0(sizeof(macaddr8));
+	result = palloc0_object(macaddr8);
 
 	result->a = addr6->a;
 	result->b = addr6->b;
@@ -547,7 +547,7 @@ macaddr8tomacaddr(PG_FUNCTION_ARGS)
 	macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
 	macaddr    *result;
 
-	result = (macaddr *) palloc0(sizeof(macaddr));
+	result = palloc0_object(macaddr);
 
 	if ((addr->d != 0xFF) || (addr->e != 0xFE))
 		ereport(ERROR,
diff --git a/src/backend/utils/adt/mcxtfuncs.c b/src/backend/utils/adt/mcxtfuncs.c
index fe6dce9cba3..46dfb3dd133 100644
--- a/src/backend/utils/adt/mcxtfuncs.c
+++ b/src/backend/utils/adt/mcxtfuncs.c
@@ -52,7 +52,7 @@ int_list_to_array(const List *list)
 	ArrayType  *result_array;
 
 	length = list_length(list);
-	datum_array = (Datum *) palloc(length * sizeof(Datum));
+	datum_array = palloc_array(Datum, length);
 
 	foreach_int(i, list)
 		datum_array[foreach_current_index(i)] = Int32GetDatum(i);
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index a365c432d34..c32f24fbf97 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -487,7 +487,7 @@ pg_get_catalog_foreign_keys(PG_FUNCTION_ARGS)
 		 * array_in, and it wouldn't be very efficient if we could.  Fill an
 		 * FmgrInfo to use for the call.
 		 */
-		arrayinp = (FmgrInfo *) palloc(sizeof(FmgrInfo));
+		arrayinp = palloc_object(FmgrInfo);
 		fmgr_info(F_ARRAY_IN, arrayinp);
 		funcctx->user_fctx = arrayinp;
 
diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c
index 5273b97f7fe..a34efea5c61 100644
--- a/src/backend/utils/adt/multirangetypes.c
+++ b/src/backend/utils/adt/multirangetypes.c
@@ -125,7 +125,7 @@ multirange_in(PG_FUNCTION_ARGS)
 	int32		range_count = 0;
 	int32		range_capacity = 8;
 	RangeType  *range;
-	RangeType **ranges = palloc(range_capacity * sizeof(RangeType *));
+	RangeType **ranges = palloc_array(RangeType *, range_capacity);
 	MultirangeIOData *cache;
 	MultirangeType *ret;
 	MultirangeParseState parse_state;
@@ -348,7 +348,7 @@ multirange_recv(PG_FUNCTION_ARGS)
 	cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_receive);
 
 	range_count = pq_getmsgint(buf, 4);
-	ranges = palloc(range_count * sizeof(RangeType *));
+	ranges = palloc_array(RangeType *, range_count);
 
 	initStringInfo(&tmpbuf);
 	for (int i = 0; i < range_count; i++)
@@ -836,7 +836,7 @@ multirange_deserialize(TypeCacheEntry *rangetyp,
 	{
 		int			i;
 
-		*ranges = palloc(*range_count * sizeof(RangeType *));
+		*ranges = palloc_array(RangeType *, *range_count);
 		for (i = 0; i < *range_count; i++)
 			(*ranges)[i] = multirange_get_range(rangetyp, multirange, i);
 	}
@@ -2818,7 +2818,7 @@ multirange_unnest(PG_FUNCTION_ARGS)
 		mr = PG_GETARG_MULTIRANGE_P(0);
 
 		/* allocate memory for user context */
-		fctx = (multirange_unnest_fctx *) palloc(sizeof(multirange_unnest_fctx));
+		fctx = palloc_object(multirange_unnest_fctx);
 
 		/* initialize state */
 		fctx->mr = mr;
diff --git a/src/backend/utils/adt/multirangetypes_selfuncs.c b/src/backend/utils/adt/multirangetypes_selfuncs.c
index 21f0205d803..fc5a4354fce 100644
--- a/src/backend/utils/adt/multirangetypes_selfuncs.c
+++ b/src/backend/utils/adt/multirangetypes_selfuncs.c
@@ -496,8 +496,8 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
 	 * bounds.
 	 */
 	nhist = hslot.nvalues;
-	hist_lower = (RangeBound *) palloc(sizeof(RangeBound) * nhist);
-	hist_upper = (RangeBound *) palloc(sizeof(RangeBound) * nhist);
+	hist_lower = palloc_array(RangeBound, nhist);
+	hist_upper = palloc_array(RangeBound, nhist);
 	for (i = 0; i < nhist; i++)
 	{
 		bool		empty;
diff --git a/src/backend/utils/adt/multixactfuncs.c b/src/backend/utils/adt/multixactfuncs.c
index e74ea938348..a428e140bc4 100644
--- a/src/backend/utils/adt/multixactfuncs.c
+++ b/src/backend/utils/adt/multixactfuncs.c
@@ -50,7 +50,7 @@ pg_get_multixact_members(PG_FUNCTION_ARGS)
 		funccxt = SRF_FIRSTCALL_INIT();
 		oldcxt = MemoryContextSwitchTo(funccxt->multi_call_memory_ctx);
 
-		multi = palloc(sizeof(mxact));
+		multi = palloc_object(mxact);
 		/* no need to allow for old values here */
 		multi->nmembers = GetMultiXactIdMembers(mxid, &multi->members, false,
 												false);
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index 3cb0ab6829a..3a2002097dd 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -75,7 +75,7 @@ network_in(char *src, bool is_cidr, Node *escontext)
 	int			bits;
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = (inet *) palloc0_object(inet);
 
 	/*
 	 * First, check to see if this is an IPv6 or IPv4 address.  IPv6 addresses
@@ -196,7 +196,7 @@ network_recv(StringInfo buf, bool is_cidr)
 				i;
 
 	/* make sure any unused bits in a CIDR value are zeroed */
-	addr = (inet *) palloc0(sizeof(inet));
+	addr = palloc0_object(inet);
 
 	ip_family(addr) = pq_getmsgbyte(buf);
 	if (ip_family(addr) != PGSQL_AF_INET &&
@@ -363,7 +363,7 @@ cidr_set_masklen(PG_FUNCTION_ARGS)
 inet *
 cidr_set_masklen_internal(const inet *src, int bits)
 {
-	inet	   *dst = (inet *) palloc0(sizeof(inet));
+	inet	   *dst = palloc0_object(inet);
 
 	ip_family(dst) = ip_family(src);
 	ip_bits(dst) = bits;
@@ -444,7 +444,7 @@ network_sortsupport(PG_FUNCTION_ARGS)
 
 		oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
 
-		uss = palloc(sizeof(network_sortsupport_state));
+		uss = palloc_object(network_sortsupport_state);
 		uss->input_count = 0;
 		uss->estimating = true;
 		initHyperLogLog(&uss->abbr_card, 10);
@@ -1227,7 +1227,7 @@ network_broadcast(PG_FUNCTION_ARGS)
 			   *b;
 
 	/* make sure any unused bits are zeroed */
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	maxbytes = ip_addrsize(ip);
 	bits = ip_bits(ip);
@@ -1271,7 +1271,7 @@ network_network(PG_FUNCTION_ARGS)
 			   *b;
 
 	/* make sure any unused bits are zeroed */
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	bits = ip_bits(ip);
 	a = ip_addr(ip);
@@ -1314,7 +1314,7 @@ network_netmask(PG_FUNCTION_ARGS)
 	unsigned char *b;
 
 	/* make sure any unused bits are zeroed */
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	bits = ip_bits(ip);
 	b = ip_addr(dst);
@@ -1357,7 +1357,7 @@ network_hostmask(PG_FUNCTION_ARGS)
 	unsigned char *b;
 
 	/* make sure any unused bits are zeroed */
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	maxbytes = ip_addrsize(ip);
 	bits = ip_maxbits(ip) - ip_bits(ip);
@@ -1792,7 +1792,7 @@ inetnot(PG_FUNCTION_ARGS)
 	inet	   *ip = PG_GETARG_INET_PP(0);
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	{
 		int			nb = ip_addrsize(ip);
@@ -1818,7 +1818,7 @@ inetand(PG_FUNCTION_ARGS)
 	inet	   *ip2 = PG_GETARG_INET_PP(1);
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	if (ip_family(ip) != ip_family(ip2))
 		ereport(ERROR,
@@ -1850,7 +1850,7 @@ inetor(PG_FUNCTION_ARGS)
 	inet	   *ip2 = PG_GETARG_INET_PP(1);
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	if (ip_family(ip) != ip_family(ip2))
 		ereport(ERROR,
@@ -1880,7 +1880,7 @@ internal_inetpl(inet *ip, int64 addend)
 {
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	{
 		int			nb = ip_addrsize(ip);
diff --git a/src/backend/utils/adt/network_gist.c b/src/backend/utils/adt/network_gist.c
index a08c4953789..30145f5985a 100644
--- a/src/backend/utils/adt/network_gist.c
+++ b/src/backend/utils/adt/network_gist.c
@@ -475,7 +475,7 @@ build_inet_union_key(int family, int minbits, int commonbits,
 	GistInetKey *result;
 
 	/* Make sure any unused bits are zeroed. */
-	result = (GistInetKey *) palloc0(sizeof(GistInetKey));
+	result = palloc0_object(GistInetKey);
 
 	gk_ip_family(result) = family;
 	gk_ip_minbits(result) = minbits;
@@ -546,13 +546,13 @@ inet_gist_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)
 	{
-		retval = palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		if (DatumGetPointer(entry->key) != NULL)
 		{
 			inet	   *in = DatumGetInetPP(entry->key);
 			GistInetKey *r;
 
-			r = (GistInetKey *) palloc0(sizeof(GistInetKey));
+			r = palloc0_object(GistInetKey);
 
 			gk_ip_family(r) = ip_family(in);
 			gk_ip_minbits(r) = ip_bits(in);
@@ -594,14 +594,14 @@ inet_gist_fetch(PG_FUNCTION_ARGS)
 	GISTENTRY  *retval;
 	inet	   *dst;
 
-	dst = (inet *) palloc0(sizeof(inet));
+	dst = palloc0_object(inet);
 
 	ip_family(dst) = gk_ip_family(key);
 	ip_bits(dst) = gk_ip_minbits(key);
 	memcpy(ip_addr(dst), gk_ip_addr(key), ip_addrsize(dst));
 	SET_INET_VARSIZE(dst);
 
-	retval = palloc(sizeof(GISTENTRY));
+	retval = palloc_object(GISTENTRY);
 	gistentryinit(*retval, InetPGetDatum(dst), entry->rel, entry->page,
 				  entry->offset, false);
 
diff --git a/src/backend/utils/adt/network_spgist.c b/src/backend/utils/adt/network_spgist.c
index a84747d9275..2f1e58e9b5c 100644
--- a/src/backend/utils/adt/network_spgist.c
+++ b/src/backend/utils/adt/network_spgist.c
@@ -196,8 +196,8 @@ inet_spg_picksplit(PG_FUNCTION_ARGS)
 
 	/* Don't need labels; allocate output arrays */
 	out->nodeLabels = NULL;
-	out->mapTuplesToNodes = (int *) palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = (Datum *) palloc(sizeof(Datum) * in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples); 
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	if (differentFamilies)
 	{
@@ -301,7 +301,7 @@ inet_spg_inner_consistent(PG_FUNCTION_ARGS)
 
 	if (which)
 	{
-		out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
+		out->nodeNumbers = palloc_array(int, in->nNodes);
 
 		for (i = 0; i < in->nNodes; i++)
 		{
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 2501007d981..6e8102a0459 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -1759,8 +1759,7 @@ generate_series_step_numeric(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		fctx = (generate_series_numeric_fctx *)
-			palloc(sizeof(generate_series_numeric_fctx));
+		fctx = palloc_object(generate_series_numeric_fctx);
 
 		/*
 		 * Use fctx to keep state from call to call. Seed current with the
@@ -2117,7 +2116,7 @@ numeric_sortsupport(PG_FUNCTION_ARGS)
 		NumericSortSupport *nss;
 		MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
 
-		nss = palloc(sizeof(NumericSortSupport));
+		nss = palloc_object(NumericSortSupport);
 
 		/*
 		 * palloc a buffer for handling unaligned packed values in addition to
@@ -4754,7 +4753,7 @@ makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
 
 	old_context = MemoryContextSwitchTo(agg_context);
 
-	state = (NumericAggState *) palloc0(sizeof(NumericAggState));
+	state = palloc0_object(NumericAggState);
 	state->calcSumX2 = calcSumX2;
 	state->agg_context = agg_context;
 
@@ -4772,7 +4771,7 @@ makeNumericAggStateCurrentContext(bool calcSumX2)
 {
 	NumericAggState *state;
 
-	state = (NumericAggState *) palloc0(sizeof(NumericAggState));
+	state = palloc0_object(NumericAggState);
 	state->calcSumX2 = calcSumX2;
 	state->agg_context = CurrentMemoryContext;
 
@@ -5418,7 +5417,7 @@ makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
 
 	old_context = MemoryContextSwitchTo(agg_context);
 
-	state = (Int128AggState *) palloc0(sizeof(Int128AggState));
+	state = palloc0_object(Int128AggState);
 	state->calcSumX2 = calcSumX2;
 
 	MemoryContextSwitchTo(old_context);
@@ -5435,7 +5434,7 @@ makeInt128AggStateCurrentContext(bool calcSumX2)
 {
 	Int128AggState *state;
 
-	state = (Int128AggState *) palloc0(sizeof(Int128AggState));
+	state = palloc0_object(Int128AggState);
 	state->calcSumX2 = calcSumX2;
 
 	return state;
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index 2121cc05f28..ac3963fc3e0 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -153,7 +153,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
 		qcontext = fcinfo->flinfo->fn_mcxt;
 		oldcontext = MemoryContextSwitchTo(qcontext);
 
-		qstate = (OSAPerQueryState *) palloc0(sizeof(OSAPerQueryState));
+		qstate = palloc0_object(OSAPerQueryState);
 		qstate->aggref = aggref;
 		qstate->qcontext = qcontext;
 
@@ -278,7 +278,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
 	/* Now build the stuff we need in group-lifespan context */
 	oldcontext = MemoryContextSwitchTo(gcontext);
 
-	osastate = (OSAPerGroupState *) palloc(sizeof(OSAPerGroupState));
+	osastate = palloc_object(OSAPerGroupState);
 	osastate->qstate = qstate;
 	osastate->gcontext = gcontext;
 
diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c
index 6ad3f93b543..b125b5da3a6 100644
--- a/src/backend/utils/adt/pg_locale_libc.c
+++ b/src/backend/utils/adt/pg_locale_libc.c
@@ -486,7 +486,7 @@ strlower_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 				 errmsg("out of memory")));
 
 	/* Output workspace cannot have more codes than input bytes */
-	workspace = (wchar_t *) palloc((srclen + 1) * sizeof(wchar_t));
+	workspace = palloc_array(wchar_t, srclen + 1);
 
 	char2wchar(workspace, srclen + 1, src, srclen, loc);
 
@@ -591,7 +591,7 @@ strtitle_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 				 errmsg("out of memory")));
 
 	/* Output workspace cannot have more codes than input bytes */
-	workspace = (wchar_t *) palloc((srclen + 1) * sizeof(wchar_t));
+	workspace = palloc_array(wchar_t, srclen + 1);
 
 	char2wchar(workspace, srclen + 1, src, srclen, loc);
 
@@ -684,7 +684,7 @@ strupper_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 				 errmsg("out of memory")));
 
 	/* Output workspace cannot have more codes than input bytes */
-	workspace = (wchar_t *) palloc((srclen + 1) * sizeof(wchar_t));
+	workspace = palloc_array(wchar_t, srclen + 1);
 
 	char2wchar(workspace, srclen + 1, src, srclen, loc);
 
diff --git a/src/backend/utils/adt/pg_ndistinct.c b/src/backend/utils/adt/pg_ndistinct.c
index 5292521b169..b47c93cff4d 100644
--- a/src/backend/utils/adt/pg_ndistinct.c
+++ b/src/backend/utils/adt/pg_ndistinct.c
@@ -180,7 +180,7 @@ ndistinct_object_end(void *state)
 	}
 
 	/* Create the MVNDistinctItem */
-	item = palloc(sizeof(MVNDistinctItem));
+	item = palloc_object(MVNDistinctItem);
 	item->nattributes = natts;
 	item->attributes = palloc0(natts * sizeof(AttrNumber));
 	item->ndistinct = (double) parse->ndistinct;
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index 065a8000cf2..e31ebd0a2de 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -1258,7 +1258,7 @@ range_minus_multi(PG_FUNCTION_ARGS)
 			elog(ERROR, "range types do not match");
 
 		/* allocate memory for user context */
-		fctx = (struct range_minus_multi_fctx *) palloc(sizeof(struct range_minus_multi_fctx));
+		fctx = palloc_object(struct range_minus_multi_fctx);
 
 		/*
 		 * Initialize state. We can't store the range typcache in fn_extra
diff --git a/src/backend/utils/adt/rangetypes_gist.c b/src/backend/utils/adt/rangetypes_gist.c
index a60ee985e74..33c705e6a87 100644
--- a/src/backend/utils/adt/rangetypes_gist.c
+++ b/src/backend/utils/adt/rangetypes_gist.c
@@ -251,7 +251,7 @@ multirange_gist_compress(PG_FUNCTION_ARGS)
 		MultirangeType *mr = DatumGetMultirangeTypeP(entry->key);
 		RangeType  *r;
 		TypeCacheEntry *typcache;
-		GISTENTRY  *retval = palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
 		r = multirange_get_union_range(typcache->rngtype, mr);
@@ -1240,8 +1240,7 @@ range_gist_single_sorting_split(TypeCacheEntry *typcache,
 
 	maxoff = entryvec->n - 1;
 
-	sortItems = (SingleBoundSortItem *)
-		palloc(maxoff * sizeof(SingleBoundSortItem));
+	sortItems = palloc_array(SingleBoundSortItem, maxoff);
 
 	/*
 	 * Prepare auxiliary array and sort the values.
@@ -1343,8 +1342,8 @@ range_gist_double_sorting_split(TypeCacheEntry *typcache,
 	context.first = true;
 
 	/* Allocate arrays for sorted range bounds */
-	by_lower = (NonEmptyRange *) palloc(nentries * sizeof(NonEmptyRange));
-	by_upper = (NonEmptyRange *) palloc(nentries * sizeof(NonEmptyRange));
+	by_lower = palloc_array(NonEmptyRange, nentries);
+	by_upper = palloc_array(NonEmptyRange, nentries);
 
 	/* Fill arrays of bounds */
 	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
@@ -1499,8 +1498,8 @@ range_gist_double_sorting_split(TypeCacheEntry *typcache,
 	 */
 
 	/* Allocate vectors for results */
-	v->spl_left = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
-	v->spl_right = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
+	v->spl_left = palloc_array(OffsetNumber, nentries);
+	v->spl_right = palloc_array(OffsetNumber, nentries);
 	v->spl_nleft = 0;
 	v->spl_nright = 0;
 
@@ -1509,7 +1508,7 @@ range_gist_double_sorting_split(TypeCacheEntry *typcache,
 	 * either group without affecting overlap along selected axis.
 	 */
 	common_entries_count = 0;
-	common_entries = (CommonEntry *) palloc(nentries * sizeof(CommonEntry));
+	common_entries = palloc_array(CommonEntry, nentries);
 
 	/*
 	 * Distribute entries which can be distributed unambiguously, and collect
diff --git a/src/backend/utils/adt/rangetypes_selfuncs.c b/src/backend/utils/adt/rangetypes_selfuncs.c
index d85252cafb2..27d736a40e5 100644
--- a/src/backend/utils/adt/rangetypes_selfuncs.c
+++ b/src/backend/utils/adt/rangetypes_selfuncs.c
@@ -412,8 +412,8 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
 	 * bounds.
 	 */
 	nhist = hslot.nvalues;
-	hist_lower = (RangeBound *) palloc(sizeof(RangeBound) * nhist);
-	hist_upper = (RangeBound *) palloc(sizeof(RangeBound) * nhist);
+	hist_lower = palloc_array(RangeBound, nhist);
+	hist_upper = palloc_array(RangeBound, nhist);
 	for (i = 0; i < nhist; i++)
 	{
 		range_deserialize(typcache, DatumGetRangeTypeP(hslot.values[i]),
diff --git a/src/backend/utils/adt/rangetypes_spgist.c b/src/backend/utils/adt/rangetypes_spgist.c
index be519654880..14e5d6065f8 100644
--- a/src/backend/utils/adt/rangetypes_spgist.c
+++ b/src/backend/utils/adt/rangetypes_spgist.c
@@ -216,8 +216,8 @@ spg_range_quad_picksplit(PG_FUNCTION_ARGS)
 								  RangeTypeGetOid(DatumGetRangeTypeP(in->datums[0])));
 
 	/* Allocate memory for bounds */
-	lowerBounds = palloc(sizeof(RangeBound) * in->nTuples);
-	upperBounds = palloc(sizeof(RangeBound) * in->nTuples);
+	lowerBounds = palloc_array(RangeBound, in->nTuples);
+	upperBounds = palloc_array(RangeBound, in->nTuples);
 	j = 0;
 
 	/* Deserialize bounds of ranges, count non-empty ranges */
@@ -243,8 +243,8 @@ spg_range_quad_picksplit(PG_FUNCTION_ARGS)
 		out->prefixDatum = PointerGetDatum(NULL);
 		out->nodeLabels = NULL;
 
-		out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
-		out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
+		out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+		out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 		/* Place all ranges into node 0 */
 		for (i = 0; i < in->nTuples; i++)
@@ -273,8 +273,8 @@ spg_range_quad_picksplit(PG_FUNCTION_ARGS)
 	out->nNodes = (in->level == 0) ? 5 : 4;
 	out->nodeLabels = NULL;		/* we don't need node labels */
 
-	out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
-	out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
+	out->mapTuplesToNodes = palloc_array(int, in->nTuples);
+	out->leafTupleDatums = palloc_array(Datum, in->nTuples);
 
 	/*
 	 * Assign ranges to corresponding nodes according to quadrants relative to
@@ -316,7 +316,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
 	{
 		/* Report that all nodes should be visited */
 		out->nNodes = in->nNodes;
-		out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
+		out->nodeNumbers = palloc_array(int, in->nNodes);
 		for (i = 0; i < in->nNodes; i++)
 			out->nodeNumbers[i] = i;
 		PG_RETURN_VOID();
@@ -732,9 +732,9 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
 	}
 
 	/* We must descend into the quadrant(s) identified by 'which' */
-	out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
+	out->nodeNumbers = palloc_array(int, in->nNodes);
 	if (needPrevious)
-		out->traversalValues = (void **) palloc(sizeof(void *) * in->nNodes);
+		out->traversalValues = palloc_array(void *, in->nNodes);
 	out->nNodes = 0;
 
 	/*
diff --git a/src/backend/utils/adt/rangetypes_typanalyze.c b/src/backend/utils/adt/rangetypes_typanalyze.c
index 36e885af2dd..45ea6cbc780 100644
--- a/src/backend/utils/adt/rangetypes_typanalyze.c
+++ b/src/backend/utils/adt/rangetypes_typanalyze.c
@@ -151,9 +151,9 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 	has_subdiff = OidIsValid(typcache->rng_subdiff_finfo.fn_oid);
 
 	/* Allocate memory to hold range bounds and lengths of the sample ranges. */
-	lowers = (RangeBound *) palloc(sizeof(RangeBound) * samplerows);
-	uppers = (RangeBound *) palloc(sizeof(RangeBound) * samplerows);
-	lengths = (float8 *) palloc(sizeof(float8) * samplerows);
+	lowers = palloc_array(RangeBound, samplerows);
+	uppers = palloc_array(RangeBound, samplerows);
+	lengths = palloc_array(float8, samplerows);
 
 	/* Loop over the sample ranges. */
 	for (range_no = 0; range_no < samplerows; range_no++)
@@ -401,7 +401,7 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 		stats->statypalign[slot_idx] = 'd';
 
 		/* Store the fraction of empty ranges */
-		emptyfrac = (float4 *) palloc(sizeof(float4));
+		emptyfrac = palloc_object(float4);
 		*emptyfrac = ((double) empty_cnt) / ((double) non_null_cnt);
 		stats->stanumbers[slot_idx] = emptyfrac;
 		stats->numnumbers[slot_idx] = 1;
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
index b0cdef9b19f..6542e8c1df0 100644
--- a/src/backend/utils/adt/regexp.c
+++ b/src/backend/utils/adt/regexp.c
@@ -189,7 +189,7 @@ RE_compile_and_cache(text *text_re, int cflags, Oid collation)
 	 */
 
 	/* Convert pattern string to wide characters */
-	pattern = (pg_wchar *) palloc((text_re_len + 1) * sizeof(pg_wchar));
+	pattern = palloc_array(pg_wchar, text_re_len + 1);
 	pattern_len = pg_mb2wchar_with_len(text_re_val,
 									   pattern,
 									   text_re_len);
@@ -329,7 +329,7 @@ RE_execute(regex_t *re, char *dat, int dat_len,
 	bool		match;
 
 	/* Convert data string to wide characters */
-	data = (pg_wchar *) palloc((dat_len + 1) * sizeof(pg_wchar));
+	data = palloc_array(pg_wchar, dat_len + 1);
 	data_len = pg_mb2wchar_with_len(dat, data, dat_len);
 
 	/* Perform RE match and return result */
@@ -1389,8 +1389,8 @@ regexp_match(PG_FUNCTION_ARGS)
 	Assert(matchctx->nmatches == 1);
 
 	/* Create workspace that build_regexp_match_result needs */
-	matchctx->elems = (Datum *) palloc(sizeof(Datum) * matchctx->npatterns);
-	matchctx->nulls = (bool *) palloc(sizeof(bool) * matchctx->npatterns);
+	matchctx->elems = palloc_array(Datum, matchctx->npatterns);
+	matchctx->nulls = palloc_array(bool, matchctx->npatterns);
 
 	PG_RETURN_DATUM(PointerGetDatum(build_regexp_match_result(matchctx)));
 }
@@ -1432,8 +1432,8 @@ regexp_matches(PG_FUNCTION_ARGS)
 										true, false, false);
 
 		/* Pre-create workspace that build_regexp_match_result needs */
-		matchctx->elems = (Datum *) palloc(sizeof(Datum) * matchctx->npatterns);
-		matchctx->nulls = (bool *) palloc(sizeof(bool) * matchctx->npatterns);
+		matchctx->elems = palloc_array(Datum, matchctx->npatterns);
+		matchctx->nulls = palloc_array(bool, matchctx->npatterns);
 
 		MemoryContextSwitchTo(oldcontext);
 		funcctx->user_fctx = matchctx;
@@ -1489,7 +1489,7 @@ setup_regexp_matches(text *orig_str, text *pattern, pg_re_flags *re_flags,
 					 bool ignore_degenerate,
 					 bool fetching_unmatched)
 {
-	regexp_matches_ctx *matchctx = palloc0(sizeof(regexp_matches_ctx));
+	regexp_matches_ctx *matchctx = palloc0_object(regexp_matches_ctx);
 	int			eml = pg_database_encoding_max_length();
 	int			orig_len;
 	pg_wchar   *wide_str;
@@ -1509,7 +1509,7 @@ setup_regexp_matches(text *orig_str, text *pattern, pg_re_flags *re_flags,
 
 	/* convert string to pg_wchar form for matching */
 	orig_len = VARSIZE_ANY_EXHDR(orig_str);
-	wide_str = (pg_wchar *) palloc(sizeof(pg_wchar) * (orig_len + 1));
+	wide_str = palloc_array(pg_wchar, orig_len + 1);
 	wide_len = pg_mb2wchar_with_len(VARDATA_ANY(orig_str), wide_str, orig_len);
 
 	/* set up the compiled pattern */
@@ -1532,7 +1532,7 @@ setup_regexp_matches(text *orig_str, text *pattern, pg_re_flags *re_flags,
 	}
 
 	/* temporary output space for RE package */
-	pmatch = palloc(sizeof(regmatch_t) * pmatch_len);
+	pmatch = palloc_array(regmatch_t, pmatch_len);
 
 	/*
 	 * the real output space (grown dynamically if needed)
@@ -1541,7 +1541,7 @@ setup_regexp_matches(text *orig_str, text *pattern, pg_re_flags *re_flags,
 	 * than at 2^27
 	 */
 	array_len = re_flags->glob ? 255 : 31;
-	matchctx->match_locs = (int *) palloc(sizeof(int) * array_len);
+	matchctx->match_locs = palloc_array(int, array_len);
 	array_idx = 0;
 
 	/* search for the pattern, perhaps repeatedly */
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index 9e5449f17d7..80f59a810fd 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -140,8 +140,8 @@ record_in(PG_FUNCTION_ARGS)
 		my_extra->ncolumns = ncolumns;
 	}
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	/*
 	 * Scan the string.  We use "buf" to accumulate the de-quoted data for
@@ -383,8 +383,8 @@ record_out(PG_FUNCTION_ARGS)
 		my_extra->ncolumns = ncolumns;
 	}
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	/* Break down the tuple into fields */
 	heap_deform_tuple(&tuple, tupdesc, values, nulls);
@@ -539,8 +539,8 @@ record_recv(PG_FUNCTION_ARGS)
 		my_extra->ncolumns = ncolumns;
 	}
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	/* Fetch number of columns user thinks it has */
 	usercols = pq_getmsgint(buf, 4);
@@ -741,8 +741,8 @@ record_send(PG_FUNCTION_ARGS)
 		my_extra->ncolumns = ncolumns;
 	}
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	/* Break down the tuple into fields */
 	heap_deform_tuple(&tuple, tupdesc, values, nulls);
@@ -1863,8 +1863,8 @@ hash_record(PG_FUNCTION_ARGS)
 	}
 
 	/* Break down the tuple into fields */
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 	heap_deform_tuple(&tuple, tupdesc, values, nulls);
 
 	for (int i = 0; i < ncolumns; i++)
@@ -1984,8 +1984,8 @@ hash_record_extended(PG_FUNCTION_ARGS)
 	}
 
 	/* Break down the tuple into fields */
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 	heap_deform_tuple(&tuple, tupdesc, values, nulls);
 
 	for (int i = 0; i < ncolumns; i++)
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 6cf90be40bb..6eae1d5e78f 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3713,7 +3713,7 @@ deparse_context_for(const char *aliasname, Oid relid)
 	deparse_namespace *dpns;
 	RangeTblEntry *rte;
 
-	dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
+	dpns = palloc0_object(deparse_namespace);
 
 	/* Build a minimal RTE for the rel */
 	rte = makeNode(RangeTblEntry);
@@ -3757,7 +3757,7 @@ deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
 {
 	deparse_namespace *dpns;
 
-	dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
+	dpns = palloc0_object(deparse_namespace);
 
 	/* Initialize fields that stay the same across the whole plan tree */
 	dpns->rtable = pstmt->rtable;
@@ -4051,7 +4051,7 @@ set_deparse_for_query(deparse_namespace *dpns, Query *query,
 	dpns->rtable_columns = NIL;
 	while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
 		dpns->rtable_columns = lappend(dpns->rtable_columns,
-									   palloc0(sizeof(deparse_columns)));
+									   palloc0_object(deparse_columns));
 
 	/* If it's a utility query, it won't have a jointree */
 	if (query->jointree)
@@ -4107,7 +4107,7 @@ set_simple_column_names(deparse_namespace *dpns)
 	dpns->rtable_columns = NIL;
 	while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
 		dpns->rtable_columns = lappend(dpns->rtable_columns,
-									   palloc0(sizeof(deparse_columns)));
+									   palloc0_object(deparse_columns));
 
 	/* Assign unique column aliases within each non-join RTE */
 	forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 540aa9628d7..c760b19db55 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -3683,7 +3683,7 @@ add_unique_group_var(PlannerInfo *root, List *varinfos,
 		}
 	}
 
-	varinfo = (GroupVarInfo *) palloc(sizeof(GroupVarInfo));
+	varinfo = palloc_object(GroupVarInfo);
 
 	varinfo->var = var;
 	varinfo->rel = vardata->rel;
@@ -4264,7 +4264,7 @@ estimate_multivariate_bucketsize(PlannerInfo *root, RelOptInfo *inner,
 				 * estimate_multivariate_ndistinct(), which doesn't care about
 				 * ndistinct and isdefault fields.  Thus, skip these fields.
 				 */
-				varinfo = (GroupVarInfo *) palloc0(sizeof(GroupVarInfo));
+				varinfo = palloc0_object(GroupVarInfo);
 				varinfo->var = expr;
 				varinfo->rel = root->simple_rel_array[relid];
 				varinfos = lappend(varinfos, varinfo);
diff --git a/src/backend/utils/adt/skipsupport.c b/src/backend/utils/adt/skipsupport.c
index 2bd35d2d272..2fcf5782ec8 100644
--- a/src/backend/utils/adt/skipsupport.c
+++ b/src/backend/utils/adt/skipsupport.c
@@ -38,7 +38,7 @@ PrepareSkipSupportFromOpclass(Oid opfamily, Oid opcintype, bool reverse)
 	if (!OidIsValid(skipSupportFunction))
 		return NULL;
 
-	sksup = palloc(sizeof(SkipSupportData));
+	sksup = palloc_object(SkipSupportData);
 	OidFunctionCall1(skipSupportFunction, PointerGetDatum(sksup));
 
 	if (reverse)
diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c
index 0cfb0bd3735..435d40fee3e 100644
--- a/src/backend/utils/adt/tid.c
+++ b/src/backend/utils/adt/tid.c
@@ -104,7 +104,7 @@ tidin(PG_FUNCTION_ARGS)
 						"tid", str)));
 	offsetNumber = (OffsetNumber) cvt;
 
-	result = (ItemPointer) palloc(sizeof(ItemPointerData));
+	result = (ItemPointer) palloc_object(ItemPointerData);
 
 	ItemPointerSet(result, blockNumber, offsetNumber);
 
@@ -146,7 +146,7 @@ tidrecv(PG_FUNCTION_ARGS)
 	blockNumber = pq_getmsgint(buf, sizeof(blockNumber));
 	offsetNumber = pq_getmsgint(buf, sizeof(offsetNumber));
 
-	result = (ItemPointer) palloc(sizeof(ItemPointerData));
+	result = (ItemPointer) palloc_object(ItemPointerData);
 
 	ItemPointerSet(result, blockNumber, offsetNumber);
 
@@ -300,7 +300,7 @@ currtid_internal(Relation rel, const ItemPointerData *tid)
 	Snapshot	snapshot;
 	TableScanDesc scan;
 
-	result = (ItemPointer) palloc(sizeof(ItemPointerData));
+	result = (ItemPointer) palloc_object(ItemPointerData);
 
 	aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
 								  ACL_SELECT);
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 2dc90a2b8a9..3569d201ee1 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -937,7 +937,7 @@ interval_in(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 	}
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	switch (dtype)
 	{
@@ -1004,7 +1004,7 @@ interval_recv(PG_FUNCTION_ARGS)
 	int32		typmod = PG_GETARG_INT32(2);
 	Interval   *interval;
 
-	interval = (Interval *) palloc(sizeof(Interval));
+	interval = palloc_object(Interval);
 
 	interval->time = pq_getmsgint64(buf);
 	interval->day = pq_getmsgint(buf, sizeof(interval->day));
@@ -1331,7 +1331,7 @@ interval_scale(PG_FUNCTION_ARGS)
 	int32		typmod = PG_GETARG_INT32(1);
 	Interval   *result;
 
-	result = palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 	*result = *interval;
 
 	AdjustIntervalForTypmod(result, typmod, NULL);
@@ -1545,7 +1545,7 @@ make_interval(PG_FUNCTION_ARGS)
 	if (isinf(secs) || isnan(secs))
 		goto out_of_range;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/* years and months -> months */
 	if (pg_mul_s32_overflow(years, MONTHS_PER_YEAR, &result->month) ||
@@ -2830,7 +2830,7 @@ timestamp_mi(PG_FUNCTION_ARGS)
 	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle infinities.
@@ -2925,7 +2925,7 @@ interval_justify_interval(PG_FUNCTION_ARGS)
 	TimeOffset	wholeday;
 	int32		wholemonth;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 	result->month = span->month;
 	result->day = span->day;
 	result->time = span->time;
@@ -3004,7 +3004,7 @@ interval_justify_hours(PG_FUNCTION_ARGS)
 	Interval   *result;
 	TimeOffset	wholeday;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 	result->month = span->month;
 	result->day = span->day;
 	result->time = span->time;
@@ -3046,7 +3046,7 @@ interval_justify_days(PG_FUNCTION_ARGS)
 	Interval   *result;
 	int32		wholemonth;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 	result->month = span->month;
 	result->day = span->day;
 	result->time = span->time;
@@ -3448,7 +3448,7 @@ interval_um(PG_FUNCTION_ARGS)
 	Interval   *interval = PG_GETARG_INTERVAL_P(0);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 	interval_um_internal(interval, result);
 
 	PG_RETURN_INTERVAL_P(result);
@@ -3506,7 +3506,7 @@ interval_pl(PG_FUNCTION_ARGS)
 	Interval   *span2 = PG_GETARG_INTERVAL_P(1);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle infinities.
@@ -3562,7 +3562,7 @@ interval_mi(PG_FUNCTION_ARGS)
 	Interval   *span2 = PG_GETARG_INTERVAL_P(1);
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle infinities.
@@ -3616,7 +3616,7 @@ interval_mul(PG_FUNCTION_ARGS)
 				orig_day = span->day;
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle NaN and infinities.
@@ -3746,7 +3746,7 @@ interval_div(PG_FUNCTION_ARGS)
 				orig_day = span->day;
 	Interval   *result;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	if (factor == 0.0)
 		ereport(ERROR,
@@ -3975,7 +3975,7 @@ makeIntervalAggState(FunctionCallInfo fcinfo)
 
 	old_context = MemoryContextSwitchTo(agg_context);
 
-	state = (IntervalAggState *) palloc0(sizeof(IntervalAggState));
+	state = palloc0_object(IntervalAggState);
 
 	MemoryContextSwitchTo(old_context);
 
@@ -4162,7 +4162,7 @@ interval_avg_deserialize(PG_FUNCTION_ARGS)
 	initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
 						   VARSIZE_ANY_EXHDR(sstate));
 
-	result = (IntervalAggState *) palloc0(sizeof(IntervalAggState));
+	result = palloc0_object(IntervalAggState);
 
 	/* N */
 	result->N = pq_getmsgint64(&buf);
@@ -4229,7 +4229,7 @@ interval_avg(PG_FUNCTION_ARGS)
 					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 					 errmsg("interval out of range")));
 
-		result = (Interval *) palloc(sizeof(Interval));
+		result = palloc_object(Interval);
 		if (state->pInfcount > 0)
 			INTERVAL_NOEND(result);
 		else
@@ -4266,7 +4266,7 @@ interval_sum(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("interval out of range")));
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	if (state->pInfcount > 0)
 		INTERVAL_NOEND(result);
@@ -4299,7 +4299,7 @@ timestamp_age(PG_FUNCTION_ARGS)
 	struct pg_tm tt2,
 			   *tm2 = &tt2;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle infinities.
@@ -4447,7 +4447,7 @@ timestamptz_age(PG_FUNCTION_ARGS)
 	int			tz1;
 	int			tz2;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	/*
 	 * Handle infinities.
@@ -5120,7 +5120,7 @@ interval_trunc(PG_FUNCTION_ARGS)
 	struct pg_itm tt,
 			   *tm = &tt;
 
-	result = (Interval *) palloc(sizeof(Interval));
+	result = palloc_object(Interval);
 
 	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
 											VARSIZE_ANY_EXHDR(units),
@@ -6687,8 +6687,7 @@ generate_series_timestamp(PG_FUNCTION_ARGS)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		fctx = (generate_series_timestamp_fctx *)
-			palloc(sizeof(generate_series_timestamp_fctx));
+		fctx = palloc_object(generate_series_timestamp_fctx);
 
 		/*
 		 * Use fctx to keep state from call to call. Seed current with the
@@ -6772,8 +6771,7 @@ generate_series_timestamptz_internal(FunctionCallInfo fcinfo)
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
 		/* allocate memory for user context */
-		fctx = (generate_series_timestamptz_fctx *)
-			palloc(sizeof(generate_series_timestamptz_fctx));
+		fctx = palloc_object(generate_series_timestamptz_fctx);
 
 		/*
 		 * Use fctx to keep state from call to call. Seed current with the
diff --git a/src/backend/utils/adt/tsginidx.c b/src/backend/utils/adt/tsginidx.c
index 2712fd89df0..24a1cbe89ed 100644
--- a/src/backend/utils/adt/tsginidx.c
+++ b/src/backend/utils/adt/tsginidx.c
@@ -73,7 +73,7 @@ gin_extract_tsvector(PG_FUNCTION_ARGS)
 		int			i;
 		WordEntry  *we = ARRPTR(vector);
 
-		entries = (Datum *) palloc(sizeof(Datum) * vector->size);
+		entries = palloc_array(Datum, vector->size);
 
 		for (i = 0; i < vector->size; i++)
 		{
@@ -133,16 +133,16 @@ gin_extract_tsquery(PG_FUNCTION_ARGS)
 		}
 		*nentries = j;
 
-		entries = (Datum *) palloc(sizeof(Datum) * j);
-		partialmatch = *ptr_partialmatch = (bool *) palloc(sizeof(bool) * j);
+		entries = palloc_array(Datum, j);
+		partialmatch = *ptr_partialmatch = palloc_array(bool, j);
 
 		/*
 		 * Make map to convert item's number to corresponding operand's (the
 		 * same, entry's) number. Entry's number is used in check array in
 		 * consistent method. We use the same map for each entry.
 		 */
-		*extra_data = (Pointer *) palloc(sizeof(Pointer) * j);
-		map_item_operand = (int *) palloc0(sizeof(int) * query->size);
+		*extra_data = palloc_array(Pointer, j);
+		map_item_operand = palloc0_array(int, query->size);
 
 		/* Now rescan the VAL items and fill in the arrays */
 		j = 0;
diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c
index 935187b37c7..01e43f86214 100644
--- a/src/backend/utils/adt/tsgistidx.c
+++ b/src/backend/utils/adt/tsgistidx.c
@@ -212,7 +212,7 @@ gtsvector_compress(PG_FUNCTION_ARGS)
 			res = ressign;
 		}
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -231,7 +231,7 @@ gtsvector_compress(PG_FUNCTION_ARGS)
 		}
 
 		res = gtsvector_alloc(SIGNKEY | ALLISTRUE, siglen, sign);
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		gistentryinit(*retval, PointerGetDatum(res),
 					  entry->rel, entry->page,
 					  entry->offset, false);
@@ -251,7 +251,7 @@ gtsvector_decompress(PG_FUNCTION_ARGS)
 
 	if (key != (SignTSVector *) DatumGetPointer(entry->key))
 	{
-		GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		GISTENTRY  *retval = palloc_object(GISTENTRY);
 
 		gistentryinit(*retval, PointerGetDatum(key),
 					  entry->rel, entry->page,
@@ -641,7 +641,7 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
 	v->spl_left = (OffsetNumber *) palloc(nbytes);
 	v->spl_right = (OffsetNumber *) palloc(nbytes);
 
-	cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2));
+	cache = palloc_array(CACHESIGN, maxoff + 2);
 	cache_sign = palloc(siglen * (maxoff + 2));
 
 	for (j = 0; j < maxoff + 2; j++)
@@ -688,7 +688,7 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
 	maxoff = OffsetNumberNext(maxoff);
 	fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff), siglen);
 	/* sort before ... */
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c
index 717de8073d5..a0c990fdfa0 100644
--- a/src/backend/utils/adt/tsquery.c
+++ b/src/backend/utils/adt/tsquery.c
@@ -534,7 +534,7 @@ pushOperator(TSQueryParserState state, int8 oper, int16 distance)
 
 	Assert(oper == OP_NOT || oper == OP_AND || oper == OP_OR || oper == OP_PHRASE);
 
-	tmp = (QueryOperator *) palloc0(sizeof(QueryOperator));
+	tmp = palloc0_object(QueryOperator);
 	tmp->type = QI_OPR;
 	tmp->oper = oper;
 	tmp->distance = (oper == OP_PHRASE) ? distance : 0;
@@ -559,7 +559,7 @@ pushValue_internal(TSQueryParserState state, pg_crc32 valcrc, int distance, int
 				 errmsg("operand is too long in tsquery: \"%s\"",
 						state->buffer)));
 
-	tmp = (QueryOperand *) palloc0(sizeof(QueryOperand));
+	tmp = palloc0_object(QueryOperand);
 	tmp->type = QI_VAL;
 	tmp->weight = weight;
 	tmp->prefix = prefix;
@@ -617,7 +617,7 @@ pushStop(TSQueryParserState state)
 {
 	QueryOperand *tmp;
 
-	tmp = (QueryOperand *) palloc0(sizeof(QueryOperand));
+	tmp = palloc0_object(QueryOperand);
 	tmp->type = QI_VALSTOP;
 
 	state->polstr = lcons(tmp, state->polstr);
@@ -1101,7 +1101,7 @@ infix(INFIX *in, int parentPriority, bool rightPhraseOp)
 		nrm.curpol = in->curpol;
 		nrm.op = in->op;
 		nrm.buflen = 16;
-		nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+		nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 
 		/* get right operand */
 		infix(&nrm, priority, (op == OP_PHRASE));
@@ -1157,7 +1157,7 @@ tsqueryout(PG_FUNCTION_ARGS)
 	}
 	nrm.curpol = GETQUERY(query);
 	nrm.buflen = 32;
-	nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+	nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 	*(nrm.cur) = '\0';
 	nrm.op = GETOPERAND(query);
 	infix(&nrm, -1 /* lowest priority */ , false);
@@ -1385,7 +1385,7 @@ tsquerytree(PG_FUNCTION_ARGS)
 	{
 		nrm.curpol = q;
 		nrm.buflen = 32;
-		nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+		nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 		*(nrm.cur) = '\0';
 		nrm.op = GETOPERAND(query);
 		infix(&nrm, -1, false);
diff --git a/src/backend/utils/adt/tsquery_cleanup.c b/src/backend/utils/adt/tsquery_cleanup.c
index 590d7c7989c..45de2da900c 100644
--- a/src/backend/utils/adt/tsquery_cleanup.c
+++ b/src/backend/utils/adt/tsquery_cleanup.c
@@ -32,7 +32,7 @@ typedef struct NODE
 static NODE *
 maketree(QueryItem *in)
 {
-	NODE	   *node = (NODE *) palloc(sizeof(NODE));
+	NODE	   *node = palloc_object(NODE);
 
 	/* since this function recurses, it could be driven to stack overflow. */
 	check_stack_depth();
diff --git a/src/backend/utils/adt/tsquery_gist.c b/src/backend/utils/adt/tsquery_gist.c
index f7f94c1c760..55fc93ebef5 100644
--- a/src/backend/utils/adt/tsquery_gist.c
+++ b/src/backend/utils/adt/tsquery_gist.c
@@ -33,7 +33,7 @@ gtsquery_compress(PG_FUNCTION_ARGS)
 	{
 		TSQuerySign sign;
 
-		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		retval = palloc_object(GISTENTRY);
 		sign = makeTSQuerySign(DatumGetTSQuery(entry->key));
 
 		gistentryinit(*retval, TSQuerySignGetDatum(sign),
@@ -213,7 +213,7 @@ gtsquery_picksplit(PG_FUNCTION_ARGS)
 	datum_r = GETENTRY(entryvec, seed_2);
 
 	maxoff = OffsetNumberNext(maxoff);
-	costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
+	costvector = palloc_array(SPLITCOST, maxoff);
 	for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
 	{
 		costvector[j - 1].pos = j;
diff --git a/src/backend/utils/adt/tsquery_op.c b/src/backend/utils/adt/tsquery_op.c
index bb77e923062..84bf070dff2 100644
--- a/src/backend/utils/adt/tsquery_op.c
+++ b/src/backend/utils/adt/tsquery_op.c
@@ -32,17 +32,17 @@ tsquery_numnode(PG_FUNCTION_ARGS)
 static QTNode *
 join_tsqueries(TSQuery a, TSQuery b, int8 operator, uint16 distance)
 {
-	QTNode	   *res = (QTNode *) palloc0(sizeof(QTNode));
+	QTNode	   *res = palloc0_object(QTNode);
 
 	res->flags |= QTN_NEEDFREE;
 
-	res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
+	res->valnode = palloc0_object(QueryItem);
 	res->valnode->type = QI_OPR;
 	res->valnode->qoperator.oper = operator;
 	if (operator == OP_PHRASE)
 		res->valnode->qoperator.distance = distance;
 
-	res->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
+	res->child = palloc0_array(QTNode *, 2);
 	res->child[0] = QT2QTN(GETQUERY(b), GETOPERAND(b));
 	res->child[1] = QT2QTN(GETQUERY(a), GETOPERAND(a));
 	res->nchild = 2;
@@ -165,15 +165,15 @@ tsquery_not(PG_FUNCTION_ARGS)
 	if (a->size == 0)
 		PG_RETURN_POINTER(a);
 
-	res = (QTNode *) palloc0(sizeof(QTNode));
+	res = palloc0_object(QTNode);
 
 	res->flags |= QTN_NEEDFREE;
 
-	res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
+	res->valnode = palloc0_object(QueryItem);
 	res->valnode->type = QI_OPR;
 	res->valnode->qoperator.oper = OP_NOT;
 
-	res->child = (QTNode **) palloc0(sizeof(QTNode *));
+	res->child = palloc0_object(QTNode *);
 	res->child[0] = QT2QTN(GETQUERY(a), GETOPERAND(a));
 	res->nchild = 1;
 
@@ -272,7 +272,7 @@ collectTSQueryValues(TSQuery a, int *nvalues_p)
 	int			nvalues = 0;
 	int			i;
 
-	values = (char **) palloc(sizeof(char *) * a->size);
+	values = palloc_array(char *, a->size);
 
 	for (i = 0; i < a->size; i++)
 	{
diff --git a/src/backend/utils/adt/tsquery_util.c b/src/backend/utils/adt/tsquery_util.c
index 1c24b041aa2..2ccfc9d3303 100644
--- a/src/backend/utils/adt/tsquery_util.c
+++ b/src/backend/utils/adt/tsquery_util.c
@@ -24,7 +24,7 @@
 QTNode *
 QT2QTN(QueryItem *in, char *operand)
 {
-	QTNode	   *node = (QTNode *) palloc0(sizeof(QTNode));
+	QTNode	   *node = palloc0_object(QTNode);
 
 	/* since this function recurses, it could be driven to stack overflow. */
 	check_stack_depth();
@@ -33,7 +33,7 @@ QT2QTN(QueryItem *in, char *operand)
 
 	if (in->type == QI_OPR)
 	{
-		node->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
+		node->child = palloc0_array(QTNode *, 2);
 		node->child[0] = QT2QTN(in + 1, operand);
 		node->sign = node->child[0]->sign;
 		if (in->qoperator.oper == OP_NOT)
@@ -226,7 +226,7 @@ QTNTernary(QTNode *in)
 			int			oldnchild = in->nchild;
 
 			in->nchild += cc->nchild - 1;
-			in->child = (QTNode **) repalloc(in->child, in->nchild * sizeof(QTNode *));
+			in->child = repalloc_array(in->child, QTNode *, in->nchild);
 
 			if (i + 1 != oldnchild)
 				memmove(in->child + i + cc->nchild, in->child + i + 1,
@@ -262,10 +262,10 @@ QTNBinary(QTNode *in)
 
 	while (in->nchild > 2)
 	{
-		QTNode	   *nn = (QTNode *) palloc0(sizeof(QTNode));
+		QTNode	   *nn = palloc0_object(QTNode);
 
-		nn->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
-		nn->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
+		nn->valnode = palloc0_object(QueryItem);
+		nn->child = palloc0_array(QTNode *, 2);
 
 		nn->nchild = 2;
 		nn->flags = QTN_NEEDFREE;
@@ -400,10 +400,10 @@ QTNCopy(QTNode *in)
 	/* since this function recurses, it could be driven to stack overflow. */
 	check_stack_depth();
 
-	out = (QTNode *) palloc(sizeof(QTNode));
+	out = palloc_object(QTNode);
 
 	*out = *in;
-	out->valnode = (QueryItem *) palloc(sizeof(QueryItem));
+	out->valnode = palloc_object(QueryItem);
 	*(out->valnode) = *(in->valnode);
 	out->flags |= QTN_NEEDFREE;
 
@@ -418,7 +418,7 @@ QTNCopy(QTNode *in)
 	{
 		int			i;
 
-		out->child = (QTNode **) palloc(sizeof(QTNode *) * in->nchild);
+		out->child = palloc_array(QTNode *, in->nchild);
 
 		for (i = 0; i < in->nchild; i++)
 			out->child[i] = QTNCopy(in->child[i]);
diff --git a/src/backend/utils/adt/tsrank.c b/src/backend/utils/adt/tsrank.c
index e863aa58653..4a341848647 100644
--- a/src/backend/utils/adt/tsrank.c
+++ b/src/backend/utils/adt/tsrank.c
@@ -160,7 +160,7 @@ SortAndUniqItems(TSQuery q, int *size)
 			  **ptr,
 			  **prevptr;
 
-	ptr = res = (QueryOperand **) palloc(sizeof(QueryOperand *) * *size);
+	ptr = res = palloc_array(QueryOperand *, *size);
 
 	/* Collect all operands from the tree to res */
 	while ((*size)--)
@@ -225,7 +225,7 @@ calc_rank_and(const float *w, TSVector t, TSQuery q)
 		pfree(item);
 		return calc_rank_or(w, t, q);
 	}
-	pos = (WordEntryPosVector **) palloc0(sizeof(WordEntryPosVector *) * q->size);
+	pos = palloc0_array(WordEntryPosVector *, q->size);
 
 	/* A dummy WordEntryPos array to use when haspos is false */
 	posnull.npos = 1;
@@ -743,7 +743,7 @@ get_docrep(TSVector txt, QueryRepresentation *qr, int *doclen)
 				cur = 0;
 	DocRepresentation *doc;
 
-	doc = (DocRepresentation *) palloc(sizeof(DocRepresentation) * len);
+	doc = palloc_array(DocRepresentation, len);
 
 	/*
 	 * Iterate through query to make DocRepresentation for words and it's
@@ -815,7 +815,7 @@ get_docrep(TSVector txt, QueryRepresentation *qr, int *doclen)
 		 * Join QueryItem per WordEntry and its position
 		 */
 		storage.pos = doc->pos;
-		storage.data.query.items = palloc(sizeof(QueryItem *) * qr->query->size);
+		storage.data.query.items = palloc_array(QueryItem *, qr->query->size);
 		storage.data.query.items[0] = doc->data.map.item;
 		storage.data.query.nitem = 1;
 
@@ -832,7 +832,7 @@ get_docrep(TSVector txt, QueryRepresentation *qr, int *doclen)
 				*wptr = storage;
 				wptr++;
 				storage.pos = rptr->pos;
-				storage.data.query.items = palloc(sizeof(QueryItem *) * qr->query->size);
+				storage.data.query.items = palloc_array(QueryItem *, qr->query->size);
 				storage.data.query.items[0] = rptr->data.map.item;
 				storage.data.query.nitem = 1;
 			}
@@ -878,8 +878,7 @@ calc_rank_cd(const float4 *arrdata, TSVector txt, TSQuery query, int method)
 	}
 
 	qr.query = query;
-	qr.operandData = (QueryRepresentationOperand *)
-		palloc0(sizeof(QueryRepresentationOperand) * query->size);
+	qr.operandData = palloc0_array(QueryRepresentationOperand, query->size);
 
 	doc = get_docrep(txt, &qr, &doclen);
 	if (!doc)
diff --git a/src/backend/utils/adt/tsvector.c b/src/backend/utils/adt/tsvector.c
index 1fa2e3729bf..39be10f45a4 100644
--- a/src/backend/utils/adt/tsvector.c
+++ b/src/backend/utils/adt/tsvector.c
@@ -202,8 +202,8 @@ tsvectorin(PG_FUNCTION_ARGS)
 	state = init_tsvector_parser(buf, 0, escontext);
 
 	arrlen = 64;
-	arr = (WordEntryIN *) palloc(sizeof(WordEntryIN) * arrlen);
-	cur = tmpbuf = (char *) palloc(buflen);
+	arr = palloc_array(WordEntryIN, arrlen); 
+	cur = tmpbuf = palloc_array(char, buflen);
 
 	while (gettoken_tsvector(state, &token, &toklen, &pos, &poslen, NULL))
 	{
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index c752cbe5463..b809089ac5d 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -1212,7 +1212,7 @@ checkclass_str(CHKVAL *chkval, WordEntry *entry, QueryOperand *val,
 			/*
 			 * Filter position information by weights
 			 */
-			dptr = data->pos = palloc(sizeof(WordEntryPos) * posvec->npos);
+			dptr = data->pos = palloc_array(WordEntryPos, posvec->npos);
 			data->allocated = true;
 
 			/* Is there a position with a matching weight? */
@@ -1391,12 +1391,12 @@ checkcondition_str(void *checkval, QueryOperand *val, ExecPhraseData *data)
 						if (totalpos == 0)
 						{
 							totalpos = 256;
-							allpos = palloc(sizeof(WordEntryPos) * totalpos);
+							allpos = palloc_array(WordEntryPos, totalpos);
 						}
 						else
 						{
 							totalpos *= 2;
-							allpos = repalloc(allpos, sizeof(WordEntryPos) * totalpos);
+							allpos = repalloc_array(allpos, WordEntryPos, totalpos);
 						}
 					}
 
@@ -2456,7 +2456,7 @@ ts_setup_firstcall(FunctionCallInfo fcinfo, FuncCallContext *funcctx,
 
 	oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-	stat->stack = palloc0(sizeof(StatEntry *) * (stat->maxdepth + 1));
+	stat->stack = palloc0_array(StatEntry *, stat->maxdepth + 1);
 	stat->stackpos = 0;
 
 	node = stat->root;
@@ -2839,7 +2839,7 @@ tsvector_update_trigger(PG_FUNCTION_ARGS, bool config_column)
 	prs.lenwords = 32;
 	prs.curwords = 0;
 	prs.pos = 0;
-	prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);
+	prs.words = palloc_array(ParsedWord, prs.lenwords);
 
 	/* find all words in indexable column(s) */
 	for (i = 2; i < trigger->tgnargs; i++)
diff --git a/src/backend/utils/adt/tsvector_parser.c b/src/backend/utils/adt/tsvector_parser.c
index e1620d3ed1f..395c3403b9a 100644
--- a/src/backend/utils/adt/tsvector_parser.c
+++ b/src/backend/utils/adt/tsvector_parser.c
@@ -58,7 +58,7 @@ init_tsvector_parser(char *input, int flags, Node *escontext)
 {
 	TSVectorParseState state;
 
-	state = (TSVectorParseState) palloc(sizeof(struct TSVectorParseStateData));
+	state = palloc_object(struct TSVectorParseStateData);
 	state->prsbuf = input;
 	state->bufstart = input;
 	state->len = 32;
@@ -322,13 +322,13 @@ gettoken_tsvector(TSVectorParseState state,
 				if (posalen == 0)
 				{
 					posalen = 4;
-					pos = (WordEntryPos *) palloc(sizeof(WordEntryPos) * posalen);
+					pos = palloc_array(WordEntryPos, posalen); 
 					npos = 0;
 				}
 				else if (npos + 1 >= posalen)
 				{
 					posalen *= 2;
-					pos = (WordEntryPos *) repalloc(pos, sizeof(WordEntryPos) * posalen);
+					pos = repalloc_array(pos, WordEntryPos, posalen);
 				}
 				npos++;
 				WEP_SETPOS(pos[npos - 1], LIMITPOS(atoi(state->prsbuf)));
diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c
index e5f27ff892b..493aac32799 100644
--- a/src/backend/utils/adt/uuid.c
+++ b/src/backend/utils/adt/uuid.c
@@ -80,7 +80,7 @@ uuid_in(PG_FUNCTION_ARGS)
 	char	   *uuid_str = PG_GETARG_CSTRING(0);
 	pg_uuid_t  *uuid;
 
-	uuid = (pg_uuid_t *) palloc(sizeof(*uuid));
+	uuid = palloc_object(pg_uuid_t);
 	string_to_uuid(uuid_str, uuid, fcinfo->context);
 	PG_RETURN_UUID_P(uuid);
 }
@@ -288,7 +288,7 @@ uuid_sortsupport(PG_FUNCTION_ARGS)
 
 		oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
 
-		uss = palloc(sizeof(uuid_sortsupport_state));
+		uss = palloc_object(uuid_sortsupport_state);
 		uss->input_count = 0;
 		uss->estimating = true;
 		initHyperLogLog(&uss->abbr_card, 10);
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 3894457ab40..c26d57ea2ec 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -1692,7 +1692,7 @@ varstr_sortsupport(SortSupport ssup, Oid typid, Oid collid)
 	 */
 	if (abbreviate || !collate_c)
 	{
-		sss = palloc(sizeof(VarStringSortSupport));
+		sss = palloc_object(VarStringSortSupport);
 		sss->buf1 = palloc(TEXTBUFLEN);
 		sss->buflen1 = TEXTBUFLEN;
 		sss->buf2 = palloc(TEXTBUFLEN);
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 41e775570ec..c8ab9d61c68 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -1255,7 +1255,7 @@ pg_xml_init(PgXmlStrictness strictness)
 	pg_xml_init_library();
 
 	/* Create error handling context structure */
-	errcxt = (PgXmlErrorContext *) palloc(sizeof(PgXmlErrorContext));
+	errcxt = palloc_object(PgXmlErrorContext);
 	errcxt->magic = ERRCXT_MAGIC;
 	errcxt->strictness = strictness;
 	errcxt->err_occurred = false;
@@ -4733,10 +4733,10 @@ XmlTableInitOpaque(TableFuncScanState *state, int natts)
 	XmlTableBuilderData *xtCxt;
 	PgXmlErrorContext *xmlerrcxt;
 
-	xtCxt = palloc0(sizeof(XmlTableBuilderData));
+	xtCxt = palloc0_object(XmlTableBuilderData);
 	xtCxt->magic = XMLTABLE_CONTEXT_MAGIC;
 	xtCxt->natts = natts;
-	xtCxt->xpathscomp = palloc0(sizeof(xmlXPathCompExprPtr) * natts);
+	xtCxt->xpathscomp = palloc0_array(xmlXPathCompExprPtr, natts);
 
 	xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
 
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 02ae7d5a831..84f1f80607e 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -920,7 +920,7 @@ InitCatCache(int id,
 	 */
 	if (CacheHdr == NULL)
 	{
-		CacheHdr = (CatCacheHeader *) palloc(sizeof(CatCacheHeader));
+		CacheHdr = palloc_object(CatCacheHeader);
 		slist_init(&CacheHdr->ch_caches);
 		CacheHdr->ch_ntup = 0;
 #ifdef CATCACHE_STATS
@@ -2243,7 +2243,7 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, Datum *arguments,
 	{
 		/* Set up keys for a negative cache entry */
 		oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-		ct = (CatCTup *) palloc(sizeof(CatCTup));
+		ct = palloc_object(CatCTup);
 
 		/*
 		 * Store keys - they'll point into separately allocated memory if not
diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index b9d5a5998be..7f03c94a974 100644
--- a/src/backend/utils/cache/evtcache.c
+++ b/src/backend/utils/cache/evtcache.c
@@ -172,7 +172,7 @@ BuildEventTriggerCache(void)
 		oldcontext = MemoryContextSwitchTo(EventTriggerCacheContext);
 
 		/* Allocate new cache item. */
-		item = palloc0(sizeof(EventTriggerCacheItem));
+		item = palloc0_object(EventTriggerCacheItem);
 		item->fnoid = form->evtfoid;
 		item->enabled = form->evtenabled;
 
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 06f736cab45..868f8f6188f 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -758,7 +758,7 @@ PrepareInplaceInvalidationState(void)
 	Assert(inplaceInvalInfo == NULL);
 
 	/* gone after WAL insertion CritSection ends, so use current context */
-	myInfo = (InvalidationInfo *) palloc0(sizeof(InvalidationInfo));
+	myInfo = palloc0_object(InvalidationInfo);
 
 	/* Stash our messages past end of the transactional messages, if any. */
 	if (transInvalInfo != NULL)
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index fa7cd7e06a7..5aa7a26d95c 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -702,8 +702,7 @@ get_op_index_interpretation(Oid opno)
 		if (cmptype == COMPARE_INVALID)
 			continue;
 
-		thisresult = (OpIndexInterpretation *)
-			palloc(sizeof(OpIndexInterpretation));
+		thisresult = palloc_object(OpIndexInterpretation);
 		thisresult->opfamily_id = op_form->amopfamily;
 		thisresult->cmptype = cmptype;
 		thisresult->oplefttype = op_form->amoplefttype;
@@ -748,8 +747,7 @@ get_op_index_interpretation(Oid opno)
 					continue;
 
 				/* OK, report it as COMPARE_NE */
-				thisresult = (OpIndexInterpretation *)
-					palloc(sizeof(OpIndexInterpretation));
+				thisresult = palloc_object(OpIndexInterpretation);
 				thisresult->opfamily_id = op_form->amopfamily;
 				thisresult->cmptype = COMPARE_NE;
 				thisresult->oplefttype = op_form->amoplefttype;
diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c
index f5d7d70def0..97f2ce33efe 100644
--- a/src/backend/utils/cache/partcache.c
+++ b/src/backend/utils/cache/partcache.c
@@ -167,18 +167,18 @@ RelationBuildPartitionKey(Relation relation)
 
 	/* Allocate assorted arrays in the partkeycxt, which we'll fill below */
 	oldcxt = MemoryContextSwitchTo(partkeycxt);
-	key->partattrs = (AttrNumber *) palloc0(key->partnatts * sizeof(AttrNumber));
-	key->partopfamily = (Oid *) palloc0(key->partnatts * sizeof(Oid));
-	key->partopcintype = (Oid *) palloc0(key->partnatts * sizeof(Oid));
-	key->partsupfunc = (FmgrInfo *) palloc0(key->partnatts * sizeof(FmgrInfo));
-
-	key->partcollation = (Oid *) palloc0(key->partnatts * sizeof(Oid));
-	key->parttypid = (Oid *) palloc0(key->partnatts * sizeof(Oid));
-	key->parttypmod = (int32 *) palloc0(key->partnatts * sizeof(int32));
-	key->parttyplen = (int16 *) palloc0(key->partnatts * sizeof(int16));
-	key->parttypbyval = (bool *) palloc0(key->partnatts * sizeof(bool));
-	key->parttypalign = (char *) palloc0(key->partnatts * sizeof(char));
-	key->parttypcoll = (Oid *) palloc0(key->partnatts * sizeof(Oid));
+	key->partattrs = (AttrNumber *) palloc0_array(AttrNumber, key->partnatts);
+	key->partopfamily = (Oid *) palloc0_array(Oid, key->partnatts);
+	key->partopcintype = (Oid *) palloc0_array(Oid, key->partnatts);
+	key->partsupfunc = (FmgrInfo *) palloc0_array(FmgrInfo, key->partnatts);
+
+	key->partcollation = (Oid *) palloc0_array(Oid, key->partnatts);
+	key->parttypid = (Oid *) palloc0_array(Oid, key->partnatts);
+	key->parttypmod = (int32 *) palloc0_array(int32, key->partnatts);
+	key->parttyplen = (int16 *) palloc0_array(int16, key->partnatts);
+	key->parttypbyval = (bool *) palloc0_array(bool, key->partnatts);
+	key->parttypalign = (char *) palloc0_array(char, key->partnatts);
+	key->parttypcoll = (Oid *) palloc0_array(Oid, key->partnatts);
 	MemoryContextSwitchTo(oldcxt);
 
 	/* determine support function number to search for */
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 6661d2c6b73..45261caaf47 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -207,7 +207,7 @@ CreateCachedPlan(RawStmt *raw_parse_tree,
 	 */
 	oldcxt = MemoryContextSwitchTo(source_context);
 
-	plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
+	plansource = palloc0_object(CachedPlanSource);
 	plansource->magic = CACHEDPLANSOURCE_MAGIC;
 	plansource->raw_parse_tree = copyObject(raw_parse_tree);
 	plansource->analyzed_parse_tree = NULL;
@@ -307,7 +307,7 @@ CreateOneShotCachedPlan(RawStmt *raw_parse_tree,
 	 * Create and fill the CachedPlanSource struct within the caller's memory
 	 * context.  Most fields are just left empty for the moment.
 	 */
-	plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
+	plansource = palloc0_object(CachedPlanSource);
 	plansource->magic = CACHEDPLANSOURCE_MAGIC;
 	plansource->raw_parse_tree = raw_parse_tree;
 	plansource->analyzed_parse_tree = NULL;
@@ -469,7 +469,7 @@ CompleteCachedPlan(CachedPlanSource *plansource,
 
 	if (num_params > 0)
 	{
-		plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
+		plansource->param_types = palloc_array(Oid, num_params);
 		memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
 	}
 	else
@@ -1119,7 +1119,7 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
 	/*
 	 * Create and fill the CachedPlan struct within the new context.
 	 */
-	plan = (CachedPlan *) palloc(sizeof(CachedPlan));
+	plan = palloc_object(CachedPlan);
 	plan->magic = CACHEDPLAN_MAGIC;
 	plan->stmt_list = plist;
 
@@ -1691,7 +1691,7 @@ CopyCachedPlan(CachedPlanSource *plansource)
 
 	oldcxt = MemoryContextSwitchTo(source_context);
 
-	newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
+	newsource = palloc0_object(CachedPlanSource);
 	newsource->magic = CACHEDPLANSOURCE_MAGIC;
 	newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
 	newsource->analyzed_parse_tree = copyObject(plansource->analyzed_parse_tree);
@@ -1700,8 +1700,7 @@ CopyCachedPlan(CachedPlanSource *plansource)
 	newsource->commandTag = plansource->commandTag;
 	if (plansource->num_params > 0)
 	{
-		newsource->param_types = (Oid *)
-			palloc(plansource->num_params * sizeof(Oid));
+		newsource->param_types = palloc_array(Oid, plansource->num_params);
 		memcpy(newsource->param_types, plansource->param_types,
 			   plansource->num_params * sizeof(Oid));
 	}
@@ -1840,7 +1839,7 @@ GetCachedExpression(Node *expr)
 
 	oldcxt = MemoryContextSwitchTo(cexpr_context);
 
-	cexpr = (CachedExpression *) palloc(sizeof(CachedExpression));
+	cexpr = palloc_object(CachedExpression);
 	cexpr->magic = CACHEDEXPR_MAGIC;
 	cexpr->expr = copyObject(expr);
 	cexpr->is_valid = true;
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 915d0bc9084..a4dc1cbe5ae 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -422,7 +422,7 @@ AllocateRelationDesc(Form_pg_class relp)
 	/*
 	 * allocate and zero space for new relation descriptor
 	 */
-	relation = (Relation) palloc0(sizeof(RelationData));
+	relation = palloc0_object(RelationData);
 
 	/* make sure relation is marked as having no open file yet */
 	relation->rd_smgr = NULL;
@@ -1902,7 +1902,7 @@ formrdesc(const char *relationName, Oid relationReltype,
 	/*
 	 * allocate new relation desc, clear all fields of reldesc
 	 */
-	relation = (Relation) palloc0(sizeof(RelationData));
+	relation = palloc0_object(RelationData);
 
 	/* make sure relation is marked as having no open file yet */
 	relation->rd_smgr = NULL;
@@ -1994,7 +1994,7 @@ formrdesc(const char *relationName, Oid relationReltype,
 	/* mark not-null status */
 	if (has_not_null)
 	{
-		TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
+		TupleConstr *constr = palloc0_object(TupleConstr);
 
 		constr->has_not_null = true;
 		relation->rd_att->constr = constr;
@@ -3579,7 +3579,7 @@ RelationBuildLocalRelation(const char *relname,
 	/*
 	 * allocate a new relation descriptor and fill in basic state fields.
 	 */
-	rel = (Relation) palloc0(sizeof(RelationData));
+	rel = palloc0_object(RelationData);
 
 	/* make sure relation is marked as having no open file yet */
 	rel->rd_smgr = NULL;
@@ -3627,7 +3627,7 @@ RelationBuildLocalRelation(const char *relname,
 
 	if (has_not_null)
 	{
-		TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
+		TupleConstr *constr = palloc0_object(TupleConstr);
 
 		constr->has_not_null = true;
 		rel->rd_att->constr = constr;
@@ -5670,9 +5670,9 @@ RelationGetExclusionInfo(Relation indexRelation,
 	indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
 
 	/* Allocate result space in caller context */
-	*operators = ops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	*procs = funcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	*strategies = strats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
+	*operators = ops = palloc_array(Oid, indnkeyatts);
+	*procs = funcs = palloc_array(Oid, indnkeyatts);
+	*strategies = strats = palloc_array(uint16, indnkeyatts);
 
 	/* Quick exit if we have the data cached already */
 	if (indexRelation->rd_exclstrats != NULL)
@@ -5763,9 +5763,9 @@ RelationGetExclusionInfo(Relation indexRelation,
 
 	/* Save a copy of the results in the relcache entry. */
 	oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
-	indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
-	indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
+	indexRelation->rd_exclops = palloc_array(Oid, indnkeyatts);
+	indexRelation->rd_exclprocs = palloc_array(Oid, indnkeyatts);
+	indexRelation->rd_exclstrats = palloc_array(uint16, indnkeyatts);
 	memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
 	memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
 	memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
@@ -5959,7 +5959,7 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
 
 	/* Now save copy of the descriptor in the relcache entry. */
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-	relation->rd_pubdesc = palloc(sizeof(PublicationDesc));
+	relation->rd_pubdesc = palloc_object(PublicationDesc);
 	memcpy(relation->rd_pubdesc, pubdesc, sizeof(PublicationDesc));
 	MemoryContextSwitchTo(oldcxt);
 }
@@ -5967,7 +5967,7 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
 static bytea **
 CopyIndexAttOptions(bytea **srcopts, int natts)
 {
-	bytea	  **opts = palloc(sizeof(*opts) * natts);
+	bytea	  **opts = palloc_array(bytea *, natts);
 
 	for (int i = 0; i < natts; i++)
 	{
@@ -5999,7 +5999,7 @@ RelationGetIndexAttOptions(Relation relation, bool copy)
 		return copy ? CopyIndexAttOptions(opts, natts) : opts;
 
 	/* Get and parse opclass options. */
-	opts = palloc0(sizeof(*opts) * natts);
+	opts = palloc0_array(bytea *, natts);
 
 	for (i = 0; i < natts; i++)
 	{
@@ -6292,7 +6292,7 @@ load_relcache_init_file(bool shared)
 		/* mark not-null status */
 		if (has_not_null)
 		{
-			TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
+			TupleConstr *constr = palloc0_object(TupleConstr);
 
 			constr->has_not_null = true;
 			rel->rd_att->constr = constr;
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index 6a347698edf..0c17d99d021 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -2764,7 +2764,7 @@ load_enum_cache_data(TypeCacheEntry *tcache)
 	 * through.
 	 */
 	maxitems = 64;
-	items = (EnumItem *) palloc(sizeof(EnumItem) * maxitems);
+	items = palloc_array(EnumItem, maxitems);
 	numitems = 0;
 
 	/* Scan pg_enum for the members of the target enum type. */
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 29643c51439..4c5a9283208 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -1774,7 +1774,7 @@ CopyErrorData(void)
 	Assert(CurrentMemoryContext != ErrorContext);
 
 	/* Copy the struct itself */
-	newedata = (ErrorData *) palloc(sizeof(ErrorData));
+	newedata = palloc_object(ErrorData);
 	memcpy(newedata, edata, sizeof(ErrorData));
 
 	/*
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 5f2317211c9..f40879f0617 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -1436,7 +1436,7 @@ get_func_arg_info(HeapTuple procTup,
 								  &elems, NULL, &nelems);
 		if (nelems != numargs)	/* should not happen */
 			elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
-		*p_argnames = (char **) palloc(sizeof(char *) * numargs);
+		*p_argnames = palloc_array(char *, numargs);
 		for (i = 0; i < numargs; i++)
 			(*p_argnames)[i] = TextDatumGetCString(elems[i]);
 	}
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 98f9598cd78..4ed69ac7ba2 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -1260,7 +1260,7 @@ process_startup_options(Port *port, bool am_superuser)
 
 		maxac = 2 + (strlen(port->cmdline_options) + 1) / 2;
 
-		av = (char **) palloc(maxac * sizeof(char *));
+		av = palloc_array(char *, maxac);
 		ac = 0;
 
 		av[ac++] = "postgres";
diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index fb629ed5c8f..0674e51edde 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -1792,7 +1792,7 @@ pgwin32_message_to_UTF16(const char *str, int len, int *utf16len)
 	 */
 	if (codepage != 0)
 	{
-		utf16 = (WCHAR *) palloc(sizeof(WCHAR) * (len + 1));
+		utf16 = palloc_array(WCHAR, len + 1); 
 		dstlen = MultiByteToWideChar(codepage, 0, str, len, utf16, len);
 		utf16[dstlen] = (WCHAR) 0;
 	}
@@ -1816,7 +1816,7 @@ pgwin32_message_to_UTF16(const char *str, int len, int *utf16len)
 		else
 			utf8 = (char *) str;
 
-		utf16 = (WCHAR *) palloc(sizeof(WCHAR) * (len + 1));
+		utf16 = palloc_array(WCHAR, len + 1);
 		dstlen = MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, len);
 		utf16[dstlen] = (WCHAR) 0;
 
diff --git a/src/backend/utils/misc/conffiles.c b/src/backend/utils/misc/conffiles.c
index 23ebad4749b..e702d1d8e31 100644
--- a/src/backend/utils/misc/conffiles.c
+++ b/src/backend/utils/misc/conffiles.c
@@ -108,7 +108,7 @@ GetConfFilesInDir(const char *includedir, const char *calling_file,
 	 * them prior to caller processing the contents.
 	 */
 	size_filenames = 32;
-	filenames = (char **) palloc(size_filenames * sizeof(char *));
+	filenames = palloc_array(char *, size_filenames);
 	*num_filenames = 0;
 
 	while ((de = ReadDir(d, directory)) != NULL)
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index 11a1e2a3f9f..c3d0f599be8 100644
--- a/src/backend/utils/misc/guc-file.l
+++ b/src/backend/utils/misc/guc-file.l
@@ -283,7 +283,7 @@ record_config_file_error(const char *errmsg,
 {
 	ConfigVariable *item;
 
-	item = palloc(sizeof *item);
+	item = palloc_object(ConfigVariable);
 	item->name = NULL;
 	item->value = NULL;
 	item->errmsg = pstrdup(errmsg);
@@ -482,7 +482,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
 		else
 		{
 			/* ordinary variable, append to list */
-			item = palloc(sizeof *item);
+			item = palloc_object(ConfigVariable);
 			item->name = opt_name;
 			item->value = opt_value;
 			item->errmsg = NULL;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index c6484aea087..dc5c3351b9c 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -844,7 +844,7 @@ get_guc_variables(int *num_vars)
 	int			i;
 
 	*num_vars = hash_get_num_entries(guc_hashtab);
-	result = palloc(sizeof(struct config_generic *) * *num_vars);
+	result = palloc_array(struct config_generic *, *num_vars);
 
 	/* Extract pointers from the hash table */
 	i = 0;
@@ -5208,7 +5208,7 @@ get_explain_guc_options(int *num)
 	 * While only a fraction of all the GUC variables are marked GUC_EXPLAIN,
 	 * it doesn't seem worth dynamically resizing this array.
 	 */
-	result = palloc(sizeof(struct config_generic *) * hash_get_num_entries(guc_hashtab));
+	result = palloc_array(struct config_generic *, hash_get_num_entries(guc_hashtab));
 
 	/* We need only consider GUCs with source not PGC_S_DEFAULT */
 	dlist_foreach(iter, &guc_nondef_list)
diff --git a/src/backend/utils/misc/injection_point.c b/src/backend/utils/misc/injection_point.c
index d02618c7ffe..54a9fe8e163 100644
--- a/src/backend/utils/misc/injection_point.c
+++ b/src/backend/utils/misc/injection_point.c
@@ -614,7 +614,7 @@ InjectionPointList(void)
 		if (generation % 2 == 0)
 			continue;
 
-		inj_point = (InjectionPointData *) palloc0(sizeof(InjectionPointData));
+		inj_point = palloc0_object(InjectionPointData);
 		inj_point->name = pstrdup(entry->name);
 		inj_point->library = pstrdup(entry->library);
 		inj_point->function = pstrdup(entry->function);
diff --git a/src/backend/utils/misc/queryenvironment.c b/src/backend/utils/misc/queryenvironment.c
index 7bc72dabe67..06983090039 100644
--- a/src/backend/utils/misc/queryenvironment.c
+++ b/src/backend/utils/misc/queryenvironment.c
@@ -38,7 +38,7 @@ struct QueryEnvironment
 QueryEnvironment *
 create_queryEnv(void)
 {
-	return (QueryEnvironment *) palloc0(sizeof(QueryEnvironment));
+	return palloc0_object(QueryEnvironment);
 }
 
 EphemeralNamedRelationMetadata
diff --git a/src/backend/utils/misc/tzparser.c b/src/backend/utils/misc/tzparser.c
index 6aaf7395ba8..d7e84bab981 100644
--- a/src/backend/utils/misc/tzparser.c
+++ b/src/backend/utils/misc/tzparser.c
@@ -466,7 +466,7 @@ load_tzoffsets(const char *filename)
 
 	/* Initialize array at a reasonable size */
 	arraysize = 128;
-	array = (tzEntry *) palloc(arraysize * sizeof(tzEntry));
+	array = palloc_array(tzEntry, arraysize);
 
 	/* Parse the file(s) */
 	n = ParseTzFile(filename, 0, &array, &arraysize, 0);
diff --git a/src/backend/utils/mmgr/dsa.c b/src/backend/utils/mmgr/dsa.c
index 4b6bcffea28..6b37839e925 100644
--- a/src/backend/utils/mmgr/dsa.c
+++ b/src/backend/utils/mmgr/dsa.c
@@ -1330,7 +1330,7 @@ create_internal(void *place, size_t size,
 	 * area.  Other backends will need to obtain their own dsa_area object by
 	 * attaching.
 	 */
-	area = palloc(sizeof(dsa_area));
+	area = palloc_object(dsa_area);
 	area->control = control;
 	area->resowner = CurrentResourceOwner;
 	memset(area->segment_maps, 0, sizeof(dsa_segment_map) * DSA_MAX_SEGMENTS);
@@ -1386,7 +1386,7 @@ attach_internal(void *place, dsm_segment *segment, dsa_handle handle)
 		   (DSA_SEGMENT_HEADER_MAGIC ^ handle ^ 0));
 
 	/* Build the backend-local area object. */
-	area = palloc(sizeof(dsa_area));
+	area = palloc_object(dsa_area);
 	area->control = control;
 	area->resowner = CurrentResourceOwner;
 	memset(&area->segment_maps[0], 0,
diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c
index 452d89a8c0f..42bf50221b8 100644
--- a/src/backend/utils/sort/logtape.c
+++ b/src/backend/utils/sort/logtape.c
@@ -437,7 +437,7 @@ ltsGetPreallocBlock(LogicalTapeSet *lts, LogicalTape *lt)
 	if (lt->prealloc == NULL)
 	{
 		lt->prealloc_size = TAPE_WRITE_PREALLOC_MIN;
-		lt->prealloc = (int64 *) palloc(sizeof(int64) * lt->prealloc_size);
+		lt->prealloc = palloc_array(int64, lt->prealloc_size);
 	}
 	else if (lt->prealloc_size < TAPE_WRITE_PREALLOC_MAX)
 	{
@@ -560,7 +560,7 @@ LogicalTapeSetCreate(bool preallocate, SharedFileSet *fileset, int worker)
 	/*
 	 * Create top-level struct including per-tape LogicalTape structs.
 	 */
-	lts = (LogicalTapeSet *) palloc(sizeof(LogicalTapeSet));
+	lts = palloc_object(LogicalTapeSet);
 	lts->nBlocksAllocated = 0L;
 	lts->nBlocksWritten = 0L;
 	lts->nHoleBlocks = 0L;
@@ -700,7 +700,7 @@ ltsCreateTape(LogicalTapeSet *lts)
 	/*
 	 * Create per-tape struct.  Note we allocate the I/O buffer lazily.
 	 */
-	lt = palloc(sizeof(LogicalTape));
+	lt = palloc_object(LogicalTape);
 	lt->tapeSet = lts;
 	lt->writing = true;
 	lt->frozen = false;
diff --git a/src/backend/utils/sort/sharedtuplestore.c b/src/backend/utils/sort/sharedtuplestore.c
index 1dedbaa29cf..e77d857ff3f 100644
--- a/src/backend/utils/sort/sharedtuplestore.c
+++ b/src/backend/utils/sort/sharedtuplestore.c
@@ -160,7 +160,7 @@ sts_initialize(SharedTuplestore *sts, int participants,
 		sts->participants[i].writing = false;
 	}
 
-	accessor = palloc0(sizeof(SharedTuplestoreAccessor));
+	accessor = palloc0_object(SharedTuplestoreAccessor);
 	accessor->participant = my_participant_number;
 	accessor->sts = sts;
 	accessor->fileset = fileset;
@@ -182,7 +182,7 @@ sts_attach(SharedTuplestore *sts,
 
 	Assert(my_participant_number < sts->nparticipants);
 
-	accessor = palloc0(sizeof(SharedTuplestoreAccessor));
+	accessor = palloc0_object(SharedTuplestoreAccessor);
 	accessor->participant = my_participant_number;
 	accessor->sts = sts;
 	accessor->fileset = fileset;
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 5d4411dc33f..c1fa7a97509 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -673,7 +673,7 @@ tuplesort_begin_common(int workMem, SortCoordinate coordinate, int sortopt)
 	 */
 	oldcontext = MemoryContextSwitchTo(maincontext);
 
-	state = (Tuplesortstate *) palloc0(sizeof(Tuplesortstate));
+	state = palloc0_object(Tuplesortstate);
 
 	if (trace_sort)
 		pg_rusage_init(&state->ru_start);
diff --git a/src/backend/utils/sort/tuplesortvariants.c b/src/backend/utils/sort/tuplesortvariants.c
index 9751a7fc495..079a51c474d 100644
--- a/src/backend/utils/sort/tuplesortvariants.c
+++ b/src/backend/utils/sort/tuplesortvariants.c
@@ -265,7 +265,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
 	Assert(indexRel->rd_rel->relam == BTREE_AM_OID);
 
 	oldcontext = MemoryContextSwitchTo(base->maincontext);
-	arg = (TuplesortClusterArg *) palloc0(sizeof(TuplesortClusterArg));
+	arg = palloc0_object(TuplesortClusterArg);
 
 	if (trace_sort)
 		elog(LOG,
@@ -372,7 +372,7 @@ tuplesort_begin_index_btree(Relation heapRel,
 	int			i;
 
 	oldcontext = MemoryContextSwitchTo(base->maincontext);
-	arg = (TuplesortIndexBTreeArg *) palloc(sizeof(TuplesortIndexBTreeArg));
+	arg = palloc_object(TuplesortIndexBTreeArg);
 
 	if (trace_sort)
 		elog(LOG,
@@ -453,7 +453,7 @@ tuplesort_begin_index_hash(Relation heapRel,
 	TuplesortIndexHashArg *arg;
 
 	oldcontext = MemoryContextSwitchTo(base->maincontext);
-	arg = (TuplesortIndexHashArg *) palloc(sizeof(TuplesortIndexHashArg));
+	arg = palloc_object(TuplesortIndexHashArg);
 
 	if (trace_sort)
 		elog(LOG,
@@ -502,7 +502,7 @@ tuplesort_begin_index_gist(Relation heapRel,
 	int			i;
 
 	oldcontext = MemoryContextSwitchTo(base->maincontext);
-	arg = (TuplesortIndexBTreeArg *) palloc(sizeof(TuplesortIndexBTreeArg));
+	arg = palloc_object(TuplesortIndexBTreeArg);
 
 	if (trace_sort)
 		elog(LOG,
@@ -662,7 +662,7 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
 	bool		typbyval;
 
 	oldcontext = MemoryContextSwitchTo(base->maincontext);
-	arg = (TuplesortDatumArg *) palloc(sizeof(TuplesortDatumArg));
+	arg = palloc_object(TuplesortDatumArg);
 
 	if (trace_sort)
 		elog(LOG,
@@ -694,7 +694,7 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
 	base->tuples = !typbyval;
 
 	/* Prepare SortSupport data */
-	base->sortKeys = (SortSupport) palloc0(sizeof(SortSupportData));
+	base->sortKeys = palloc0_object(SortSupportData);
 
 	base->sortKeys->ssup_cxt = CurrentMemoryContext;
 	base->sortKeys->ssup_collation = sortCollation;
diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c
index c9aecab8d66..def945b0454 100644
--- a/src/backend/utils/sort/tuplestore.c
+++ b/src/backend/utils/sort/tuplestore.c
@@ -257,7 +257,7 @@ tuplestore_begin_common(int eflags, bool interXact, int maxKBytes)
 {
 	Tuplestorestate *state;
 
-	state = (Tuplestorestate *) palloc0(sizeof(Tuplestorestate));
+	state = palloc0_object(Tuplestorestate);
 
 	state->status = TSS_INMEM;
 	state->eflags = eflags;
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 24f73a49d27..40a2e90e071 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -1179,7 +1179,7 @@ ExportSnapshot(Snapshot snapshot)
 	snapshot = CopySnapshot(snapshot);
 
 	oldcxt = MemoryContextSwitchTo(TopTransactionContext);
-	esnap = (ExportedSnapshot *) palloc(sizeof(ExportedSnapshot));
+	esnap = palloc_object(ExportedSnapshot);
 	esnap->snapfile = pstrdup(path);
 	esnap->snapshot = snapshot;
 	exportedSnapshots = lappend(exportedSnapshots, esnap);
diff --git a/src/bin/pg_basebackup/astreamer_inject.c b/src/bin/pg_basebackup/astreamer_inject.c
index 15334e458ad..e77de72f7ac 100644
--- a/src/bin/pg_basebackup/astreamer_inject.c
+++ b/src/bin/pg_basebackup/astreamer_inject.c
@@ -68,7 +68,7 @@ astreamer_recovery_injector_new(astreamer *next,
 {
 	astreamer_recovery_injector *streamer;
 
-	streamer = palloc0(sizeof(astreamer_recovery_injector));
+	streamer = palloc0_object(astreamer_recovery_injector);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_recovery_injector_ops;
 	streamer->base.bbs_next = next;
diff --git a/src/bin/pg_combinebackup/load_manifest.c b/src/bin/pg_combinebackup/load_manifest.c
index 8e0d04a26a6..44db0d2b164 100644
--- a/src/bin/pg_combinebackup/load_manifest.c
+++ b/src/bin/pg_combinebackup/load_manifest.c
@@ -298,7 +298,7 @@ combinebackup_per_wal_range_cb(JsonManifestParseContext *context,
 	manifest_wal_range *range;
 
 	/* Allocate and initialize a struct describing this WAL range. */
-	range = palloc(sizeof(manifest_wal_range));
+	range = palloc_object(manifest_wal_range);
 	range->tli = tli;
 	range->start_lsn = start_lsn;
 	range->end_lsn = end_lsn;
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 4e7303ea631..0007e78667f 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -353,7 +353,7 @@ flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables,
 						 tblinfo[i].numParents,
 						 tblinfo[i].dobj.name);
 
-			attachinfo = (TableAttachInfo *) palloc(sizeof(TableAttachInfo));
+			attachinfo = palloc_object(TableAttachInfo);
 			attachinfo->dobj.objType = DO_TABLE_ATTACH;
 			attachinfo->dobj.catId.tableoid = 0;
 			attachinfo->dobj.catId.oid = 0;
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index 2d22723aa91..7ff9dbd1a33 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -972,7 +972,7 @@ char *
 generate_restrict_key(void)
 {
 	uint8		buf[64];
-	char	   *ret = palloc(sizeof(buf));
+	char	   *ret = palloc_array(char, sizeof(buf));
 
 	if (!pg_strong_random(buf, sizeof(buf)))
 		return NULL;
diff --git a/src/bin/pg_verifybackup/astreamer_verify.c b/src/bin/pg_verifybackup/astreamer_verify.c
index 33cf67670a7..e503a3ec487 100644
--- a/src/bin/pg_verifybackup/astreamer_verify.c
+++ b/src/bin/pg_verifybackup/astreamer_verify.c
@@ -69,7 +69,7 @@ astreamer_verify_content_new(astreamer *next, verifier_context *context,
 {
 	astreamer_verify *streamer;
 
-	streamer = palloc0(sizeof(astreamer_verify));
+	streamer = palloc0_object(astreamer_verify);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_verify_ops;
 
diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c
index 8d5befa947f..c9b24df7c05 100644
--- a/src/bin/pg_verifybackup/pg_verifybackup.c
+++ b/src/bin/pg_verifybackup/pg_verifybackup.c
@@ -584,7 +584,7 @@ verifybackup_per_wal_range_cb(JsonManifestParseContext *context,
 	manifest_wal_range *range;
 
 	/* Allocate and initialize a struct describing this WAL range. */
-	range = palloc(sizeof(manifest_wal_range));
+	range = palloc_object(manifest_wal_range);
 	range->tli = tli;
 	range->start_lsn = start_lsn;
 	range->end_lsn = end_lsn;
diff --git a/src/bin/scripts/vacuuming.c b/src/bin/scripts/vacuuming.c
index f836f21fb03..9f44cae02ae 100644
--- a/src/bin/scripts/vacuuming.c
+++ b/src/bin/scripts/vacuuming.c
@@ -530,7 +530,7 @@ retrieve_objects(PGconn *conn, vacuumingOptions *vacopts,
 	PQExpBufferData catalog_query;
 	PGresult   *res;
 	SimpleStringListCell *cell;
-	SimpleStringList *found_objs = palloc0(sizeof(SimpleStringList));
+	SimpleStringList *found_objs = palloc0_object(SimpleStringList);
 	bool		objects_listed = false;
 
 	initPQExpBuffer(&catalog_query);
diff --git a/src/common/blkreftable.c b/src/common/blkreftable.c
index b935baf9ad4..29d64a58bad 100644
--- a/src/common/blkreftable.c
+++ b/src/common/blkreftable.c
@@ -234,7 +234,7 @@ static void BlockRefTableFileTerminate(BlockRefTableBuffer *buffer);
 BlockRefTable *
 CreateEmptyBlockRefTable(void)
 {
-	BlockRefTable *brtab = palloc(sizeof(BlockRefTable));
+	BlockRefTable *brtab = palloc_object(BlockRefTable);
 
 	/*
 	 * Even completely empty database has a few hundred relation forks, so it
@@ -497,7 +497,7 @@ WriteBlockRefTable(BlockRefTable *brtab,
 
 		/* Extract entries into serializable format and sort them. */
 		sdata =
-			palloc(brtab->hash->members * sizeof(BlockRefTableSerializedEntry));
+			palloc_array(BlockRefTableSerializedEntry, brtab->hash->members);
 		blockreftable_start_iterate(brtab->hash, &it);
 		while ((brtentry = blockreftable_iterate(brtab->hash, &it)) != NULL)
 		{
@@ -584,7 +584,7 @@ CreateBlockRefTableReader(io_callback_fn read_callback,
 	uint32		magic;
 
 	/* Initialize data structure. */
-	reader = palloc0(sizeof(BlockRefTableReader));
+	reader = palloc0_object(BlockRefTableReader);
 	reader->buffer.io_callback = read_callback;
 	reader->buffer.io_callback_arg = read_callback_arg;
 	reader->error_filename = error_filename;
@@ -660,7 +660,7 @@ BlockRefTableReaderNextRelation(BlockRefTableReader *reader,
 	/* Read chunk size array. */
 	if (reader->chunk_size != NULL)
 		pfree(reader->chunk_size);
-	reader->chunk_size = palloc(sentry.nchunks * sizeof(uint16));
+	reader->chunk_size = palloc_array(uint16, sentry.nchunks);
 	BlockRefTableRead(reader, reader->chunk_size,
 					  sentry.nchunks * sizeof(uint16));
 
@@ -794,7 +794,7 @@ CreateBlockRefTableWriter(io_callback_fn write_callback,
 	uint32		magic = BLOCKREFTABLE_MAGIC;
 
 	/* Prepare buffer and CRC check and save callbacks. */
-	writer = palloc0(sizeof(BlockRefTableWriter));
+	writer = palloc0_object(BlockRefTableWriter);
 	writer->buffer.io_callback = write_callback;
 	writer->buffer.io_callback_arg = write_callback_arg;
 	INIT_CRC32C(writer->buffer.crc);
@@ -874,7 +874,7 @@ DestroyBlockRefTableWriter(BlockRefTableWriter *writer)
 BlockRefTableEntry *
 CreateBlockRefTableEntry(RelFileLocator rlocator, ForkNumber forknum)
 {
-	BlockRefTableEntry *entry = palloc0(sizeof(BlockRefTableEntry));
+	BlockRefTableEntry *entry = palloc0_object(BlockRefTableEntry);
 
 	memcpy(&entry->key.rlocator, &rlocator, sizeof(RelFileLocator));
 	entry->key.forknum = forknum;
@@ -997,10 +997,9 @@ BlockRefTableEntryMarkBlockModified(BlockRefTableEntry *entry,
 
 		if (entry->nchunks == 0)
 		{
-			entry->chunk_size = palloc0(sizeof(uint16) * max_chunks);
-			entry->chunk_usage = palloc0(sizeof(uint16) * max_chunks);
-			entry->chunk_data =
-				palloc0(sizeof(BlockRefTableChunk) * max_chunks);
+			entry->chunk_size = palloc0_array(uint16, max_chunks); 
+			entry->chunk_usage = palloc0_array(uint16, max_chunks);
+			entry->chunk_data = palloc0_array(BlockRefTableChunk, max_chunks);
 		}
 		else
 		{
@@ -1029,7 +1028,7 @@ BlockRefTableEntryMarkBlockModified(BlockRefTableEntry *entry,
 	if (entry->chunk_size[chunkno] == 0)
 	{
 		entry->chunk_data[chunkno] =
-			palloc(sizeof(uint16) * INITIAL_ENTRIES_PER_CHUNK);
+			palloc_array(uint16, INITIAL_ENTRIES_PER_CHUNK);
 		entry->chunk_size[chunkno] = INITIAL_ENTRIES_PER_CHUNK;
 		entry->chunk_data[chunkno][0] = chunkoffset;
 		entry->chunk_usage[chunkno] = 1;
diff --git a/src/common/parse_manifest.c b/src/common/parse_manifest.c
index 58e0948100f..cc5fa0e5e07 100644
--- a/src/common/parse_manifest.c
+++ b/src/common/parse_manifest.c
@@ -132,8 +132,8 @@ json_parse_manifest_incremental_init(JsonManifestParseContext *context)
 	JsonManifestParseState *parse;
 	pg_cryptohash_ctx *manifest_ctx;
 
-	incstate = palloc(sizeof(JsonManifestParseIncrementalState));
-	parse = palloc(sizeof(JsonManifestParseState));
+	incstate = palloc_object(JsonManifestParseIncrementalState);
+	parse = palloc_object(JsonManifestParseState);
 
 	parse->context = context;
 	parse->state = JM_EXPECT_TOPLEVEL_START;
diff --git a/src/common/pgfnames.c b/src/common/pgfnames.c
index 8fb79105714..591535a24b8 100644
--- a/src/common/pgfnames.c
+++ b/src/common/pgfnames.c
@@ -49,7 +49,7 @@ pgfnames(const char *path)
 		return NULL;
 	}
 
-	filenames = (char **) palloc(fnsize * sizeof(char *));
+	filenames = palloc_array(char *, fnsize);
 
 	while (errno = 0, (file = readdir(dir)) != NULL)
 	{
@@ -58,8 +58,7 @@ pgfnames(const char *path)
 			if (numnames + 1 >= fnsize)
 			{
 				fnsize *= 2;
-				filenames = (char **) repalloc(filenames,
-											   fnsize * sizeof(char *));
+				filenames = repalloc_array(filenames, char *, fnsize);
 			}
 			filenames[numnames++] = pstrdup(file->d_name);
 		}
diff --git a/src/common/rmtree.c b/src/common/rmtree.c
index 2f364f84ae5..47cd0a4d8a1 100644
--- a/src/common/rmtree.c
+++ b/src/common/rmtree.c
@@ -64,7 +64,7 @@ rmtree(const char *path, bool rmtopdir)
 		return false;
 	}
 
-	dirnames = (char **) palloc(sizeof(char *) * dirnames_capacity);
+	dirnames = palloc_array(char *, dirnames_capacity);
 
 	while (errno = 0, (de = readdir(dir)))
 	{
diff --git a/src/common/stringinfo.c b/src/common/stringinfo.c
index 22d03807697..a3e77088f8e 100644
--- a/src/common/stringinfo.c
+++ b/src/common/stringinfo.c
@@ -57,7 +57,7 @@ initStringInfoInternal(StringInfo str, int initsize)
 static inline StringInfo
 makeStringInfoInternal(int initsize)
 {
-	StringInfo	res = (StringInfo) palloc(sizeof(StringInfoData));
+	StringInfo	res = palloc_object(StringInfoData);
 
 	initStringInfoInternal(res, initsize);
 	return res;
diff --git a/src/fe_utils/astreamer_file.c b/src/fe_utils/astreamer_file.c
index c6856285086..940f0f5a1a6 100644
--- a/src/fe_utils/astreamer_file.c
+++ b/src/fe_utils/astreamer_file.c
@@ -82,7 +82,7 @@ astreamer_plain_writer_new(char *pathname, FILE *file)
 {
 	astreamer_plain_writer *streamer;
 
-	streamer = palloc0(sizeof(astreamer_plain_writer));
+	streamer = palloc0_object(astreamer_plain_writer);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_plain_writer_ops;
 
@@ -189,7 +189,7 @@ astreamer_extractor_new(const char *basepath,
 {
 	astreamer_extractor *streamer;
 
-	streamer = palloc0(sizeof(astreamer_extractor));
+	streamer = palloc0_object(astreamer_extractor);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_extractor_ops;
 	streamer->basepath = pstrdup(basepath);
diff --git a/src/fe_utils/astreamer_gzip.c b/src/fe_utils/astreamer_gzip.c
index a395f57edcd..06e2670d363 100644
--- a/src/fe_utils/astreamer_gzip.c
+++ b/src/fe_utils/astreamer_gzip.c
@@ -102,7 +102,7 @@ astreamer_gzip_writer_new(char *pathname, FILE *file,
 #ifdef HAVE_LIBZ
 	astreamer_gzip_writer *streamer;
 
-	streamer = palloc0(sizeof(astreamer_gzip_writer));
+	streamer = palloc0_object(astreamer_gzip_writer);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_gzip_writer_ops;
 
@@ -241,7 +241,7 @@ astreamer_gzip_decompressor_new(astreamer *next)
 
 	Assert(next != NULL);
 
-	streamer = palloc0(sizeof(astreamer_gzip_decompressor));
+	streamer = palloc0_object(astreamer_gzip_decompressor);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_gzip_decompressor_ops;
 
diff --git a/src/fe_utils/astreamer_lz4.c b/src/fe_utils/astreamer_lz4.c
index 5f581d1de37..6aead209fd2 100644
--- a/src/fe_utils/astreamer_lz4.c
+++ b/src/fe_utils/astreamer_lz4.c
@@ -78,7 +78,7 @@ astreamer_lz4_compressor_new(astreamer *next, pg_compress_specification *compres
 
 	Assert(next != NULL);
 
-	streamer = palloc0(sizeof(astreamer_lz4_frame));
+	streamer = palloc0_object(astreamer_lz4_frame);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_lz4_compressor_ops;
 
@@ -282,7 +282,7 @@ astreamer_lz4_decompressor_new(astreamer *next)
 
 	Assert(next != NULL);
 
-	streamer = palloc0(sizeof(astreamer_lz4_frame));
+	streamer = palloc0_object(astreamer_lz4_frame);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_lz4_decompressor_ops;
 
diff --git a/src/fe_utils/astreamer_tar.c b/src/fe_utils/astreamer_tar.c
index 088e2357920..896f8ab4970 100644
--- a/src/fe_utils/astreamer_tar.c
+++ b/src/fe_utils/astreamer_tar.c
@@ -94,7 +94,7 @@ astreamer_tar_parser_new(astreamer *next)
 {
 	astreamer_tar_parser *streamer;
 
-	streamer = palloc0(sizeof(astreamer_tar_parser));
+	streamer = palloc0_object(astreamer_tar_parser);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_tar_parser_ops;
 	streamer->base.bbs_next = next;
@@ -357,7 +357,7 @@ astreamer_tar_archiver_new(astreamer *next)
 {
 	astreamer_tar_archiver *streamer;
 
-	streamer = palloc0(sizeof(astreamer_tar_archiver));
+	streamer = palloc0_object(astreamer_tar_archiver);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_tar_archiver_ops;
 	streamer->base.bbs_next = next;
@@ -463,7 +463,7 @@ astreamer_tar_terminator_new(astreamer *next)
 {
 	astreamer  *streamer;
 
-	streamer = palloc0(sizeof(astreamer));
+	streamer = palloc0_object(astreamer);
 	*((const astreamer_ops **) &streamer->bbs_ops) =
 		&astreamer_tar_terminator_ops;
 	streamer->bbs_next = next;
diff --git a/src/fe_utils/astreamer_zstd.c b/src/fe_utils/astreamer_zstd.c
index bacdcc150c4..6666f1abeb3 100644
--- a/src/fe_utils/astreamer_zstd.c
+++ b/src/fe_utils/astreamer_zstd.c
@@ -75,7 +75,7 @@ astreamer_zstd_compressor_new(astreamer *next, pg_compress_specification *compre
 
 	Assert(next != NULL);
 
-	streamer = palloc0(sizeof(astreamer_zstd_frame));
+	streamer = palloc0_object(astreamer_zstd_frame);
 
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_zstd_compressor_ops;
@@ -266,7 +266,7 @@ astreamer_zstd_decompressor_new(astreamer *next)
 
 	Assert(next != NULL);
 
-	streamer = palloc0(sizeof(astreamer_zstd_frame));
+	streamer = palloc0_object(astreamer_zstd_frame);
 	*((const astreamer_ops **) &streamer->base.bbs_ops) =
 		&astreamer_zstd_decompressor_ops;
 
diff --git a/src/include/lib/radixtree.h b/src/include/lib/radixtree.h
index ead7500fe13..adf81c6f0eb 100644
--- a/src/include/lib/radixtree.h
+++ b/src/include/lib/radixtree.h
@@ -1825,7 +1825,7 @@ RT_CREATE(MemoryContext ctx)
 	dsa_pointer dp;
 #endif
 
-	tree = (RT_RADIX_TREE *) palloc0(sizeof(RT_RADIX_TREE));
+	tree = palloc0_object(RT_RADIX_TREE);
 
 #ifdef RT_SHMEM
 	tree->dsa = dsa;
@@ -1835,7 +1835,7 @@ RT_CREATE(MemoryContext ctx)
 	tree->ctl->magic = RT_RADIX_TREE_MAGIC;
 	LWLockInitialize(&tree->ctl->lock, tranche_id);
 #else
-	tree->ctl = (RT_RADIX_TREE_CONTROL *) palloc0(sizeof(RT_RADIX_TREE_CONTROL));
+	tree->ctl = palloc0_object(RT_RADIX_TREE_CONTROL);
 
 	/* Create a slab context for each size class */
 	for (int i = 0; i < RT_NUM_SIZE_CLASSES; i++)
@@ -1868,7 +1868,7 @@ RT_ATTACH(dsa_area *dsa, RT_HANDLE handle)
 	RT_RADIX_TREE *tree;
 	dsa_pointer control;
 
-	tree = (RT_RADIX_TREE *) palloc0(sizeof(RT_RADIX_TREE));
+	tree = palloc0_object(RT_RADIX_TREE);
 
 	/* Find the control object in shared memory */
 	control = handle;
@@ -2057,7 +2057,7 @@ RT_BEGIN_ITERATE(RT_RADIX_TREE * tree)
 	RT_ITER    *iter;
 	RT_CHILD_PTR root;
 
-	iter = (RT_ITER *) palloc0(sizeof(RT_ITER));
+	iter = palloc0_object(RT_ITER);
 	iter->tree = tree;
 
 	Assert(RT_PTR_ALLOC_IS_VALID(tree->ctl->root));
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 73ba1748fe0..02eced3b2c5 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1082,8 +1082,8 @@ plperl_build_tuple_result(HV *perlhash, TupleDesc td)
 	HE		   *he;
 	HeapTuple	tup;
 
-	values = palloc0(sizeof(Datum) * td->natts);
-	nulls = palloc(sizeof(bool) * td->natts);
+	values = palloc0_array(Datum, td->natts);
+	nulls = palloc_array(bool, td->natts);
 	memset(nulls, true, sizeof(bool) * td->natts);
 
 	hv_iterinit(perlhash);
@@ -1502,7 +1502,7 @@ plperl_ref_from_pg_array(Datum arg, Oid typid)
 	 * Currently we make no effort to cache any of the stuff we look up here,
 	 * which is bad.
 	 */
-	info = palloc0(sizeof(plperl_array_info));
+	info = palloc0_object(plperl_array_info);
 
 	/* get element type information, including output conversion function */
 	get_type_io_data(elementtype, IOFunc_output,
@@ -1538,7 +1538,7 @@ plperl_ref_from_pg_array(Datum arg, Oid typid)
 						  &nitems);
 
 		/* Get total number of elements in each dimension */
-		info->nelems = palloc(sizeof(int) * info->ndims);
+		info->nelems = palloc_array(int, info->ndims);
 		info->nelems[0] = nitems;
 		for (i = 1; i < info->ndims; i++)
 			info->nelems[i] = info->nelems[i - 1] / dims[i - 1];
@@ -2797,7 +2797,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
 		 * struct prodesc and subsidiary data must all live in proc_cxt.
 		 ************************************************************/
 		oldcontext = MemoryContextSwitchTo(proc_cxt);
-		prodesc = (plperl_proc_desc *) palloc0(sizeof(plperl_proc_desc));
+		prodesc = palloc0_object(plperl_proc_desc);
 		prodesc->proname = pstrdup(NameStr(procStruct->proname));
 		MemoryContextSetIdentifier(proc_cxt, prodesc->proname);
 		prodesc->fn_cxt = proc_cxt;
@@ -3596,7 +3596,7 @@ plperl_spi_prepare(char *query, int argc, SV **argv)
 										 "PL/Perl spi_prepare query",
 										 ALLOCSET_SMALL_SIZES);
 		MemoryContextSwitchTo(plan_cxt);
-		qdesc = (plperl_query_desc *) palloc0(sizeof(plperl_query_desc));
+		qdesc = palloc0_object(plperl_query_desc);
 		snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
 		qdesc->plan_cxt = plan_cxt;
 		qdesc->nargs = argc;
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index f6976689a69..4d90a0c2f06 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -298,8 +298,8 @@ plpgsql_compile_callback(FunctionCallInfo fcinfo,
 											   forValidator,
 											   plpgsql_error_funcname);
 
-			in_arg_varnos = (int *) palloc(numargs * sizeof(int));
-			out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
+			in_arg_varnos = palloc_array(int, numargs);
+			out_arg_variables = palloc_array(PLpgSQL_variable *, numargs);
 
 			MemoryContextSwitchTo(func_cxt);
 
@@ -772,7 +772,7 @@ plpgsql_compile_inline(char *proc_source)
 	plpgsql_check_syntax = check_function_bodies;
 
 	/* Function struct does not live past current statement */
-	function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
+	function = palloc0_object(PLpgSQL_function);
 
 	plpgsql_curr_compile = function;
 
@@ -954,7 +954,7 @@ add_dummy_return(PLpgSQL_function *function)
 	{
 		PLpgSQL_stmt_block *new;
 
-		new = palloc0(sizeof(PLpgSQL_stmt_block));
+		new = palloc0_object(PLpgSQL_stmt_block);
 		new->cmd_type = PLPGSQL_STMT_BLOCK;
 		new->stmtid = ++function->nstatements;
 		new->body = list_make1(function->action);
@@ -966,7 +966,7 @@ add_dummy_return(PLpgSQL_function *function)
 	{
 		PLpgSQL_stmt_return *new;
 
-		new = palloc0(sizeof(PLpgSQL_stmt_return));
+		new = palloc0_object(PLpgSQL_stmt_return);
 		new->cmd_type = PLPGSQL_STMT_RETURN;
 		new->stmtid = ++function->nstatements;
 		new->expr = NULL;
@@ -1776,7 +1776,7 @@ plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
 				/* Ordinary scalar datatype */
 				PLpgSQL_var *var;
 
-				var = palloc0(sizeof(PLpgSQL_var));
+				var = palloc0_object(PLpgSQL_var);
 				var->dtype = PLPGSQL_DTYPE_VAR;
 				var->refname = pstrdup(refname);
 				var->lineno = lineno;
@@ -1833,7 +1833,7 @@ plpgsql_build_record(const char *refname, int lineno,
 {
 	PLpgSQL_rec *rec;
 
-	rec = palloc0(sizeof(PLpgSQL_rec));
+	rec = palloc0_object(PLpgSQL_rec);
 	rec->dtype = PLPGSQL_DTYPE_REC;
 	rec->refname = pstrdup(refname);
 	rec->lineno = lineno;
@@ -1859,14 +1859,14 @@ build_row_from_vars(PLpgSQL_variable **vars, int numvars)
 	PLpgSQL_row *row;
 	int			i;
 
-	row = palloc0(sizeof(PLpgSQL_row));
+	row = palloc0_object(PLpgSQL_row);
 	row->dtype = PLPGSQL_DTYPE_ROW;
 	row->refname = "(unnamed row)";
 	row->lineno = -1;
 	row->rowtupdesc = CreateTemplateTupleDesc(numvars);
 	row->nfields = numvars;
-	row->fieldnames = palloc(numvars * sizeof(char *));
-	row->varnos = palloc(numvars * sizeof(int));
+	row->fieldnames = palloc_array(char *, numvars);
+	row->varnos = palloc_array(int, numvars);
 
 	for (i = 0; i < numvars; i++)
 	{
@@ -1940,7 +1940,7 @@ plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
 	}
 
 	/* nope, so make a new one */
-	recfield = palloc0(sizeof(PLpgSQL_recfield));
+	recfield = palloc0_object(PLpgSQL_recfield);
 	recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
 	recfield->fieldname = pstrdup(fldname);
 	recfield->recparentno = rec->dno;
@@ -2004,7 +2004,7 @@ build_datatype(HeapTuple typeTup, int32 typmod,
 				 errmsg("type \"%s\" is only a shell",
 						NameStr(typeStruct->typname))));
 
-	typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
+	typ = palloc_object(PLpgSQL_type);
 
 	typ->typname = pstrdup(NameStr(typeStruct->typname));
 	typ->typoid = typeStruct->oid;
@@ -2184,7 +2184,7 @@ plpgsql_parse_err_condition(char *condname)
 
 	if (strcmp(condname, "others") == 0)
 	{
-		new = palloc(sizeof(PLpgSQL_condition));
+		new = palloc_object(PLpgSQL_condition);
 		new->sqlerrstate = PLPGSQL_OTHERS;
 		new->condname = condname;
 		new->next = NULL;
@@ -2196,7 +2196,7 @@ plpgsql_parse_err_condition(char *condname)
 	{
 		if (strcmp(condname, exception_label_map[i].label) == 0)
 		{
-			new = palloc(sizeof(PLpgSQL_condition));
+			new = palloc_object(PLpgSQL_condition);
 			new->sqlerrstate = exception_label_map[i].sqlerrstate;
 			new->condname = condname;
 			new->next = prev;
@@ -2258,7 +2258,7 @@ plpgsql_finish_datums(PLpgSQL_function *function)
 	int			i;
 
 	function->ndatums = plpgsql_nDatums;
-	function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
+	function->datums = palloc_array(PLpgSQL_datum *, plpgsql_nDatums);
 	for (i = 0; i < plpgsql_nDatums; i++)
 	{
 		function->datums[i] = plpgsql_Datums[i];
@@ -2323,7 +2323,7 @@ plpgsql_add_initdatums(int **varnos)
 	{
 		if (n > 0)
 		{
-			*varnos = (int *) palloc(sizeof(int) * n);
+			*varnos = palloc_array(int, n);
 
 			n = 0;
 			for (i = datums_last; i < plpgsql_nDatums; i++)
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index d19425b7a71..63598aba8a8 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -1318,8 +1318,7 @@ copy_plpgsql_datums(PLpgSQL_execstate *estate,
 	int			i;
 
 	/* Allocate local datum-pointer array */
-	estate->datums = (PLpgSQL_datum **)
-		palloc(sizeof(PLpgSQL_datum *) * ndatums);
+	estate->datums = palloc_array(PLpgSQL_datum *, ndatums);
 
 	/*
 	 * To reduce palloc overhead, we make a single palloc request for all the
@@ -1497,7 +1496,7 @@ plpgsql_fulfill_promise(PLpgSQL_execstate *estate,
 				int			lbs[1];
 				int			i;
 
-				elems = palloc(sizeof(Datum) * nelems);
+				elems = palloc_array(Datum, nelems);
 				for (i = 0; i < nelems; i++)
 					elems[i] = CStringGetTextDatum(estate->trigdata->tg_trigger->tgargs[i]);
 				dims[0] = nelems;
@@ -2340,11 +2339,11 @@ make_callstmt_target(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 	 */
 	MemoryContextSwitchTo(estate->func->fn_cxt);
 
-	row = (PLpgSQL_row *) palloc0(sizeof(PLpgSQL_row));
+	row = palloc0_object(PLpgSQL_row);
 	row->dtype = PLPGSQL_DTYPE_ROW;
 	row->refname = "(unnamed row)";
 	row->lineno = -1;
-	row->varnos = (int *) palloc(numargs * sizeof(int));
+	row->varnos = palloc_array(int, numargs);
 
 	MemoryContextSwitchTo(get_eval_mcontext(estate));
 
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 17568d82554..cd1fe5a509f 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -426,7 +426,7 @@ pl_block		: decl_sect K_BEGIN proc_sect exception_sect K_END opt_label
 					{
 						PLpgSQL_stmt_block *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_block));
+						new = palloc0_object(PLpgSQL_stmt_block);
 
 						new->cmd_type	= PLPGSQL_STMT_BLOCK;
 						new->lineno		= plpgsql_location_to_lineno(@2, yyscanner);
@@ -606,14 +606,14 @@ decl_cursor_args :
 						int			i;
 						ListCell   *l;
 
-						new = palloc0(sizeof(PLpgSQL_row));
+						new = palloc0_object(PLpgSQL_row);
 						new->dtype = PLPGSQL_DTYPE_ROW;
 						new->refname = "(unnamed row)";
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->rowtupdesc = NULL;
 						new->nfields = list_length($2);
-						new->fieldnames = palloc(new->nfields * sizeof(char *));
-						new->varnos = palloc(new->nfields * sizeof(int));
+						new->fieldnames = palloc_array(char *, new->nfields);
+						new->varnos = palloc_array(int, new->nfields);
 
 						i = 0;
 						foreach (l, $2)
@@ -898,7 +898,7 @@ stmt_perform	: K_PERFORM
 						PLpgSQL_stmt_perform *new;
 						int			startloc;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_perform));
+						new = palloc0_object(PLpgSQL_stmt_perform);
 						new->cmd_type = PLPGSQL_STMT_PERFORM;
 						new->lineno   = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -934,7 +934,7 @@ stmt_call		: K_CALL
 					{
 						PLpgSQL_stmt_call *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_call));
+						new = palloc0_object(PLpgSQL_stmt_call);
 						new->cmd_type = PLPGSQL_STMT_CALL;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -953,7 +953,7 @@ stmt_call		: K_CALL
 						/* use the same structures as for CALL, for simplicity */
 						PLpgSQL_stmt_call *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_call));
+						new = palloc0_object(PLpgSQL_stmt_call);
 						new->cmd_type = PLPGSQL_STMT_CALL;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -992,7 +992,7 @@ stmt_assign		: T_DATUM
 						}
 
 						check_assignable($1.datum, @1, yyscanner);
-						new = palloc0(sizeof(PLpgSQL_stmt_assign));
+						new = palloc0_object(PLpgSQL_stmt_assign);
 						new->cmd_type = PLPGSQL_STMT_ASSIGN;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -1015,7 +1015,7 @@ stmt_getdiag	: K_GET getdiag_area_opt K_DIAGNOSTICS getdiag_list ';'
 						PLpgSQL_stmt_getdiag *new;
 						ListCell	   *lc;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_getdiag));
+						new = palloc0_object(PLpgSQL_stmt_getdiag);
 						new->cmd_type = PLPGSQL_STMT_GETDIAG;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -1101,7 +1101,7 @@ getdiag_list_item : getdiag_target assign_operator getdiag_item
 					{
 						PLpgSQL_diag_item *new;
 
-						new = palloc(sizeof(PLpgSQL_diag_item));
+						new = palloc_object(PLpgSQL_diag_item);
 						new->target = $1->dno;
 						new->kind = $3;
 
@@ -1191,7 +1191,7 @@ stmt_if			: K_IF expr_until_then proc_sect stmt_elsifs stmt_else K_END K_IF ';'
 					{
 						PLpgSQL_stmt_if *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_if));
+						new = palloc0_object(PLpgSQL_stmt_if);
 						new->cmd_type = PLPGSQL_STMT_IF;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -1212,7 +1212,7 @@ stmt_elsifs		:
 					{
 						PLpgSQL_if_elsif *new;
 
-						new = palloc0(sizeof(PLpgSQL_if_elsif));
+						new = palloc0_object(PLpgSQL_if_elsif);
 						new->lineno = plpgsql_location_to_lineno(@2, yyscanner);
 						new->cond = $3;
 						new->stmts = $4;
@@ -1264,7 +1264,7 @@ case_when_list	: case_when_list case_when
 
 case_when		: K_WHEN expr_until_then proc_sect
 					{
-						PLpgSQL_case_when *new = palloc(sizeof(PLpgSQL_case_when));
+						PLpgSQL_case_when *new = palloc_object(PLpgSQL_case_when);
 
 						new->lineno	= plpgsql_location_to_lineno(@1, yyscanner);
 						new->expr = $2;
@@ -1296,7 +1296,7 @@ stmt_loop		: opt_loop_label K_LOOP loop_body
 					{
 						PLpgSQL_stmt_loop *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_loop));
+						new = palloc0_object(PLpgSQL_stmt_loop);
 						new->cmd_type = PLPGSQL_STMT_LOOP;
 						new->lineno = plpgsql_location_to_lineno(@2, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -1314,7 +1314,7 @@ stmt_while		: opt_loop_label K_WHILE expr_until_loop loop_body
 					{
 						PLpgSQL_stmt_while *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_while));
+						new = palloc0_object(PLpgSQL_stmt_while);
 						new->cmd_type = PLPGSQL_STMT_WHILE;
 						new->lineno = plpgsql_location_to_lineno(@2, yyscanner);
 						new->stmtid	= ++plpgsql_curr_compile->nstatements;
@@ -1380,7 +1380,7 @@ for_control		: for_variable K_IN
 														"LOOP or USING",
 														&term, &yylval, &yylloc, yyscanner);
 
-							new = palloc0(sizeof(PLpgSQL_stmt_dynfors));
+							new = palloc0_object(PLpgSQL_stmt_dynfors);
 							new->cmd_type = PLPGSQL_STMT_DYNFORS;
 							new->stmtid = ++plpgsql_curr_compile->nstatements;
 							if ($1.row)
@@ -1426,7 +1426,7 @@ for_control		: for_variable K_IN
 							PLpgSQL_stmt_forc *new;
 							PLpgSQL_var	*cursor = (PLpgSQL_var *) yylval.wdatum.datum;
 
-							new = (PLpgSQL_stmt_forc *) palloc0(sizeof(PLpgSQL_stmt_forc));
+							new = palloc0_object(PLpgSQL_stmt_forc);
 							new->cmd_type = PLPGSQL_STMT_FORC;
 							new->stmtid = ++plpgsql_curr_compile->nstatements;
 							new->curvar = cursor->dno;
@@ -1545,7 +1545,7 @@ for_control		: for_variable K_IN
 																				  NULL),
 														   true);
 
-								new = palloc0(sizeof(PLpgSQL_stmt_fori));
+								new = palloc0_object(PLpgSQL_stmt_fori);
 								new->cmd_type = PLPGSQL_STMT_FORI;
 								new->stmtid	= ++plpgsql_curr_compile->nstatements;
 								new->var = fvar;
@@ -1573,7 +1573,7 @@ for_control		: for_variable K_IN
 								check_sql_expr(expr1->query, expr1->parseMode,
 											   expr1loc, yyscanner);
 
-								new = palloc0(sizeof(PLpgSQL_stmt_fors));
+								new = palloc0_object(PLpgSQL_stmt_fors);
 								new->cmd_type = PLPGSQL_STMT_FORS;
 								new->stmtid = ++plpgsql_curr_compile->nstatements;
 								if ($1.row)
@@ -1675,7 +1675,7 @@ stmt_foreach_a	: opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRA
 					{
 						PLpgSQL_stmt_foreach_a *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_foreach_a));
+						new = palloc0_object(PLpgSQL_stmt_foreach_a);
 						new->cmd_type = PLPGSQL_STMT_FOREACH_A;
 						new->lineno = plpgsql_location_to_lineno(@2, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -1723,7 +1723,7 @@ stmt_exit		: exit_type opt_label opt_exitcond
 					{
 						PLpgSQL_stmt_exit *new;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_exit));
+						new = palloc0_object(PLpgSQL_stmt_exit);
 						new->cmd_type = PLPGSQL_STMT_EXIT;
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
 						new->is_exit = $1;
@@ -1813,7 +1813,7 @@ stmt_raise		: K_RAISE
 						PLpgSQL_stmt_raise *new;
 						int			tok;
 
-						new = palloc(sizeof(PLpgSQL_stmt_raise));
+						new = palloc_object(PLpgSQL_stmt_raise);
 
 						new->cmd_type = PLPGSQL_STMT_RAISE;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
@@ -1959,7 +1959,7 @@ stmt_assert		: K_ASSERT
 						PLpgSQL_stmt_assert	*new;
 						int			tok;
 
-						new = palloc(sizeof(PLpgSQL_stmt_assert));
+						new = palloc_object(PLpgSQL_stmt_assert);
 
 						new->cmd_type = PLPGSQL_STMT_ASSERT;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
@@ -2045,7 +2045,7 @@ stmt_dynexecute : K_EXECUTE
 												  NULL, &endtoken,
 												  &yylval, &yylloc, yyscanner);
 
-						new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
+						new = palloc_object(PLpgSQL_stmt_dynexecute);
 						new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -2103,7 +2103,7 @@ stmt_open		: K_OPEN cursor_variable
 						PLpgSQL_stmt_open *new;
 						int			tok;
 
-						new = palloc0(sizeof(PLpgSQL_stmt_open));
+						new = palloc0_object(PLpgSQL_stmt_open);
 						new->cmd_type = PLPGSQL_STMT_OPEN;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -2229,7 +2229,7 @@ stmt_close		: K_CLOSE cursor_variable ';'
 					{
 						PLpgSQL_stmt_close *new;
 
-						new = palloc(sizeof(PLpgSQL_stmt_close));
+						new = palloc_object(PLpgSQL_stmt_close);
 						new->cmd_type = PLPGSQL_STMT_CLOSE;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -2250,7 +2250,7 @@ stmt_commit		: K_COMMIT opt_transaction_chain ';'
 					{
 						PLpgSQL_stmt_commit *new;
 
-						new = palloc(sizeof(PLpgSQL_stmt_commit));
+						new = palloc_object(PLpgSQL_stmt_commit);
 						new->cmd_type = PLPGSQL_STMT_COMMIT;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -2264,7 +2264,7 @@ stmt_rollback	: K_ROLLBACK opt_transaction_chain ';'
 					{
 						PLpgSQL_stmt_rollback *new;
 
-						new = palloc(sizeof(PLpgSQL_stmt_rollback));
+						new = palloc_object(PLpgSQL_stmt_rollback);
 						new->cmd_type = PLPGSQL_STMT_ROLLBACK;
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -2327,7 +2327,7 @@ exception_sect	:
 						 * current block.
 						 */
 						int			lineno = plpgsql_location_to_lineno(@1, yyscanner);
-						PLpgSQL_exception_block *new = palloc(sizeof(PLpgSQL_exception_block));
+						PLpgSQL_exception_block *new = palloc_object(PLpgSQL_exception_block);
 						PLpgSQL_variable *var;
 
 						plpgsql_curr_compile->has_exception_block = true;
@@ -2375,7 +2375,7 @@ proc_exception	: K_WHEN proc_conditions K_THEN proc_sect
 					{
 						PLpgSQL_exception *new;
 
-						new = palloc0(sizeof(PLpgSQL_exception));
+						new = palloc0_object(PLpgSQL_exception);
 						new->lineno = plpgsql_location_to_lineno(@1, yyscanner);
 						new->conditions = $2;
 						new->action = $4;
@@ -2420,7 +2420,7 @@ proc_condition	: any_identifier
 								if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
 									yyerror(&yylloc, NULL, yyscanner, "invalid SQLSTATE code");
 
-								new = palloc(sizeof(PLpgSQL_condition));
+								new = palloc_object(PLpgSQL_condition);
 								new->sqlerrstate =
 									MAKE_SQLSTATE(sqlstatestr[0],
 												  sqlstatestr[1],
@@ -2671,7 +2671,7 @@ static PLpgSQL_expr *
 make_plpgsql_expr(const char *query,
 				  RawParseMode parsemode)
 {
-	PLpgSQL_expr *expr = palloc0(sizeof(PLpgSQL_expr));
+	PLpgSQL_expr *expr = palloc0_object(PLpgSQL_expr);
 
 	expr->query = pstrdup(query);
 	expr->parseMode = parsemode;
@@ -3181,7 +3181,7 @@ make_execsql_stmt(int firsttoken, int location, PLword *word, YYSTYPE *yylvalp,
 
 	check_sql_expr(expr->query, expr->parseMode, location, yyscanner);
 
-	execsql = palloc0(sizeof(PLpgSQL_stmt_execsql));
+	execsql = palloc0_object(PLpgSQL_stmt_execsql);
 	execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
 	execsql->lineno = plpgsql_location_to_lineno(location, yyscanner);
 	execsql->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -3208,7 +3208,7 @@ read_fetch_direction(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner)
 	 * We create the PLpgSQL_stmt_fetch struct here, but only fill in the
 	 * fields arising from the optional direction clause
 	 */
-	fetch = (PLpgSQL_stmt_fetch *) palloc0(sizeof(PLpgSQL_stmt_fetch));
+	fetch = (PLpgSQL_stmt_fetch *) palloc0_object(PLpgSQL_stmt_fetch);
 	fetch->cmd_type = PLPGSQL_STMT_FETCH;
 	fetch->stmtid = ++plpgsql_curr_compile->nstatements;
 	/* set direction defaults: */
@@ -3360,7 +3360,7 @@ make_return_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yysc
 {
 	PLpgSQL_stmt_return *new;
 
-	new = palloc0(sizeof(PLpgSQL_stmt_return));
+	new = palloc0_object(PLpgSQL_stmt_return);
 	new->cmd_type = PLPGSQL_STMT_RETURN;
 	new->lineno = plpgsql_location_to_lineno(location, yyscanner);
 	new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -3448,7 +3448,7 @@ make_return_next_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t
 				 errmsg("cannot use RETURN NEXT in a non-SETOF function"),
 				 parser_errposition(location)));
 
-	new = palloc0(sizeof(PLpgSQL_stmt_return_next));
+	new = palloc0_object(PLpgSQL_stmt_return_next);
 	new->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
 	new->lineno = plpgsql_location_to_lineno(location, yyscanner);
 	new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -3512,7 +3512,7 @@ make_return_query_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_
 				 errmsg("cannot use RETURN QUERY in a non-SETOF function"),
 				 parser_errposition(location)));
 
-	new = palloc0(sizeof(PLpgSQL_stmt_return_query));
+	new = palloc0_object(PLpgSQL_stmt_return_query);
 	new->cmd_type = PLPGSQL_STMT_RETURN_QUERY;
 	new->lineno = plpgsql_location_to_lineno(location, yyscanner);
 	new->stmtid = ++plpgsql_curr_compile->nstatements;
@@ -3706,14 +3706,14 @@ read_into_scalar_list(char *initial_name,
 	 */
 	plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner);
 
-	row = palloc0(sizeof(PLpgSQL_row));
+	row = palloc0_object(PLpgSQL_row);
 	row->dtype = PLPGSQL_DTYPE_ROW;
 	row->refname = "(unnamed row)";
 	row->lineno = plpgsql_location_to_lineno(initial_location, yyscanner);
 	row->rowtupdesc = NULL;
 	row->nfields = nfields;
-	row->fieldnames = palloc(sizeof(char *) * nfields);
-	row->varnos = palloc(sizeof(int) * nfields);
+	row->fieldnames = palloc_array(char *, nfields);
+	row->varnos = palloc_array(int, nfields);
 	while (--nfields >= 0)
 	{
 		row->fieldnames[nfields] = fieldnames[nfields];
@@ -3741,14 +3741,14 @@ make_scalar_list1(char *initial_name,
 
 	check_assignable(initial_datum, location, yyscanner);
 
-	row = palloc0(sizeof(PLpgSQL_row));
+	row = palloc0_object(PLpgSQL_row);
 	row->dtype = PLPGSQL_DTYPE_ROW;
 	row->refname = "(unnamed row)";
 	row->lineno = lineno;
 	row->rowtupdesc = NULL;
 	row->nfields = 1;
-	row->fieldnames = palloc(sizeof(char *));
-	row->varnos = palloc(sizeof(int));
+	row->fieldnames = palloc_object(char *);
+	row->varnos = palloc_object(int);
 	row->fieldnames[0] = initial_name;
 	row->varnos[0] = initial_datum->dno;
 
@@ -3955,7 +3955,7 @@ read_cursor_args(PLpgSQL_var *cursor, int until, YYSTYPE *yylvalp, YYLTYPE *yyll
 	 * Read the arguments, one by one.
 	 */
 	row = (PLpgSQL_row *) plpgsql_Datums[cursor->cursor_explicit_argrow];
-	argv = (char **) palloc0(row->nfields * sizeof(char *));
+	argv = (char **) palloc0_array(char *, row->nfields);
 
 	for (argc = 0; argc < row->nfields; argc++)
 	{
@@ -4091,7 +4091,7 @@ read_raise_options(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner)
 		if ((tok = yylex(yylvalp, yyllocp, yyscanner)) == 0)
 			yyerror(yyllocp, NULL, yyscanner, "unexpected end of function definition");
 
-		opt = (PLpgSQL_raise_option *) palloc(sizeof(PLpgSQL_raise_option));
+		opt = palloc_object(PLpgSQL_raise_option);
 
 		if (tok_is_keyword(tok, yylvalp,
 						   K_ERRCODE, "errcode"))
@@ -4182,7 +4182,7 @@ make_case(int location, PLpgSQL_expr *t_expr,
 {
 	PLpgSQL_stmt_case *new;
 
-	new = palloc(sizeof(PLpgSQL_stmt_case));
+	new = palloc_object(PLpgSQL_stmt_case);
 	new->cmd_type = PLPGSQL_STMT_CASE;
 	new->lineno = plpgsql_location_to_lineno(location, yyscanner);
 	new->stmtid = ++plpgsql_curr_compile->nstatements;
diff --git a/src/pl/plpython/plpy_procedure.c b/src/pl/plpython/plpy_procedure.c
index 655ab1d09ee..750ba586e0c 100644
--- a/src/pl/plpython/plpy_procedure.c
+++ b/src/pl/plpython/plpy_procedure.c
@@ -177,7 +177,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger)
 
 	oldcxt = MemoryContextSwitchTo(cxt);
 
-	proc = (PLyProcedure *) palloc0(sizeof(PLyProcedure));
+	proc = palloc0_object(PLyProcedure);
 	proc->mcxt = cxt;
 
 	PG_TRY();
@@ -293,8 +293,8 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger)
 			}
 
 			/* Allocate arrays for per-input-argument data */
-			proc->argnames = (char **) palloc0(sizeof(char *) * proc->nargs);
-			proc->args = (PLyDatumToOb *) palloc0(sizeof(PLyDatumToOb) * proc->nargs);
+			proc->argnames = (char **) palloc0_array(char *, proc->nargs);
+			proc->args = (PLyDatumToOb *) palloc0_array(PLyDatumToOb, proc->nargs);
 
 			for (i = pos = 0; i < total; i++)
 			{
diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c
index 1e386aadcca..46f2ca0f792 100644
--- a/src/pl/plpython/plpy_spi.c
+++ b/src/pl/plpython/plpy_spi.c
@@ -65,8 +65,8 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
 	nargs = list ? PySequence_Length(list) : 0;
 
 	plan->nargs = nargs;
-	plan->types = nargs ? palloc0(sizeof(Oid) * nargs) : NULL;
-	plan->args = nargs ? palloc0(sizeof(PLyObToDatum) * nargs) : NULL;
+	plan->types = nargs ? palloc0_array(Oid, nargs) : NULL;
+	plan->args = nargs ? palloc0_array(PLyObToDatum, nargs) : NULL;
 
 	MemoryContextSwitchTo(oldcontext);
 
diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c
index d88d10068f3..1f69109b081 100644
--- a/src/pl/plpython/plpy_typeio.c
+++ b/src/pl/plpython/plpy_typeio.c
@@ -1353,8 +1353,8 @@ PLyMapping_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *mapping)
 	Assert(PyMapping_Check(mapping));
 
 	/* Build tuple */
-	values = palloc(sizeof(Datum) * desc->natts);
-	nulls = palloc(sizeof(bool) * desc->natts);
+	values = palloc_array(Datum, desc->natts);
+	nulls = palloc_array(bool, desc->natts);
 	for (i = 0; i < desc->natts; ++i)
 	{
 		char	   *key;
@@ -1435,8 +1435,8 @@ PLySequence_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *sequence)
 				 errmsg("length of returned sequence did not match number of columns in row")));
 
 	/* Build tuple */
-	values = palloc(sizeof(Datum) * desc->natts);
-	nulls = palloc(sizeof(bool) * desc->natts);
+	values = palloc_array(Datum, desc->natts);
+	nulls = palloc_array(bool, desc->natts);
 	idx = 0;
 	for (i = 0; i < desc->natts; ++i)
 	{
@@ -1493,8 +1493,8 @@ PLyGenericObject_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *object
 	volatile int i;
 
 	/* Build tuple */
-	values = palloc(sizeof(Datum) * desc->natts);
-	nulls = palloc(sizeof(bool) * desc->natts);
+	values = palloc_array(Datum, desc->natts);
+	nulls = palloc_array(bool, desc->natts);
 	for (i = 0; i < desc->natts; ++i)
 	{
 		char	   *key;
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 73d660e88a6..187698ccdd2 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -1586,7 +1586,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid,
 		 * struct prodesc and subsidiary data must all live in proc_cxt.
 		 ************************************************************/
 		oldcontext = MemoryContextSwitchTo(proc_cxt);
-		prodesc = (pltcl_proc_desc *) palloc0(sizeof(pltcl_proc_desc));
+		prodesc = palloc0_object(pltcl_proc_desc);
 		prodesc->user_proname = pstrdup(user_proname);
 		MemoryContextSetIdentifier(proc_cxt, prodesc->user_proname);
 		prodesc->internal_proname = pstrdup(internal_proname);
@@ -2668,7 +2668,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
 									 "PL/Tcl spi_prepare query",
 									 ALLOCSET_SMALL_SIZES);
 	MemoryContextSwitchTo(plan_cxt);
-	qdesc = (pltcl_query_desc *) palloc0(sizeof(pltcl_query_desc));
+	qdesc = palloc0_object(pltcl_query_desc);
 	snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
 	qdesc->nargs = nargs;
 	qdesc->argtypes = (Oid *) palloc(nargs * sizeof(Oid));
diff --git a/src/test/modules/dummy_index_am/dummy_index_am.c b/src/test/modules/dummy_index_am/dummy_index_am.c
index 94ef639b6fc..a34382a5f79 100644
--- a/src/test/modules/dummy_index_am/dummy_index_am.c
+++ b/src/test/modules/dummy_index_am/dummy_index_am.c
@@ -138,7 +138,7 @@ dibuild(Relation heap, Relation index, IndexInfo *indexInfo)
 {
 	IndexBuildResult *result;
 
-	result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
+	result = palloc_object(IndexBuildResult);
 
 	/* let's pretend that no tuples were scanned */
 	result->heap_tuples = 0;
diff --git a/src/test/modules/spgist_name_ops/spgist_name_ops.c b/src/test/modules/spgist_name_ops/spgist_name_ops.c
index 38e54e0e0a4..f32dfb317fa 100644
--- a/src/test/modules/spgist_name_ops/spgist_name_ops.c
+++ b/src/test/modules/spgist_name_ops/spgist_name_ops.c
@@ -171,7 +171,7 @@ spgist_name_choose(PG_FUNCTION_ARGS)
 			}
 			out->result.splitTuple.prefixNNodes = 1;
 			out->result.splitTuple.prefixNodeLabels =
-				(Datum *) palloc(sizeof(Datum));
+				palloc_object(Datum);
 			out->result.splitTuple.prefixNodeLabels[0] =
 				Int16GetDatum(*(unsigned char *) (prefixStr + commonLen));
 
@@ -243,7 +243,7 @@ spgist_name_choose(PG_FUNCTION_ARGS)
 		out->result.splitTuple.prefixHasPrefix = in->hasPrefix;
 		out->result.splitTuple.prefixPrefixDatum = in->prefixDatum;
 		out->result.splitTuple.prefixNNodes = 1;
-		out->result.splitTuple.prefixNodeLabels = (Datum *) palloc(sizeof(Datum));
+		out->result.splitTuple.prefixNodeLabels = palloc_object(Datum);
 		out->result.splitTuple.prefixNodeLabels[0] = Int16GetDatum(-2);
 		out->result.splitTuple.childNodeN = 0;
 		out->result.splitTuple.postfixHasPrefix = false;
@@ -318,9 +318,9 @@ spgist_name_inner_consistent(PG_FUNCTION_ARGS)
 	 * and see if it's consistent with the query.  If so, emit an entry into
 	 * the output arrays.
 	 */
-	out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
-	out->levelAdds = (int *) palloc(sizeof(int) * in->nNodes);
-	out->reconstructedValues = (Datum *) palloc(sizeof(Datum) * in->nNodes);
+	out->nodeNumbers = palloc_array(int, in->nNodes);
+	out->levelAdds = palloc_array(int, in->nNodes);
+	out->reconstructedValues = palloc_array(Datum, in->nNodes);
 	out->nNodes = 0;
 
 	for (i = 0; i < in->nNodes; i++)
diff --git a/src/test/modules/test_bitmapset/test_bitmapset.c b/src/test/modules/test_bitmapset/test_bitmapset.c
index 8162285fcb3..69383a98e37 100644
--- a/src/test/modules/test_bitmapset/test_bitmapset.c
+++ b/src/test/modules/test_bitmapset/test_bitmapset.c
@@ -622,7 +622,7 @@ test_random_operations(PG_FUNCTION_ARGS)
 	 * still possible if all the operations hit the "0" case during phase 4
 	 * where multiple operation types are mixed together.
 	 */
-	members = palloc(sizeof(int) * num_ops);
+	members = palloc_array(int, num_ops);
 
 	/* Phase 1: Random insertions in first set */
 	for (int i = 0; i < num_ops / 2; i++)
diff --git a/src/test/modules/test_integerset/test_integerset.c b/src/test/modules/test_integerset/test_integerset.c
index cfdc6762785..7ac1fe6cb23 100644
--- a/src/test/modules/test_integerset/test_integerset.c
+++ b/src/test/modules/test_integerset/test_integerset.c
@@ -385,7 +385,7 @@ test_single_value_and_filler(uint64 value, uint64 filler_min, uint64 filler_max)
 
 	intset = intset_create();
 
-	iter_expected = palloc(sizeof(uint64) * (filler_max - filler_min + 1));
+	iter_expected = palloc_array(uint64, filler_max - filler_min + 1);
 	if (value < filler_min)
 	{
 		intset_add_member(intset, value);
diff --git a/src/test/modules/test_json_parser/test_json_parser_incremental.c b/src/test/modules/test_json_parser/test_json_parser_incremental.c
index 8c78061ee46..a95ac798481 100644
--- a/src/test/modules/test_json_parser/test_json_parser_incremental.c
+++ b/src/test/modules/test_json_parser/test_json_parser_incremental.c
@@ -124,7 +124,7 @@ main(int argc, char **argv)
 				break;
 			case 's':			/* do semantic processing */
 				testsem = &sem;
-				sem.semstate = palloc(sizeof(struct DoState));
+				sem.semstate = palloc_object(struct DoState);
 				((struct DoState *) sem.semstate)->lex = lex;
 				((struct DoState *) sem.semstate)->buf = makeStringInfo();
 				need_strings = true;
diff --git a/src/test/modules/test_parser/test_parser.c b/src/test/modules/test_parser/test_parser.c
index 15ed3617cb5..353f9072819 100644
--- a/src/test/modules/test_parser/test_parser.c
+++ b/src/test/modules/test_parser/test_parser.c
@@ -46,7 +46,7 @@ PG_FUNCTION_INFO_V1(testprs_lextype);
 Datum
 testprs_start(PG_FUNCTION_ARGS)
 {
-	ParserState *pst = (ParserState *) palloc0(sizeof(ParserState));
+	ParserState *pst = palloc0_object(ParserState);
 
 	pst->buffer = (char *) PG_GETARG_POINTER(0);
 	pst->len = PG_GETARG_INT32(1);
@@ -112,7 +112,7 @@ testprs_lextype(PG_FUNCTION_ARGS)
 	 * the same lexids like Teodor in the default word parser; in this way we
 	 * can reuse the headline function of the default word parser.
 	 */
-	LexDescr   *descr = (LexDescr *) palloc(sizeof(LexDescr) * (2 + 1));
+	LexDescr   *descr = palloc_array(LexDescr, 2 + 1);
 
 	/* there are only two types in this parser */
 	descr[0].lexid = 3;
diff --git a/src/test/modules/test_radixtree/test_radixtree.c b/src/test/modules/test_radixtree/test_radixtree.c
index 606d8d3cd2d..031e8737d45 100644
--- a/src/test/modules/test_radixtree/test_radixtree.c
+++ b/src/test/modules/test_radixtree/test_radixtree.c
@@ -183,7 +183,7 @@ test_basic(rt_node_class_test_elem *test_info, int shift, bool asc)
 	elog(NOTICE, "testing node %s with shift %d and %s keys",
 		 test_info->class_name, shift, asc ? "ascending" : "descending");
 
-	keys = palloc(sizeof(uint64) * children);
+	keys = palloc_array(uint64, children);
 	for (int i = 0; i < children; i++)
 	{
 		if (asc)
diff --git a/src/test/modules/test_regex/test_regex.c b/src/test/modules/test_regex/test_regex.c
index 2548a0ef7b1..675a6674736 100644
--- a/src/test/modules/test_regex/test_regex.c
+++ b/src/test/modules/test_regex/test_regex.c
@@ -107,10 +107,8 @@ test_regex(PG_FUNCTION_ARGS)
 									  true);
 
 		/* Pre-create workspace that build_test_match_result needs */
-		matchctx->elems = (Datum *) palloc(sizeof(Datum) *
-										   (matchctx->npatterns + 1));
-		matchctx->nulls = (bool *) palloc(sizeof(bool) *
-										  (matchctx->npatterns + 1));
+		matchctx->elems = palloc_array(Datum, matchctx->npatterns + 1);
+		matchctx->nulls = palloc_array(bool, matchctx->npatterns + 1);
 
 		MemoryContextSwitchTo(oldcontext);
 		funcctx->user_fctx = matchctx;
@@ -436,7 +434,7 @@ setup_test_matches(text *orig_str,
 				   Oid collation,
 				   bool use_subpatterns)
 {
-	test_regex_ctx *matchctx = palloc0(sizeof(test_regex_ctx));
+	test_regex_ctx *matchctx = palloc0_object(test_regex_ctx);
 	int			eml = pg_database_encoding_max_length();
 	int			orig_len;
 	pg_wchar   *wide_str;
@@ -457,7 +455,7 @@ setup_test_matches(text *orig_str,
 
 	/* convert string to pg_wchar form for matching */
 	orig_len = VARSIZE_ANY_EXHDR(orig_str);
-	wide_str = (pg_wchar *) palloc(sizeof(pg_wchar) * (orig_len + 1));
+	wide_str = palloc_array(pg_wchar, orig_len + 1);
 	wide_len = pg_mb2wchar_with_len(VARDATA_ANY(orig_str), wide_str, orig_len);
 
 	/* do we want to remember subpatterns? */
@@ -474,7 +472,7 @@ setup_test_matches(text *orig_str,
 	}
 
 	/* temporary output space for RE package */
-	pmatch = palloc(sizeof(regmatch_t) * pmatch_len);
+	pmatch = palloc_array(regmatch_t, pmatch_len); 
 
 	/*
 	 * the real output space (grown dynamically if needed)
@@ -483,7 +481,7 @@ setup_test_matches(text *orig_str,
 	 * than at 2^27
 	 */
 	array_len = re_flags->glob ? 255 : 31;
-	matchctx->match_locs = (int *) palloc(sizeof(int) * array_len);
+	matchctx->match_locs = palloc_array(int, array_len);
 	array_idx = 0;
 
 	/* search for the pattern, perhaps repeatedly */
diff --git a/src/test/modules/test_resowner/test_resowner_many.c b/src/test/modules/test_resowner/test_resowner_many.c
index 1f64939404f..e43f911244a 100644
--- a/src/test/modules/test_resowner/test_resowner_many.c
+++ b/src/test/modules/test_resowner/test_resowner_many.c
@@ -121,7 +121,7 @@ RememberManyTestResources(ResourceOwner owner,
 
 	for (int i = 0; i < nresources; i++)
 	{
-		ManyTestResource *mres = palloc(sizeof(ManyTestResource));
+		ManyTestResource *mres = palloc_object(ManyTestResource);
 
 		mres->kind = &kinds[kind_idx];
 		dlist_node_init(&mres->node);
diff --git a/src/test/modules/test_rls_hooks/test_rls_hooks.c b/src/test/modules/test_rls_hooks/test_rls_hooks.c
index b1f161cf7bb..86453f96147 100644
--- a/src/test/modules/test_rls_hooks/test_rls_hooks.c
+++ b/src/test/modules/test_rls_hooks/test_rls_hooks.c
@@ -44,7 +44,7 @@ List *
 test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
 {
 	List	   *policies = NIL;
-	RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
+	RowSecurityPolicy *policy = palloc0_object(RowSecurityPolicy);
 	Datum		role;
 	FuncCall   *n;
 	Node	   *e;
@@ -112,7 +112,7 @@ List *
 test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)
 {
 	List	   *policies = NIL;
-	RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
+	RowSecurityPolicy *policy = palloc0_object(RowSecurityPolicy);
 	Datum		role;
 	FuncCall   *n;
 	Node	   *e;
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index bea8339f464..1a21b8c8876 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -142,7 +142,7 @@ worker_spi_main(Datum main_arg)
 	char	   *p;
 	bits32		flags = 0;
 
-	table = palloc(sizeof(worktable));
+	table = palloc_object(worktable);
 	sprintf(name, "schema%d", index);
 	table->schema = pstrdup(name);
 	table->name = pstrdup("counted");
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index 56cc0567b1c..c27305cf10b 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -198,7 +198,7 @@ widget_in(PG_FUNCTION_ARGS)
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"widget", str)));
 
-	result = (WIDGET *) palloc(sizeof(WIDGET));
+	result = palloc_object(WIDGET);
 	result->center.x = atof(coord[0]);
 	result->center.y = atof(coord[1]);
 	result->radius = atof(coord[2]);
diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
index 504c0235ffb..505a2d33839 100644
--- a/src/timezone/pgtz.c
+++ b/src/timezone/pgtz.c
@@ -396,7 +396,7 @@ struct pg_tzenum
 pg_tzenum *
 pg_tzenumerate_start(void)
 {
-	pg_tzenum  *ret = (pg_tzenum *) palloc0(sizeof(pg_tzenum));
+	pg_tzenum  *ret = palloc0_object(pg_tzenum);
 	char	   *startdir = pstrdup(pg_TZDIR());
 
 	ret->baselen = strlen(startdir) + 1;
diff --git a/src/tutorial/complex.c b/src/tutorial/complex.c
index 6798a9e6ba6..46dc54e62d0 100644
--- a/src/tutorial/complex.c
+++ b/src/tutorial/complex.c
@@ -41,7 +41,7 @@ complex_in(PG_FUNCTION_ARGS)
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"complex", str)));
 
-	result = (Complex *) palloc(sizeof(Complex));
+	result = palloc_object(Complex);
 	result->x = x;
 	result->y = y;
 	PG_RETURN_POINTER(result);
@@ -73,7 +73,7 @@ complex_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	Complex    *result;
 
-	result = (Complex *) palloc(sizeof(Complex));
+	result = palloc_object(Complex);
 	result->x = pq_getmsgfloat8(buf);
 	result->y = pq_getmsgfloat8(buf);
 	PG_RETURN_POINTER(result);
@@ -108,7 +108,7 @@ complex_add(PG_FUNCTION_ARGS)
 	Complex    *b = (Complex *) PG_GETARG_POINTER(1);
 	Complex    *result;
 
-	result = (Complex *) palloc(sizeof(Complex));
+	result = palloc_object(Complex);
 	result->x = a->x + b->x;
 	result->y = a->y + b->y;
 	PG_RETURN_POINTER(result);
diff --git a/src/tutorial/funcs.c b/src/tutorial/funcs.c
index 3cc94534187..80882cf1414 100644
--- a/src/tutorial/funcs.c
+++ b/src/tutorial/funcs.c
@@ -50,7 +50,7 @@ makepoint(PG_FUNCTION_ARGS)
 {
 	Point	   *pointx = PG_GETARG_POINT_P(0);
 	Point	   *pointy = PG_GETARG_POINT_P(1);
-	Point	   *new_point = (Point *) palloc(sizeof(Point));
+	Point	   *new_point = palloc_object(Point);
 
 	new_point->x = pointx->x;
 	new_point->y = pointy->y;
-- 
2.51.0



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
@ 2025-12-05 07:41                   ` Michael Paquier <michael@paquier.xyz>
  2025-12-05 12:53                     ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-09 22:37                     ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  0 siblings, 2 replies; 29+ messages in thread

From: Michael Paquier @ 2025-12-05 07:41 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On Thu, Dec 04, 2025 at 10:31:41AM +0100, David Geier wrote:
> Attached are the two patches, rebased on latest master.
> 
> The first one contains all changes that either result in no changes to
> the disassembly, or only in changes due to the line counts; because
> elog.h makes use of __LINE__.

Thanks.  That's a lot to digest.

I have generated some reports by comparing builds of HEAD and
HEAD+0001 to indeed note that a lot of noise is caused by the line
number changes.  And then, I have begun looking at contrib/ to start
with something as I had a bit of time today.  One part which we need
to be careful about is that the allocations map with the actual
declarations, and I'm doubting my compiler to detect all of them, so
visual check for each path it is...

-   void       *out = palloc(sizeof(float4KEY));
+   void       *out = palloc_object(float4KEY);

btree_gist/ has a bunch of these, which I guess don't really matter in
terms of type safety.

-   sv = palloc(sizeof(bytea *) * (maxoff + 1));
+   sv = palloc_array(bytea *, (maxoff + 1));

This one also in gbt_var_picksplit@btree_utils_var.c.  We have a
GBT_VARKEY.

+   keys = (char **) palloc_array(char *, key_count);
+   values = (char **) palloc_array(char *, val_count);

These two should not need casts.

-               stack = palloc(sizeof(*stack));
+               stack = palloc_object(sepgsql_proc_stack);

This one in sepgsql was wrong, that can be detected with a compilation
of the module.

And done with the contrib/ part for the trival changes.
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../aTKMtSMTh4eiSGMr@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
@ 2025-12-05 12:53                     ` David Geier <geidav.pg@gmail.com>
  2025-12-05 14:47                       ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  1 sibling, 1 reply; 29+ messages in thread

From: David Geier @ 2025-12-05 12:53 UTC (permalink / raw)
  To: Michael Paquier <michael@paquier.xyz>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On 05.12.2025 08:41, Michael Paquier wrote:
> On Thu, Dec 04, 2025 at 10:31:41AM +0100, David Geier wrote:
>> Attached are the two patches, rebased on latest master.
>>
>> The first one contains all changes that either result in no changes to
>> the disassembly, or only in changes due to the line counts; because
>> elog.h makes use of __LINE__.
> 
> Thanks.  That's a lot to digest.
> 
> I have generated some reports by comparing builds of HEAD and
> HEAD+0001 to indeed note that a lot of noise is caused by the line
> number changes.  And then, I have begun looking at contrib/ to start
> with something as I had a bit of time today.  One part which we need
> to be careful about is that the allocations map with the actual
> declarations, and I'm doubting my compiler to detect all of them, so
> visual check for each path it is...
> 
> -   void       *out = palloc(sizeof(float4KEY));
> +   void       *out = palloc_object(float4KEY);
> 
> btree_gist/ has a bunch of these, which I guess don't really matter in
> terms of type safety.
> 
> -   sv = palloc(sizeof(bytea *) * (maxoff + 1));
> +   sv = palloc_array(bytea *, (maxoff + 1));
> 
> This one also in gbt_var_picksplit@btree_utils_var.c.  We have a
> GBT_VARKEY.
> 
> +   keys = (char **) palloc_array(char *, key_count);
> +   values = (char **) palloc_array(char *, val_count);
> 
> These two should not need casts.
> 
> -               stack = palloc(sizeof(*stack));
> +               stack = palloc_object(sepgsql_proc_stack);
> 
> This one in sepgsql was wrong, that can be detected with a compilation
> of the module.

My bad. I hadn't realized that - obviously - not necessarily all code is
actually compiled by default.

Will the build system enable any target for which all dependencies (e.g.
libraries) are met, or are there targets that need to be enabled
explicitly? Is there a way to enable all of them so I can easily make
sure, I actually compile all code?

> And done with the contrib/ part for the trival changes.

Thanks for applying the first batch of changes.

--
David Geier






^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-05 12:53                     ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
@ 2025-12-05 14:47                       ` Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-11 07:54                         ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  0 siblings, 1 reply; 29+ messages in thread

From: Tom Lane @ 2025-12-05 14:47 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: Michael Paquier <michael@paquier.xyz>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

David Geier <geidav.pg@gmail.com> writes:
> My bad. I hadn't realized that - obviously - not necessarily all code is
> actually compiled by default.

> Will the build system enable any target for which all dependencies (e.g.
> libraries) are met, or are there targets that need to be enabled
> explicitly? Is there a way to enable all of them so I can easily make
> sure, I actually compile all code?

There's a good deal of platform-specific code in PG, particularly for
Windows, and obviously none of that will be built unless you're on the
right platform.  (You can reach some of the Windows-specific code on
other systems with -DEXEC_BACKEND, but that goes only so far.)

As for optional-feature stuff, I think the meson build system will by
default build every option it can find the supporting libraries for.
But the other side of that coin is that if you didn't install the
right packages it will silently not build it.

I think the most reliable way is to look at "./configure --help"
and select all the options you think should work on your platform.
Then, if you forgot to install libfoo-devel or whatever, you'll
get configure failures.

			regards, tom lane





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-05 12:53                     ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 14:47                       ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
@ 2025-12-11 07:54                         ` David Geier <geidav.pg@gmail.com>
  2025-12-11 15:32                           ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 1 reply; 29+ messages in thread

From: David Geier @ 2025-12-11 07:54 UTC (permalink / raw)
  To: Tom Lane <tgl@sss.pgh.pa.us>; +Cc: Michael Paquier <michael@paquier.xyz>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On 05.12.2025 15:47, Tom Lane wrote:
> David Geier <geidav.pg@gmail.com> writes:
>> My bad. I hadn't realized that - obviously - not necessarily all code is
>> actually compiled by default.
> 
>> Will the build system enable any target for which all dependencies (e.g.
>> libraries) are met, or are there targets that need to be enabled
>> explicitly? Is there a way to enable all of them so I can easily make
>> sure, I actually compile all code?
> 
> There's a good deal of platform-specific code in PG, particularly for
> Windows, and obviously none of that will be built unless you're on the
> right platform.  (You can reach some of the Windows-specific code on
> other systems with -DEXEC_BACKEND, but that goes only so far.)
> 
> As for optional-feature stuff, I think the meson build system will by
> default build every option it can find the supporting libraries for.
> But the other side of that coin is that if you didn't install the
> right packages it will silently not build it.
> 
> I think the most reliable way is to look at "./configure --help"
> and select all the options you think should work on your platform.
> Then, if you forgot to install libfoo-devel or whatever, you'll
> get configure failures.

Thanks for the pointers.

Do we know what code each build animal actually has enabled? The
platform specific code is clear but anything that depends on specific
libraries being installed is not.

Do build animal owners try to enable as much code as possible, or is
this completely up to what the owner happened to do when setting up the
build animal?

I'm wondering how much more code coverage we could get on each animal if
maximized the amount of code that is enabled.

--
David Geier






^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-05 12:53                     ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 14:47                       ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-11 07:54                         ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
@ 2025-12-11 15:32                           ` Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 0 replies; 29+ messages in thread

From: Tom Lane @ 2025-12-11 15:32 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: Michael Paquier <michael@paquier.xyz>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

David Geier <geidav.pg@gmail.com> writes:
> Do we know what code each build animal actually has enabled?

Of course.  The configuration is reported in the logs of every
buildfarm run.  For instance, in the most recent run at this
moment,

https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=caiman&dt=2025-12-11%2015%3A00%3A05

we can see

  $ ./configure --enable-cassert --enable-debug --enable-nls --with-perl \
        --with-python --with-tcl --with-gssapi --with-openssl --with-ldap \
        --with-libxml --with-libxslt --with-pam --with-selinux \
        --with-systemd --with-liburing --with-libcurl --with-libnuma \
        --with-lz4 --with-zstd --prefix=/repos/client-code-REL_20/HEAD/inst \
        --with-pgport=5678 --cache-file=/repos/client-code-REL_20/accache-caiman/config-HEAD.cache

and you can drill down to the "configure" step if you want more
detail.

> Do build animal owners try to enable as much code as possible, or is
> this completely up to what the owner happened to do when setting up the
> build animal?

It's the owner's choice.  The buildfarm client's sample config file
has a list of suggested options, and I wouldn't be too surprised
if a lot of people just left that list alone.  I think the ones
paying closer attention probably try to enable as much as they can.

			regards, tom lane





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
@ 2025-12-09 22:37                     ` Michael Paquier <michael@paquier.xyz>
  2025-12-09 22:41                       ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-10 11:48                       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  1 sibling, 2 replies; 29+ messages in thread

From: Michael Paquier @ 2025-12-09 22:37 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On Fri, Dec 05, 2025 at 04:41:41PM +0900, Michael Paquier wrote:
> Thanks.  That's a lot to digest.

Digesting a bit more now..

-   char       *ret = palloc(sizeof(buf));
+   char       *ret = palloc_array(char, sizeof(buf))

This one in dumputils.c is right, but I am not sure that it is an
improvement compared to the statu-quo.

Here is a list of the files where I have noticed tha addition of
casts, which are not required anymore:
brin_tuple.c.
gistbuildbuffers.c.
genam.c.
nbtdedup.c.
nbtree.c.
nbtsort.c.
index.c
execGrouping.c
execMain.c
relnode.c
partbounds.c
mcv.c
spell.c
arrayfuncs.c
partcache.c

Perhaps you have used a semi-automatic process and missed these?
Okay, some of these relied on a "Data" structure for the size vs
pointer for the allocation, but the results are the same.

-       IndexOrderByDistance *distances =
-           palloc(sizeof(distances[0]) * so->numberOfOrderBys);

Okay, this one in spgscan.c is not the usual project style.  Correct,
still funky.

            b_checkargnulls =
-               palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
+               palloc_array(LLVMBasicBlockRef *, op->d.func.nargs);

This one in llvmjit_expr.c was causing a compilation failure.  I am
not exactly sure why, but discarded for now.  I got a reproduction
locally as well as in the CI.

-   node->tsm_state = palloc0(sizeof(BernoulliSamplerData));
+   node->tsm_state = palloc0_object(BernoulliSamplerData); 

One can argue that this one in bernouilli.c is not really necessary,
tsm_state is actually a void *.

Among the 300-ish files changed in the backend, 48 of them had their
builds slightly change.  The list of them is attached.

So that's everything for the trivial changes, with 4601e7f1c708 for
src/backend/ and 0c3c5c3b06a3 for the rest.
--
Michael
src/backend/replication/syncrep.c
src/backend/replication/logical/reorderbuffer.c
src/backend/replication/logical/snapbuild.c
src/backend/partitioning/partbounds.c
src/backend/access/gist/gistbuildbuffers.c
src/backend/access/spgist/spgtextproc.c
src/backend/access/spgist/spgscan.c
src/backend/access/spgist/spgdoinsert.c
src/backend/access/gin/ginscan.c
src/backend/access/gin/ginbulk.c
src/backend/access/transam/parallel.c
src/backend/access/transam/multixact.c
src/backend/access/nbtree/nbtree.c
src/backend/access/hash/hash.c
src/backend/statistics/dependencies.c
src/backend/statistics/extended_stats.c
src/backend/storage/lmgr/predicate.c
src/backend/storage/lmgr/lock.c
src/backend/storage/ipc/procarray.c
src/backend/optimizer/plan/analyzejoins.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/util/appendinfo.c
src/backend/optimizer/util/extendplan.c
src/backend/optimizer/util/plancat.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/path/joinrels.c
src/backend/optimizer/prep/prepjointree.c
src/backend/executor/nodeIndexscan.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeGatherMerge.c
src/backend/executor/nodeHashjoin.c
src/backend/executor/spi.c
src/backend/executor/execExpr.c
src/backend/executor/nodeIndexonlyscan.c
src/backend/executor/nodeProjectSet.c
src/backend/executor/nodeModifyTable.c
src/backend/catalog/dependency.c
src/backend/parser/analyze.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/plancache.c
src/backend/utils/adt/jsonpath_exec.c
src/backend/utils/adt/array_typanalyze.c
src/backend/utils/adt/jsonb_gin.c
src/backend/utils/adt/rangetypes_gist.c
src/backend/utils/adt/timestamp.c
src/backend/utils/adt/numeric.c
src/backend/postmaster/walsummarizer.c

Attachments:

  [text/plain] backend_files.txt (1.7K, ../../aTikrhT9NvtKncUK@paquier.xyz/2-backend_files.txt)
  download | inline:
src/backend/replication/syncrep.c
src/backend/replication/logical/reorderbuffer.c
src/backend/replication/logical/snapbuild.c
src/backend/partitioning/partbounds.c
src/backend/access/gist/gistbuildbuffers.c
src/backend/access/spgist/spgtextproc.c
src/backend/access/spgist/spgscan.c
src/backend/access/spgist/spgdoinsert.c
src/backend/access/gin/ginscan.c
src/backend/access/gin/ginbulk.c
src/backend/access/transam/parallel.c
src/backend/access/transam/multixact.c
src/backend/access/nbtree/nbtree.c
src/backend/access/hash/hash.c
src/backend/statistics/dependencies.c
src/backend/statistics/extended_stats.c
src/backend/storage/lmgr/predicate.c
src/backend/storage/lmgr/lock.c
src/backend/storage/ipc/procarray.c
src/backend/optimizer/plan/analyzejoins.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/util/appendinfo.c
src/backend/optimizer/util/extendplan.c
src/backend/optimizer/util/plancat.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/path/joinrels.c
src/backend/optimizer/prep/prepjointree.c
src/backend/executor/nodeIndexscan.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeGatherMerge.c
src/backend/executor/nodeHashjoin.c
src/backend/executor/spi.c
src/backend/executor/execExpr.c
src/backend/executor/nodeIndexonlyscan.c
src/backend/executor/nodeProjectSet.c
src/backend/executor/nodeModifyTable.c
src/backend/catalog/dependency.c
src/backend/parser/analyze.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/plancache.c
src/backend/utils/adt/jsonpath_exec.c
src/backend/utils/adt/array_typanalyze.c
src/backend/utils/adt/jsonb_gin.c
src/backend/utils/adt/rangetypes_gist.c
src/backend/utils/adt/timestamp.c
src/backend/utils/adt/numeric.c
src/backend/postmaster/walsummarizer.c

  [application/pgp-signature] signature.asc (832B, ../../aTikrhT9NvtKncUK@paquier.xyz/3-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-09 22:37                     ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
@ 2025-12-09 22:41                       ` Thomas Munro <thomas.munro@gmail.com>
  2025-12-09 23:00                         ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  1 sibling, 1 reply; 29+ messages in thread

From: Thomas Munro @ 2025-12-09 22:41 UTC (permalink / raw)
  To: Michael Paquier <michael@paquier.xyz>; +Cc: David Geier <geidav.pg@gmail.com>; Tom Lane <tgl@sss.pgh.pa.us>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On Wed, Dec 10, 2025 at 11:38 AM Michael Paquier <michael@paquier.xyz> wrote:
>             b_checkargnulls =
> -               palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
> +               palloc_array(LLVMBasicBlockRef *, op->d.func.nargs);
>
> This one in llvmjit_expr.c was causing a compilation failure.  I am
> not exactly sure why, but discarded for now.  I got a reproduction
> locally as well as in the CI.

I think the original code is wrong, it should have been
sizeof(LLVMBasicBlockRef)?  It'll be the same size anyway (these
LLVM*Ref types are just pointers), but that'd explain why the
transformation didn't compile.





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-09 22:37                     ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-09 22:41                       ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
@ 2025-12-09 23:00                         ` Michael Paquier <michael@paquier.xyz>
  0 siblings, 0 replies; 29+ messages in thread

From: Michael Paquier @ 2025-12-09 23:00 UTC (permalink / raw)
  To: Thomas Munro <thomas.munro@gmail.com>; +Cc: David Geier <geidav.pg@gmail.com>; Tom Lane <tgl@sss.pgh.pa.us>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On Wed, Dec 10, 2025 at 11:41:25AM +1300, Thomas Munro wrote:
> On Wed, Dec 10, 2025 at 11:38 AM Michael Paquier <michael@paquier.xyz> wrote:
>>             b_checkargnulls =
>> -               palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
>> +               palloc_array(LLVMBasicBlockRef *, op->d.func.nargs);
>>
>> This one in llvmjit_expr.c was causing a compilation failure.  I am
>> not exactly sure why, but discarded for now.  I got a reproduction
>> locally as well as in the CI.
> 
> I think the original code is wrong, it should have been
> sizeof(LLVMBasicBlockRef)?  It'll be the same size anyway (these
> LLVM*Ref types are just pointers), but that'd explain why the
> transformation didn't compile.

Yes, perhaps, I would need to double-check to be sure, and you make it
sound like this one should be back-patched.  I was planning to get
back to this one with the batch of non-trivial changes that Bryan has
posted now that I've cleared the path for the stright-forward ones.
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../aTiqDV9wxbCfox1p@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-09 22:37                     ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
@ 2025-12-10 11:48                       ` David Geier <geidav.pg@gmail.com>
  2025-12-10 23:01                         ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  1 sibling, 1 reply; 29+ messages in thread

From: David Geier @ 2025-12-10 11:48 UTC (permalink / raw)
  To: Michael Paquier <michael@paquier.xyz>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

Hi Michael!

Thanks for continuing applying the patches.

On 09.12.2025 23:37, Michael Paquier wrote:
> On Fri, Dec 05, 2025 at 04:41:41PM +0900, Michael Paquier wrote:
>> Thanks.  That's a lot to digest.
> 
> Digesting a bit more now..
> 
> -   char       *ret = palloc(sizeof(buf));
> +   char       *ret = palloc_array(char, sizeof(buf))
> 
> This one in dumputils.c is right, but I am not sure that it is an
> improvement compared to the statu-quo.

Apart from saving casts, using the _array() and _object() variants
improves readability as it's clear from the used macro what the code
intents to do.

For example. without knowing the type of buf, it's not immediately clear
if this is allocating an array of the size of buf, or if it's allocating
an object (e.g. if buf happened to be some struct that represents a
buffer object).

The amount of allocated memory would of course be the same, but how it's
going to be used can be nicely derived from the used macro.

> Here is a list of the files where I have noticed tha addition of
> casts, which are not required anymore:
> brin_tuple.c.
> gistbuildbuffers.c.
> genam.c.
> nbtdedup.c.
> nbtree.c.
> nbtsort.c.
> index.c
> execGrouping.c
> execMain.c
> relnode.c
> partbounds.c
> mcv.c
> spell.c
> arrayfuncs.c
> partcache.c
> 
> Perhaps you have used a semi-automatic process and missed these?

Do you mean in these files I forgot removing casts that got unnecessary
after using _array() / _object()? It's possible that I missed some,
given the large amount. Please fix them as you see fit.

> One can argue that this one in bernouilli.c is not really necessary,
> tsm_state is actually a void *.

As stated above: this change is not only about saving casts but the
macros convey the intent much better than a call to palloc().

> Among the 300-ish files changed in the backend, 48 of them had their
> builds slightly change.  The list of them is attached.

Do you mean the disassembly because the number of lines of code changes?

--
David Geier





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-09 22:37                     ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-10 11:48                       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
@ 2025-12-10 23:01                         ` Michael Paquier <michael@paquier.xyz>
  2025-12-11 05:33                           ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  0 siblings, 1 reply; 29+ messages in thread

From: Michael Paquier @ 2025-12-10 23:01 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On Wed, Dec 10, 2025 at 12:48:35PM +0100, David Geier wrote:
> On 09.12.2025 23:37, Michael Paquier wrote:
>> On Fri, Dec 05, 2025 at 04:41:41PM +0900, Michael Paquier wrote:
> Do you mean in these files I forgot removing casts that got unnecessary
> after using _array() / _object()? It's possible that I missed some,
> given the large amount. Please fix them as you see fit.

Yes, your patch did not remove casts in all the files I have listed
upthread.  I have fixed them already in the tree, for all the trivial
changes.

>> One can argue that this one in bernouilli.c is not really necessary,
>> tsm_state is actually a void *.
> 
> As stated above: this change is not only about saving casts but the
> macros convey the intent much better than a call to palloc().

I got that, but I could not convinced myself that such cases are worth
it.  We don't have many of them in the tree anyway.  They count for
less than 1% of all the changes dealt with here 

>> Among the 300-ish files changed in the backend, 48 of them had their
>> builds slightly change.  The list of them is attached.
> 
> Do you mean the disassembly because the number of lines of code changes?

Yes, I have cross-checked the reports generated between before and
after the patches, to see that they matched with the formulas
changing.  A trick that I have used here and that was rather painful
is to manually change the files where the formulas got shorter to make
their build match..  But well..

I still need to get through the remaining dubious changes you have
posted, including the llvm one that was wrong.  It seems like some of
these things warrant a backpatch.
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../aTn73SDlm922r67G@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-09 22:37                     ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-10 11:48                       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-10 23:01                         ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
@ 2025-12-11 05:33                           ` Michael Paquier <michael@paquier.xyz>
  2025-12-11 08:06                             ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  0 siblings, 1 reply; 29+ messages in thread

From: Michael Paquier @ 2025-12-11 05:33 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On Thu, Dec 11, 2025 at 08:01:49AM +0900, Michael Paquier wrote:
> I still need to get through the remaining dubious changes you have
> posted, including the llvm one that was wrong.  It seems like some of
> these things warrant a backpatch.

I have been looking at the rest of these changes with some -O2, and I
have been puzzled by the differences in hstore_gin.c and hstore_op.c.
In all these cases we generate more instructions with the patch than
without the patch.  Anyway, I assume that these are the ones that
matter:
entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
out_datums = palloc_array(Datum, count * 2);

pg_trgm.c was less puzzling.  For example:
-   trg1 = (trgm *) palloc(sizeof(trgm) * (slen1 / 2 + 1) * 3);
+   trg1 = palloc_array(trgm, (slen1 / 2 + 1) * 3);
This one leads to something like that before vs after:
<     1418:     83 c0 01                add    eax,0x1
>     1418:     8d 44 40 03             lea    eax,[rax+rax*2+0x3]

In execPartition.c and partprune.c, as far as I can see we are cutting
a few mov, leading to less instructions overall.

For mvdistinct.c, we are cutting things overall.  I am seeing less.

All the fuzz in postgres_fdw.c is caused by this one:
-   p_values = (const char **) palloc(sizeof(char *) * fmstate->p_nums
* numSlots);
+   p_values = palloc_array(const char *, fmstate->p_nums * numSlots);  

bufmgr.c did not matter, same before and after.

I am not completely sure about the one in fuzzystrmatch, I would need
to study more the metaphone code.  :)

One formula in llvmjit_expr.c has been wrong since v10, so I have
backpatched a fix for it.

In pg_buffercache_pages.c, the difference is here:
-           os_page_status = palloc(sizeof(uint64) * os_page_count);
+           os_page_status = palloc_array(int, os_page_count);
Your formula is correct, the previous one was not by using a uint64.
So it allocated twice too much memory.  Backpatched this one down to
v18.

And that should close this thread, at least from my side..
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../aTpXvSiis8ufin_I@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-26 23:03 ` Re: Consistently use palloc_object() and palloc_array() Chao Li <li.evan.chao@gmail.com>
  2025-11-28 21:06   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 21:28     ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:47       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-28 22:31         ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-12-02 15:13           ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 00:35             ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-03 00:40               ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-12-04 09:31                 ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-05 07:41                   ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-09 22:37                     ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-10 11:48                       ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-10 23:01                         ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2025-12-11 05:33                           ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
@ 2025-12-11 08:06                             ` David Geier <geidav.pg@gmail.com>
  0 siblings, 0 replies; 29+ messages in thread

From: David Geier @ 2025-12-11 08:06 UTC (permalink / raw)
  To: Michael Paquier <michael@paquier.xyz>; +Cc: Tom Lane <tgl@sss.pgh.pa.us>; Thomas Munro <thomas.munro@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers

On 11.12.2025 06:33, Michael Paquier wrote:
> On Thu, Dec 11, 2025 at 08:01:49AM +0900, Michael Paquier wrote:
>> I still need to get through the remaining dubious changes you have
>> posted, including the llvm one that was wrong.  It seems like some of
>> these things warrant a backpatch.
> 
> I have been looking at the rest of these changes with some -O2, and I
> have been puzzled by the differences in hstore_gin.c and hstore_op.c.
> In all these cases we generate more instructions with the patch than
> without the patch.  Anyway, I assume that these are the ones that
> matter:
> entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
> out_datums = palloc_array(Datum, count * 2);

Yeah, in a few cases the different bracketing has some surprisingly big
influence on the generated assmebly.

> pg_trgm.c was less puzzling.  For example:
> -   trg1 = (trgm *) palloc(sizeof(trgm) * (slen1 / 2 + 1) * 3);
> +   trg1 = palloc_array(trgm, (slen1 / 2 + 1) * 3);
> This one leads to something like that before vs after:
> <     1418:     83 c0 01                add    eax,0x1
>>     1418:     8d 44 40 03             lea    eax,[rax+rax*2+0x3]
> 
> In execPartition.c and partprune.c, as far as I can see we are cutting
> a few mov, leading to less instructions overall.
> 
> For mvdistinct.c, we are cutting things overall.  I am seeing less.
> 
> All the fuzz in postgres_fdw.c is caused by this one:
> -   p_values = (const char **) palloc(sizeof(char *) * fmstate->p_nums
> * numSlots);
> +   p_values = palloc_array(const char *, fmstate->p_nums * numSlots);  
> 
> bufmgr.c did not matter, same before and after.
> 
> I am not completely sure about the one in fuzzystrmatch, I would need
> to study more the metaphone code.  :)
Actually, the change in fuzzystrmatch.c is incorrect.

With the new code, palloc(0) will be called for strlen(word) == 0. Then
no space for the null-terminator byte will be left.

Even if palloc(0) returns memory that can be dereferenced, I don't think
it's a good idea to rely on that.

> One formula in llvmjit_expr.c has been wrong since v10, so I have
> backpatched a fix for it.
> 
> In pg_buffercache_pages.c, the difference is here:
> -           os_page_status = palloc(sizeof(uint64) * os_page_count);
> +           os_page_status = palloc_array(int, os_page_count);
> Your formula is correct, the previous one was not by using a uint64.
> So it allocated twice too much memory.  Backpatched this one down to
> v18.
> 
> And that should close this thread, at least from my side..

Thanks Michael for taking care of this patch!

--
David Geier





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
@ 2025-11-27 00:24 ` Michael Paquier <michael@paquier.xyz>
  2025-11-28 21:33   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2 siblings, 1 reply; 29+ messages in thread

From: Michael Paquier @ 2025-11-27 00:24 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: pgsql-hackers

On Wed, Nov 26, 2025 at 11:09:31PM +0100, David Geier wrote:
> I've changed all code to use the "new" palloc_object(), palloc_array(),
> palloc0_object(), palloc0_array, repalloc_array() and repalloc0_array()
> macros. This makes the code more readable and more consistent.
>
> The patch is pretty big but potential merge conflicts should be easy to
> resolve. If preferred, I can also further split up the patch, e.g.
> directory by directory or high impact files first.

The backpatching extra-pain argument indeed comes into mind first when
it comes to such changes, but perhaps we should just bite the bullet
and encourage the new allocation styles across the tree, as you are
doing here.  I'm not completely sure if it would make sense to split
things up, if we do I would do it on a subdirectory basis like to
suggest, perhaps, like contrib/, src/backend/executor/, etc. to
balance the blast damage.  Did you use some kind of automation to find
all of these?  If yes, what did you use?

> The patch is passing "meson test" and I've additionally wrote a script
> that parses the patch file and verifies that every two corresponding +
> and - lines match (e.g. palloc0() replaced by palloc0_array() or
> palloc0_object(), the same for palloc() and repalloc(), additionally
> some checks to make sure the conversion to the _array() variant is
> correct).

It may be an idea to share that as well, so as your checks could be
replicated rather than partially re-guessed.
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../aSeaNNJqIzQTd3LI@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-27 00:24 ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
@ 2025-11-28 21:33   ` David Geier <geidav.pg@gmail.com>
  0 siblings, 0 replies; 29+ messages in thread

From: David Geier @ 2025-11-28 21:33 UTC (permalink / raw)
  To: Michael Paquier <michael@paquier.xyz>; +Cc: pgsql-hackers

Hi Michael!

On 27.11.2025 01:24, Michael Paquier wrote:
> On Wed, Nov 26, 2025 at 11:09:31PM +0100, David Geier wrote:
>> I've changed all code to use the "new" palloc_object(), palloc_array(),
>> palloc0_object(), palloc0_array, repalloc_array() and repalloc0_array()
>> macros. This makes the code more readable and more consistent.
>>
>> The patch is pretty big but potential merge conflicts should be easy to
>> resolve. If preferred, I can also further split up the patch, e.g.
>> directory by directory or high impact files first.
> 
> The backpatching extra-pain argument indeed comes into mind first when
> it comes to such changes, but perhaps we should just bite the bullet
> and encourage the new allocation styles across the tree, as you are
> doing here.  I'm not completely sure if it would make sense to split
> things up, if we do I would do it on a subdirectory basis like to
> suggest, perhaps, like contrib/, src/backend/executor/, etc. to
> balance the blast damage.  Did you use some kind of automation to find
> all of these?  If yes, what did you use?
I thought again about splitting up the patch. I'm not sure how useful
this really is. If a single committer takes this on, then it doesn't
really matter. He can apply the patch but then commit directory by
directory or in any other way he deems best. If we want to divide the
work among multiple committers splitting might be more useful.

Just tell me what you prefer and I'll provide the patch accordingly.

>> The patch is passing "meson test" and I've additionally wrote a script
>> that parses the patch file and verifies that every two corresponding +
>> and - lines match (e.g. palloc0() replaced by palloc0_array() or
>> palloc0_object(), the same for palloc() and repalloc(), additionally
>> some checks to make sure the conversion to the _array() variant is
>> correct).
> 
> It may be an idea to share that as well, so as your checks could be
> replicated rather than partially re-guessed.
I've attached the script. You can run it via

python3 verify_palloc_pairs.py patch_file

Disclaimer: The script is a bit of a mess. It doesn't check repalloc()
and it still reports five conversions as erroneous while they're
actually correct. I checked them manually. I left it at that because the
vast majority of changes it processes correctly and all tests pass. The
repalloc() occurrences I also checked manually.

--
David Geier

Attachments:

  [text/x-python] verify_palloc_pairs.py (10.8K, ../../2df720fb-664b-480e-96f7-19cc141762d3@gmail.com/2-verify_palloc_pairs.py)
  download | inline:
#!/usr/bin/env python3

import sys
import re
from typing import List, Tuple, Optional, Dict
from dataclasses import dataclass

@dataclass
class PallocLine:
    line_num: int
    content: str
    file_path: str
    palloc_type: str  # 'palloc', 'palloc0', 'palloc_object', 'palloc_array', 'palloc0_object', 'palloc0_array'
    is_deletion: bool
    
    def __str__(self):
        prefix = "-" if self.is_deletion else "+"
        return f"{prefix} Line {self.line_num}: {self.content.strip()}"

def extract_palloc_type(line: str) -> Optional[str]:
    # Match all palloc variants
    patterns = [
        r'\bpalloc0_object\s*\(',
        r'\bpalloc0_array\s*\(',
        r'\bpalloc_object\s*\(',
        r'\bpalloc_array\s*\(',
        r'\bpalloc0\s*\(',
        r'\bpalloc\s*\('
    ]
    
    for pattern in patterns:
        if re.search(pattern, line):
            match = re.search(r'\b(palloc0?(?:_(?:object|array))?)\s*\(', line)
            if match:
                return match.group(1)
    
    return None

def is_zero_initialized(palloc_type: str) -> bool:
    return palloc_type in ['palloc0', 'palloc0_object', 'palloc0_array']

def parse_patch_file(patch_file: str) -> List[Tuple[PallocLine, Optional[PallocLine]]]:
    try:
        with open(patch_file, 'r', encoding='utf-8') as f:
            lines = f.readlines()
    except FileNotFoundError:
        print(f"Error: Patch file '{patch_file}' not found.")
        sys.exit(1)
    except Exception as e:
        print(f"Error reading patch file: {e}")
        sys.exit(1)
    
    pairs = []
    current_file = ""
    deletion_lines = []  # Track pending deletions
    
    for i, line in enumerate(lines):
        line_content = line.rstrip()
        
        # Track current file being patched
        if line_content.startswith('+++'):
            match = re.search(r'\+\+\+ b/(.+)', line_content)
            if match:
                current_file = match.group(1)
        
        # Handle deletion lines
        elif line_content.startswith('-'):
            palloc_type = extract_palloc_type(line_content)
            if palloc_type:
                deletion_line = PallocLine(
                    line_num=i + 1,
                    content=line_content,
                    file_path=current_file,
                    palloc_type=palloc_type,
                    is_deletion=True
                )
                deletion_lines.append(deletion_line)
        
        # Handle insertion lines
        elif line_content.startswith('+'):
            palloc_type = extract_palloc_type(line_content)
            if palloc_type:
                insertion_line = PallocLine(
                    line_num=i + 1,
                    content=line_content,
                    file_path=current_file,
                    palloc_type=palloc_type,
                    is_deletion=False
                )
                
                # Try to match with a pending deletion
                matched_deletion = None
                for j, deletion in enumerate(deletion_lines):
                    # Simple heuristic: match if they're close and in the same file
                    if (deletion.file_path == current_file and 
                        abs(deletion.line_num - insertion_line.line_num) < 10):
                        matched_deletion = deletion_lines.pop(j)
                        break
                
                pairs.append((matched_deletion, insertion_line))
        
        # Handle context lines (reset deletion buffer if we've moved past the change)
        elif line_content.startswith(' ') or line_content.startswith('@@'):
            # Keep recent deletions, clear old ones
            deletion_lines = [d for d in deletion_lines if abs(d.line_num - (i + 1)) < 5]
    
    # Add any unmatched deletions
    for deletion in deletion_lines:
        pairs.append((deletion, None))
    
    return pairs

def is_array_allocation(line: str) -> bool:
    # Look for patterns like: count * sizeof, sizeof(...) * count, etc.
    patterns = [
        r'\w+\s*\*\s*sizeof\s*\(',  # count * sizeof(
        r'sizeof\s*\([^)]+\)\s*\*\s*\w+',  # sizeof(...) * count
        r'\(\s*\w+[^)]*\)\s*\*\s*sizeof',  # (count) * sizeof
        r'sizeof\s*\([^)]+\)\s*\*\s*\(',  # sizeof(...) * (count)
        r'sizeof\s*\([^)]+\)\s*\*\s*\d+',  # sizeof(...) * number
        r'\d+\s*\*\s*sizeof\s*\(',  # number * sizeof(
    ]
    
    for pattern in patterns:
        if re.search(pattern, line):
            return True
    
    # Check for more complex multiplication patterns
    # This catches cases like: lenq * sizeof(bool), nparts * sizeof(Type), etc.
    if re.search(r'\b\w+\s*\*\s*sizeof\s*\(\s*\w+\s*\)', line):
        return True
    
    # Check for parenthesized expressions with sizeof
    if re.search(r'\([^)]*\w+[^)]*\)\s*\*\s*sizeof', line):
        return True
        
    return False

def is_single_object_allocation(line: str) -> bool:
    # Look for patterns like: sizeof(Type) without multiplication
    if re.search(r'sizeof\s*\([^)]+\)(?!\s*\*)', line):
        return True
    if re.search(r'sizeof\s*\(\s*\*\s*\w+\s*\)', line):  # sizeof(*ptr)
        return True
    return False

def verify_pair(deletion: Optional[PallocLine], insertion: Optional[PallocLine]) -> Tuple[bool, str]:
    if deletion is None and insertion is None:
        return False, " Empty pair"
    
    if deletion is None:
        return True, f"  New palloc addition: {insertion.palloc_type}"
    
    if insertion is None:
        return False, f" Unmatched deletion: {deletion.palloc_type} (no corresponding insertion found)"
    
    # Check if zero-initialization behavior is preserved
    deletion_is_zero = is_zero_initialized(deletion.palloc_type)
    insertion_is_zero = is_zero_initialized(insertion.palloc_type)
    
    if deletion_is_zero != insertion_is_zero:
        if deletion_is_zero and not insertion_is_zero:
            return False, f" ZERO-INIT LOST: {deletion.palloc_type} -> {insertion.palloc_type}"
        else:
            return False, f" UNEXPECTED ZERO-INIT: {deletion.palloc_type} -> {insertion.palloc_type}"
    
    # Check if array vs object conversion is semantically correct
    deletion_is_array = is_array_allocation(deletion.content)
    deletion_is_object = is_single_object_allocation(deletion.content)
    
    # Array detection takes precedence over object detection
    # If it's detected as both, it's an array (since arrays contain sizeof too)
    if deletion_is_array and deletion_is_object:
        deletion_is_object = False
    
    insertion_uses_array = insertion.palloc_type.endswith('_array')
    insertion_uses_object = insertion.palloc_type.endswith('_object')
    
    # Only check semantic correctness if we can clearly identify the pattern
    if deletion_is_array or deletion_is_object:
        # Verify semantic correctness of array vs object choice
        if deletion_is_array and insertion_uses_object:
            return False, f" ARRAY->OBJECT MISMATCH: Array allocation converted to _object: {deletion.palloc_type} -> {insertion.palloc_type}"
        
        if deletion_is_object and insertion_uses_array:
            return False, f" OBJECT->ARRAY MISMATCH: Single object allocation converted to _array: {deletion.palloc_type} -> {insertion.palloc_type}"
    
    # All checks passed
    conversion_type = ""
    if deletion_is_array and insertion_uses_array:
        conversion_type = " (ARRAY)"
    elif deletion_is_object and insertion_uses_object:
        conversion_type = " (OBJECT)"
    elif not deletion_is_array and not deletion_is_object:
        conversion_type = " (COMPLEX)"
    
    return True, f"CORRECT: {deletion.palloc_type} -> {insertion.palloc_type}{conversion_type}"

def main():
    if len(sys.argv) != 2:
        print("Usage: python verify_palloc_pairs.py <patch_file>")
        sys.exit(1)
    
    patch_file = sys.argv[1]
    print(f"Analyzing palloc pairs in patch file: {patch_file}")
    print("=" * 80)
    
    pairs = parse_patch_file(patch_file)
    
    if not pairs:
        print(" No palloc conversions found in the patch file.")
        return
    
    print(f"Found {len(pairs)} palloc conversion pairs to verify:")
    print()
    
    valid_count = 0
    invalid_count = 0
    issues = []
    
    for i, (deletion, insertion) in enumerate(pairs, 1):
        is_valid, message = verify_pair(deletion, insertion)
        
        print(f"{i:3d}. {message}")
        
        if deletion:
            print(f"     File: {deletion.file_path}")
            print(f"     Del:  {deletion.content.strip()}")
        if insertion:
            if not deletion or deletion.file_path != insertion.file_path:
                print(f"     File: {insertion.file_path}")
            print(f"     Add:  {insertion.content.strip()}")
        
        if is_valid:
            valid_count += 1
        else:
            invalid_count += 1
            issues.append((deletion, insertion, message))
        
        print()
    
    print("=" * 80)
    print(f" SUMMARY:")
    print(f"    Valid pairs: {valid_count}")
    print(f"    Invalid pairs: {invalid_count}")
    print(f"    Total pairs: {len(pairs)}")
    
    # Count conversion types
    array_conversions = 0
    object_conversions = 0
    complex_conversions = 0
    zero_init_conversions = 0
    non_zero_conversions = 0
    
    for i, (deletion, insertion) in enumerate(pairs, 1):
        if deletion and insertion:
            if insertion.palloc_type.endswith('_array'):
                array_conversions += 1
            elif insertion.palloc_type.endswith('_object'):
                object_conversions += 1
            else:
                complex_conversions += 1
                
            if is_zero_initialized(insertion.palloc_type):
                zero_init_conversions += 1
            else:
                non_zero_conversions += 1
    
    print()
    print(f"CONVERSION BREAKDOWN:")
    print(f"   Array conversions (_array): {array_conversions}")
    print(f"   Object conversions (_object): {object_conversions}")
    print(f"   Complex conversions: {complex_conversions}")
    print(f"   Zero-initialized: {zero_init_conversions}")
    print(f"   Non-zero: {non_zero_conversions}")
    
    if invalid_count == 0:
        print()
        print("SUCCESS: All palloc conversion pairs are semantically correct!")
        print("   Zero-initialization behavior preserved")
        print("   Array vs Object semantics correct")
        sys.exit(0)
    else:
        print()
        print("ISSUES FOUND:")
        for deletion, insertion, message in issues:
            print(f"   • {message}")
            if deletion:
                print(f"     File: {deletion.file_path} (line {deletion.line_num})")
            elif insertion:
                print(f"     File: {insertion.file_path} (line {insertion.line_num})")
        print()
        print(" FAILED: Some conversion pairs have semantic issues.")
        sys.exit(1)

if __name__ == "__main__":
    main()

^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
@ 2025-11-27 02:53 ` Thomas Munro <thomas.munro@gmail.com>
  2025-11-27 03:25   ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-28 21:39   ` Re: Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-12-03 19:11   ` Re: Consistently use palloc_object() and palloc_array() Peter Eisentraut <peter@eisentraut.org>
  2 siblings, 3 replies; 29+ messages in thread

From: Thomas Munro @ 2025-11-27 02:53 UTC (permalink / raw)
  To: David Geier <geidav.pg@gmail.com>; +Cc: pgsql-hackers

On Thu, Nov 27, 2025 at 11:10 AM David Geier <geidav.pg@gmail.com> wrote:
> I've changed all code to use the "new" palloc_object(), palloc_array(),
> palloc0_object(), palloc0_array, repalloc_array() and repalloc0_array()
> macros. This makes the code more readable and more consistent.

I wondered about this in the context of special alignment
requirements[1].  palloc() aligns to MAXALIGN, which we artificially
constrain for various reasons that we can't easily change (at least
not without splitting on-disk MAXALIGN from allocation MAXALIGN, and
if we do that we'll waste more memory).  That's less than
alignof(max_align_t) on common systems, so then we have to do some
weird stuff to handle __int128 that doesn't fit too well into modern
<stdalign.h> thinking and also disables optimal codegen.

This isn't a fully-baked thought, just a thought that occurred to me
while looking into that:  If palloc_object(Int128AggState) were smart
enough to detect that alignof(T) > MAXALIGN and redirect to
palloc_aligned(sizeof(T), alignof(T), ...) at compile time, then
Int128AggState would naturally propagate the layout requirements of
its __int128 member, and we wouldn't need to do that weird stuff, and
it wouldn't be error-prone if usage of __int128 spreads to more
structs.  That really only makes sense if we generalise
palloc_object() as a programming style and consider direct use of
palloc() to be a rarer low-level interface that triggers human
reviewers to think about alignment, I guess.  I think you'd also want
a variant that can deal with structs ending in a flexible array
member, but that seems doable...  palloc_flexible_object(T,
flexible_member, flexible_elements) or whatever.  But I might also be
missing some parts of that puzzle, for example it wouldn't make sense
if __int128 is ever stored.

[1] https://www.postgresql.org/message-id/CA%2BhUKGLQUivg-NC7dHdbRAPmG0Hapg1gGnygM5KgDfDM2a_TMg%40mail.g...





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-27 02:53 ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
@ 2025-11-27 03:25   ` Tom Lane <tgl@sss.pgh.pa.us>
  2025-11-27 05:18     ` Re: Consistently use palloc_object() and palloc_array() Michael Paquier <michael@paquier.xyz>
  2 siblings, 1 reply; 29+ messages in thread

From: Tom Lane @ 2025-11-27 03:25 UTC (permalink / raw)
  To: Thomas Munro <thomas.munro@gmail.com>; +Cc: David Geier <geidav.pg@gmail.com>; pgsql-hackers

Thomas Munro <thomas.munro@gmail.com> writes:
> This isn't a fully-baked thought, just a thought that occurred to me
> while looking into that:  If palloc_object(Int128AggState) were smart
> enough to detect that alignof(T) > MAXALIGN and redirect to
> palloc_aligned(sizeof(T), alignof(T), ...) at compile time, then
> Int128AggState would naturally propagate the layout requirements of
> its __int128 member, and we wouldn't need to do that weird stuff, and
> it wouldn't be error-prone if usage of __int128 spreads to more
> structs.  That really only makes sense if we generalise
> palloc_object() as a programming style and consider direct use of
> palloc() to be a rarer low-level interface that triggers human
> reviewers to think about alignment, I guess.

Hmm ... I had the same doubts as Michael about whether this change
could possibly be worth the ensuing back-patching pain.  But if
it leads to an improvement in type-safety, that'd be a reason to
take on the work.

			regards, tom lane





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-27 02:53 ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
  2025-11-27 03:25   ` Re: Consistently use palloc_object() and palloc_array() Tom Lane <tgl@sss.pgh.pa.us>
@ 2025-11-27 05:18     ` Michael Paquier <michael@paquier.xyz>
  0 siblings, 0 replies; 29+ messages in thread

From: Michael Paquier @ 2025-11-27 05:18 UTC (permalink / raw)
  To: Tom Lane <tgl@sss.pgh.pa.us>; +Cc: Thomas Munro <thomas.munro@gmail.com>; David Geier <geidav.pg@gmail.com>; pgsql-hackers

On Wed, Nov 26, 2025 at 10:25:12PM -0500, Tom Lane wrote:
> Hmm ... I had the same doubts as Michael about whether this change
> could possibly be worth the ensuing back-patching pain.  But if
> it leads to an improvement in type-safety, that'd be a reason to
> take on the work.

Yeah, that sounds like a reason convincing enough to do the jump.  I
didn't really feel strongly against the original proposal to begin
with as it improves the code style, FWIW.

The backpatching bits like these are always annoying, of course.  Now,
these fancy palloc() routines exist since v16 so that would just mean
two years and two branches that would need special handling.  Even
better, why not just backpatch into v15 and v14 the macros in palloc.h
and fe_memutils.h to avoid backpatch hazards due to some new code?
--
Michael

Attachments:

  [application/pgp-signature] signature.asc (832B, ../../aSffJWtqfi0ut6NI@paquier.xyz/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-27 02:53 ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
@ 2025-11-28 21:39   ` David Geier <geidav.pg@gmail.com>
  2 siblings, 0 replies; 29+ messages in thread

From: David Geier @ 2025-11-28 21:39 UTC (permalink / raw)
  To: Thomas Munro <thomas.munro@gmail.com>; +Cc: pgsql-hackers

Hi Thomas!

On 27.11.2025 03:53, Thomas Munro wrote:
> On Thu, Nov 27, 2025 at 11:10 AM David Geier <geidav.pg@gmail.com> wrote:
>> I've changed all code to use the "new" palloc_object(), palloc_array(),
>> palloc0_object(), palloc0_array, repalloc_array() and repalloc0_array()
>> macros. This makes the code more readable and more consistent.
> 
> I wondered about this in the context of special alignment
> requirements[1].  palloc() aligns to MAXALIGN, which we artificially
> constrain for various reasons that we can't easily change (at least
> not without splitting on-disk MAXALIGN from allocation MAXALIGN, and
> if we do that we'll waste more memory).  That's less than
> alignof(max_align_t) on common systems, so then we have to do some
> weird stuff to handle __int128 that doesn't fit too well into modern
> <stdalign.h> thinking and also disables optimal codegen.
> 
> This isn't a fully-baked thought, just a thought that occurred to me
> while looking into that:  If palloc_object(Int128AggState) were smart
> enough to detect that alignof(T) > MAXALIGN and redirect to
> palloc_aligned(sizeof(T), alignof(T), ...) at compile time, then
> Int128AggState would naturally propagate the layout requirements of
> its __int128 member, and we wouldn't need to do that weird stuff, and
> it wouldn't be error-prone if usage of __int128 spreads to more
> structs.  That really only makes sense if we generalise
> palloc_object() as a programming style and consider direct use of
> palloc() to be a rarer low-level interface that triggers human
> reviewers to think about alignment, I guess.  I think you'd also want
> a variant that can deal with structs ending in a flexible array
> member, but that seems doable...  palloc_flexible_object(T,
> flexible_member, flexible_elements) or whatever.  But I might also be
> missing some parts of that puzzle, for example it wouldn't make sense
> if __int128 is ever stored.
> 
> [1] https://www.postgresql.org/message-id/CA%2BhUKGLQUivg-NC7dHdbRAPmG0Hapg1gGnygM5KgDfDM2a_TMg%40mail.g...

These are some interesting ideas but I would consider them for now as
possible follow-up work, once this refactoring is merged.

--
David Geier





^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: Consistently use palloc_object() and palloc_array()
  2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
  2025-11-27 02:53 ` Re: Consistently use palloc_object() and palloc_array() Thomas Munro <thomas.munro@gmail.com>
@ 2025-12-03 19:11   ` Peter Eisentraut <peter@eisentraut.org>
  2 siblings, 0 replies; 29+ messages in thread

From: Peter Eisentraut @ 2025-12-03 19:11 UTC (permalink / raw)
  To: Thomas Munro <thomas.munro@gmail.com>; David Geier <geidav.pg@gmail.com>; +Cc: pgsql-hackers

On 27.11.25 03:53, Thomas Munro wrote:
> I wondered about this in the context of special alignment
> requirements[1].  palloc() aligns to MAXALIGN, which we artificially
> constrain for various reasons that we can't easily change (at least
> not without splitting on-disk MAXALIGN from allocation MAXALIGN, and
> if we do that we'll waste more memory).  That's less than
> alignof(max_align_t) on common systems, so then we have to do some
> weird stuff to handle __int128 that doesn't fit too well into modern
> <stdalign.h> thinking and also disables optimal codegen.

On macOS ARM, I have MAXALIGN == alignof(max_align_t) == 8, but 
alignof(__int128) == 16.  (macOS Intel has 16/16.)  Also, as a 
consequence of that, the result of malloc() is not guaranteed to be 
aligned sufficiently for __int128 (need to use aligned_alloc()).  So it 
seems to me that the current behavior of palloc() is pretty consistent 
with that.






^ permalink  raw  reply  [nested|flat] 29+ messages in thread


end of thread, other threads:[~2025-12-11 15:32 UTC | newest]

Thread overview: 29+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2025-11-26 22:09 Consistently use palloc_object() and palloc_array() David Geier <geidav.pg@gmail.com>
2025-11-26 23:03 ` Chao Li <li.evan.chao@gmail.com>
2025-11-28 21:06   ` David Geier <geidav.pg@gmail.com>
2025-11-28 21:28     ` Tom Lane <tgl@sss.pgh.pa.us>
2025-11-28 21:47       ` David Geier <geidav.pg@gmail.com>
2025-11-28 22:31         ` Thomas Munro <thomas.munro@gmail.com>
2025-12-02 15:13           ` David Geier <geidav.pg@gmail.com>
2025-12-03 00:35             ` Michael Paquier <michael@paquier.xyz>
2025-12-03 00:40               ` Tom Lane <tgl@sss.pgh.pa.us>
2025-12-04 09:31                 ` David Geier <geidav.pg@gmail.com>
2025-12-05 07:41                   ` Michael Paquier <michael@paquier.xyz>
2025-12-05 12:53                     ` David Geier <geidav.pg@gmail.com>
2025-12-05 14:47                       ` Tom Lane <tgl@sss.pgh.pa.us>
2025-12-11 07:54                         ` David Geier <geidav.pg@gmail.com>
2025-12-11 15:32                           ` Tom Lane <tgl@sss.pgh.pa.us>
2025-12-09 22:37                     ` Michael Paquier <michael@paquier.xyz>
2025-12-09 22:41                       ` Thomas Munro <thomas.munro@gmail.com>
2025-12-09 23:00                         ` Michael Paquier <michael@paquier.xyz>
2025-12-10 11:48                       ` David Geier <geidav.pg@gmail.com>
2025-12-10 23:01                         ` Michael Paquier <michael@paquier.xyz>
2025-12-11 05:33                           ` Michael Paquier <michael@paquier.xyz>
2025-12-11 08:06                             ` David Geier <geidav.pg@gmail.com>
2025-11-27 00:24 ` Michael Paquier <michael@paquier.xyz>
2025-11-28 21:33   ` David Geier <geidav.pg@gmail.com>
2025-11-27 02:53 ` Thomas Munro <thomas.munro@gmail.com>
2025-11-27 03:25   ` Tom Lane <tgl@sss.pgh.pa.us>
2025-11-27 05:18     ` Michael Paquier <michael@paquier.xyz>
2025-11-28 21:39   ` David Geier <geidav.pg@gmail.com>
2025-12-03 19:11   ` Peter Eisentraut <peter@eisentraut.org>

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox