In GCC-based builds, use a better newNode() macro that relies on GCC-specific
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 29 Aug 2008 22:49:07 +0000 (22:49 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 29 Aug 2008 22:49:07 +0000 (22:49 +0000)
syntax to avoid a useless store into a global variable.  Per experimentation,
this works better than my original thought of trying to push the code into
an out-of-line subroutine.

src/backend/nodes/nodes.c
src/include/nodes/nodes.h

index e81a7d53646aaddeb0c369237b2bce0672e74f65..b843d2081a09dd942ba2fc649e32b8397d75967d 100644 (file)
 
 /*
  * 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 745aae482d104a3a733ad55b81f54282b8a2b751..f365eacdbb5105315ce12f696b6ea0dace5be2a3 100644 (file)
@@ -384,6 +384,23 @@ 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
@@ -399,6 +416,8 @@ extern PGDLLIMPORT Node *newNodeMacroHolder;
        newNodeMacroHolder \
 )
 
+#endif   /* __GNUC__ */
+
 
 #define makeNode(_type_)               ((_type_ *) newNode(sizeof(_type_),T_##_type_))
 #define NodeSetTag(nodeptr,t)  (((Node*)(nodeptr))->type = (t))