From: Heikki Linnakangas Date: Tue, 19 Dec 2023 10:11:47 +0000 (+0200) Subject: Simplify newNode() by removing special cases X-Git-Tag: REL_17_BETA1~1279 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=3c080fb4fad3e1c1e34f74a7b84a443137adc9f2;p=postgresql.git Simplify newNode() by removing special cases - Remove MemoryContextAllocZeroAligned(). It was supposed to be a faster version of MemoryContextAllocZero(), but modern compilers turn the MemSetLoop() into a call to memset() anyway, making it more or less identical to MemoryContextAllocZero(). That was the only user of MemSetTest, MemSetLoop, so remove those too, as well as palloc0fast(). - Convert newNode() to a static inline function. When this was originally originally written, it was written as a macro because testing showed that gcc didn't inline the size check as we intended. Modern compiler versions do, and now that it just calls palloc0() there is no size-check to inline anyway. One nice effect is that the palloc0() takes one less argument than MemoryContextAllocZeroAligned(), which saves a few instructions in the callers of newNode(). Reviewed-by: Peter Eisentraut, Tom Lane, John Naylor, Thomas Munro Discussion: https://www.postgresql.org/message-id/b51f1fa7-7e6a-4ecc-936d-90a8a1659e7c@iki.fi --- diff --git a/src/backend/nodes/Makefile b/src/backend/nodes/Makefile index ebbe9052cb7..66bbad8e6e0 100644 --- a/src/backend/nodes/Makefile +++ b/src/backend/nodes/Makefile @@ -23,7 +23,6 @@ OBJS = \ makefuncs.o \ multibitmapset.o \ nodeFuncs.o \ - nodes.o \ outfuncs.o \ params.o \ print.o \ diff --git a/src/backend/nodes/meson.build b/src/backend/nodes/meson.build index 31467a12d3b..1efbf2c11ca 100644 --- a/src/backend/nodes/meson.build +++ b/src/backend/nodes/meson.build @@ -7,7 +7,6 @@ backend_sources += files( 'makefuncs.c', 'multibitmapset.c', 'nodeFuncs.c', - 'nodes.c', 'params.c', 'print.c', 'read.c', diff --git a/src/backend/nodes/nodes.c b/src/backend/nodes/nodes.c deleted file mode 100644 index 1913a4bdf7d..00000000000 --- a/src/backend/nodes/nodes.c +++ /dev/null @@ -1,31 +0,0 @@ -/*------------------------------------------------------------------------- - * - * nodes.c - * support code for nodes (now that we have removed the home-brew - * inheritance system, our support code for nodes is much simpler) - * - * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/backend/nodes/nodes.c - * - * HISTORY - * Andrew Yu Oct 20, 1994 file creation - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "nodes/nodes.h" - -/* - * Support for newNode() macro - * - * In a GCC build there is no need for the global variable newNodeMacroHolder. - * However, we create it anyway, to support the case of a non-GCC-built - * loadable module being loaded into a GCC-built backend. - */ - -Node *newNodeMacroHolder; diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index 9fc83f11f6f..4b30fcaebd0 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -1091,44 +1091,6 @@ MemoryContextAllocZero(MemoryContext context, Size size) return ret; } -/* - * MemoryContextAllocZeroAligned - * MemoryContextAllocZero where length is suitable for MemSetLoop - * - * This might seem overly specialized, but it's not because newNode() - * is so often called with compile-time-constant sizes. - */ -void * -MemoryContextAllocZeroAligned(MemoryContext context, Size size) -{ - void *ret; - - Assert(MemoryContextIsValid(context)); - AssertNotInCriticalSection(context); - - if (!AllocSizeIsValid(size)) - elog(ERROR, "invalid memory alloc request size %zu", size); - - context->isReset = false; - - ret = context->methods->alloc(context, size); - if (unlikely(ret == NULL)) - { - MemoryContextStats(TopMemoryContext); - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"), - errdetail("Failed on request of size %zu in memory context \"%s\".", - size, context->name))); - } - - VALGRIND_MEMPOOL_ALLOC(context, ret, size); - - MemSetLoop(ret, 0, size); - - return ret; -} - /* * MemoryContextAllocExtended * Allocate space within the specified context using the given flags. diff --git a/src/include/c.h b/src/include/c.h index 4b0f5138d83..26bf7ec16e7 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -1060,30 +1060,6 @@ extern void ExceptionalCondition(const char *conditionName, } while (0) -/* - * MemSetTest/MemSetLoop are a variant version that allow all the tests in - * MemSet to be done at compile time in cases where "val" and "len" are - * constants *and* we know the "start" pointer must be word-aligned. - * If MemSetTest succeeds, then it is okay to use MemSetLoop, otherwise use - * MemSetAligned. Beware of multiple evaluations of the arguments when using - * this approach. - */ -#define MemSetTest(val, len) \ - ( ((len) & LONG_ALIGN_MASK) == 0 && \ - (len) <= MEMSET_LOOP_LIMIT && \ - MEMSET_LOOP_LIMIT != 0 && \ - (val) == 0 ) - -#define MemSetLoop(start, val, len) \ - do \ - { \ - long * _start = (long *) (start); \ - long * _stop = (long *) ((char *) _start + (Size) (len)); \ - \ - while (_start < _stop) \ - *_start++ = 0; \ - } while (0) - /* * Macros for range-checking float values before converting to integer. * We must be careful here that the boundary values are expressed exactly diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index a178d08727a..50b025cd8a4 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -139,39 +139,18 @@ typedef struct Node * * !WARNING!: Avoid using newNode directly. You should be using the * macro makeNode. eg. to create a Query node, use makeNode(Query) - * - * Note: the size argument should always be a compile-time constant, so the - * apparent risk of multiple evaluation doesn't matter in practice. - */ -#ifdef __GNUC__ - -/* With GCC, we can use a compound statement within an expression */ -#define newNode(size, tag) \ -({ Node *_result; \ - AssertMacro((size) >= sizeof(Node)); /* need the tag, at least */ \ - _result = (Node *) palloc0fast(size); \ - _result->type = (tag); \ - _result; \ -}) -#else - -/* - * There is no way to dereference the palloc'ed pointer to assign the - * tag, and also return the pointer itself, so we need a holder variable. - * Fortunately, this macro isn't recursive so we just define - * a global variable for this purpose. */ -extern PGDLLIMPORT Node *newNodeMacroHolder; +static inline Node * +newNode(size_t size, NodeTag tag) +{ + Node *result; -#define newNode(size, tag) \ -( \ - AssertMacro((size) >= sizeof(Node)), /* need the tag, at least */ \ - newNodeMacroHolder = (Node *) palloc0fast(size), \ - newNodeMacroHolder->type = (tag), \ - newNodeMacroHolder \ -) -#endif /* __GNUC__ */ + Assert(size >= sizeof(Node)); /* need the tag, at least */ + result = (Node *) palloc0(size); + result->type = tag; + return result; +} #define makeNode(_type_) ((_type_ *) newNode(sizeof(_type_),T_##_type_)) #define NodeSetTag(nodeptr,t) (((Node*)(nodeptr))->type = (t)) diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h index d1146c12351..cf98ddc0ec9 100644 --- a/src/include/utils/palloc.h +++ b/src/include/utils/palloc.h @@ -70,7 +70,6 @@ extern PGDLLIMPORT MemoryContext CurrentMemoryContext; */ extern void *MemoryContextAlloc(MemoryContext context, Size size); extern void *MemoryContextAllocZero(MemoryContext context, Size size); -extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size); extern void *MemoryContextAllocExtended(MemoryContext context, Size size, int flags); extern void *MemoryContextAllocAligned(MemoryContext context, @@ -109,19 +108,6 @@ extern void pfree(void *pointer); #define repalloc_array(pointer, type, count) ((type *) repalloc(pointer, sizeof(type) * (count))) #define repalloc0_array(pointer, type, oldcount, count) ((type *) repalloc0(pointer, sizeof(type) * (oldcount), sizeof(type) * (count))) -/* - * The result of palloc() is always word-aligned, so we can skip testing - * alignment of the pointer when deciding which MemSet variant to use. - * Note that this variant does not offer any advantage, and should not be - * used, unless its "sz" argument is a compile-time constant; therefore, the - * issue that it evaluates the argument multiple times isn't a problem in - * practice. - */ -#define palloc0fast(sz) \ - ( MemSetTest(0, sz) ? \ - MemoryContextAllocZeroAligned(CurrentMemoryContext, sz) : \ - MemoryContextAllocZero(CurrentMemoryContext, sz) ) - /* Higher-limit allocators. */ extern void *MemoryContextAllocHuge(MemoryContext context, Size size); extern pg_nodiscard void *repalloc_huge(void *pointer, Size size);