Simplify newNode() by removing special cases
authorHeikki Linnakangas <[email protected]>
Tue, 19 Dec 2023 10:11:47 +0000 (12:11 +0200)
committerHeikki Linnakangas <[email protected]>
Tue, 19 Dec 2023 10:11:47 +0000 (12:11 +0200)
- 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

src/backend/nodes/Makefile
src/backend/nodes/meson.build
src/backend/nodes/nodes.c [deleted file]
src/backend/utils/mmgr/mcxt.c
src/include/c.h
src/include/nodes/nodes.h
src/include/utils/palloc.h

index ebbe9052cb76693caf915bb059a3595d08484667..66bbad8e6e02d522bef5c76bf7e3cc08e59efc9d 100644 (file)
@@ -23,7 +23,6 @@ OBJS = \
    makefuncs.o \
    multibitmapset.o \
    nodeFuncs.o \
-   nodes.o \
    outfuncs.o \
    params.o \
    print.o \
index 31467a12d3b5925caec141e99f0191e83fed764e..1efbf2c11ca257fd857b7a050ec92f863fe12575 100644 (file)
@@ -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 (file)
index 1913a4b..0000000
+++ /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;
index 9fc83f11f6f1ff6b56d62eaf4a28af7cfd54779f..4b30fcaebd0f4e422be61619749316f45beae7f4 100644 (file)
@@ -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.
index 4b0f5138d83900d180bfa5820c776a7926ec7ee1..26bf7ec16e7dfd5b8f6c923c9f4e02c6bf09e126 100644 (file)
@@ -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
index a178d08727ab9aa282ef4db89cbc00146313479a..50b025cd8a45393433605b4717dd593ed3125014 100644 (file)
@@ -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))
index d1146c123510436f5264e5d6cfff39e86347ab78..cf98ddc0ec90c8fc2f4b4339577f8e2746c2f7ed 100644 (file)
@@ -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);