*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/nodes.c,v 1.18 2002/11/10 02:17:25 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/nodes.c,v 1.19 2002/12/16 16:22:46 tgl Exp $
*
* HISTORY
* Andrew Yu Oct 20, 1994 file creation
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+
#include "nodes/nodes.h"
/*
- * newNode -
- * create a new node of the specified size and tag the node with the
- * specified tag.
- *
- * !WARNING!: Avoid using newNode directly. You should be using the
- * macro makeNode. eg. to create a Resdom node, use makeNode(Resdom)
- *
+ * Support for newNode() macro
*/
-Node *newNodeMacroHolder;
+Node *newNodeMacroHolder;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.37 2002/12/15 21:01:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.38 2002/12/16 16:22:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
pointer);
}
+/*
+ * GetMemoryChunkContext
+ * Given a currently-allocated chunk, determine the context
+ * it belongs to.
+ */
+MemoryContext
+GetMemoryChunkContext(void *pointer)
+{
+ StandardChunkHeader *header;
+
+ /*
+ * Try to detect bogus pointers handed to us, poorly though we can.
+ * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
+ * allocated chunk.
+ */
+ Assert(pointer != NULL);
+ Assert(pointer == (void *) MAXALIGN(pointer));
+
+ /*
+ * OK, it's probably safe to look at the chunk header.
+ */
+ header = (StandardChunkHeader *)
+ ((char *) pointer - STANDARDCHUNKHEADERSIZE);
+
+ AssertArg(MemoryContextIsValid(header->context));
+
+ return header->context;
+}
+
/*
* MemoryContextStats
* Print statistics about the named context and all its descendants.
}
/*
- * MemoryContextAllocPalloc0
+ * MemoryContextAllocZero
* Like MemoryContextAlloc, but clears allocated memory
*
* We could just call MemoryContextAlloc then clear the memory, but this
- * function is called too many times, so we have a separate version.
+ * is a very common combination, so we provide the combined operation.
*/
void *
-MemoryContextAllocPalloc0(MemoryContext context, Size size)
+MemoryContextAllocZero(MemoryContext context, Size size)
{
void *ret;
AssertArg(MemoryContextIsValid(context));
if (!AllocSizeIsValid(size))
- elog(ERROR, "MemoryContextAllocZero: invalid request size %lu",
+ elog(ERROR, "MemoryContextAlloc: invalid request size %lu",
(unsigned long) size);
ret = (*context->methods->alloc) (context, size);
+
+ MemSetAligned(ret, 0, 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;
+
+ AssertArg(MemoryContextIsValid(context));
+
+ if (!AllocSizeIsValid(size))
+ elog(ERROR, "MemoryContextAlloc: invalid request size %lu",
+ (unsigned long) size);
+
+ ret = (*context->methods->alloc) (context, size);
+
MemSetLoop(ret, 0, size);
+
return ret;
}
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: c.h,v 1.133 2002/12/05 04:04:48 momjian Exp $
+ * $Id: c.h,v 1.134 2002/12/16 16:22:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* memset() functions. More research needs to be done, perhaps with
* platform-specific MEMSET_LOOP_LIMIT values or tests in configure.
*
- * MemSet has been split into two parts so MemSetTest can be optimized
- * away for constant 'val' and 'len'. This is used by palloc0().
- *
- * Note, arguments are evaluated more than once.
- *
* bjm 2002-10-08
*/
+#define MemSet(start, val, len) \
+ do \
+ { \
+ int32 * _start = (int32 *) (start); \
+ int _val = (val); \
+ Size _len = (len); \
+\
+ if ((((long) _start) & INT_ALIGN_MASK) == 0 && \
+ (_len & INT_ALIGN_MASK) == 0 && \
+ _val == 0 && \
+ _len <= MEMSET_LOOP_LIMIT) \
+ { \
+ int32 * _stop = (int32 *) ((char *) _start + _len); \
+ while (_start < _stop) \
+ *_start++ = 0; \
+ } \
+ else \
+ memset((char *) _start, _val, _len); \
+ } while (0)
+
+#define MEMSET_LOOP_LIMIT 1024
+
+/*
+ * MemSetAligned is the same as MemSet except it omits the test to see if
+ * "start" is word-aligned. This is okay to use if the caller knows a-priori
+ * that the pointer is suitably aligned (typically, because he just got it
+ * from palloc(), which always delivers a max-aligned pointer).
+ */
+#define MemSetAligned(start, val, len) \
+ do \
+ { \
+ int32 * _start = (int32 *) (start); \
+ int _val = (val); \
+ Size _len = (len); \
+\
+ if ((_len & INT_ALIGN_MASK) == 0 && \
+ _val == 0 && \
+ _len <= MEMSET_LOOP_LIMIT) \
+ { \
+ int32 * _stop = (int32 *) ((char *) _start + _len); \
+ while (_start < _stop) \
+ *_start++ = 0; \
+ } \
+ else \
+ memset((char *) _start, _val, _len); \
+ } 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) & INT_ALIGN_MASK) == 0 && \
(len) <= MEMSET_LOOP_LIMIT && \
(val) == 0 )
#define MemSetLoop(start, val, len) \
-do \
-{ \
- int32 * _start = (int32 *) (start); \
- int32 * _stop = (int32 *) ((char *) _start + (len)); \
-\
- while (_start < _stop) \
- *_start++ = 0; \
-} while (0)
-
-#define MemSet(start, val, len) \
-do \
-{ \
- if (MemSetTest(val, len) && ((long)(start) & INT_ALIGN_MASK) == 0 ) \
- MemSetLoop(start, val, len); \
- else \
- memset((char *)(start), (val), (len)); \
-} while (0)
-
-#define MEMSET_LOOP_LIMIT 1024
+ do \
+ { \
+ int32 * _start = (int32 *) (start); \
+ int32 * _stop = (int32 *) ((char *) _start + (Size) (len)); \
+ \
+ while (_start < _stop) \
+ *_start++ = 0; \
+ } while (0)
/* ----------------------------------------------------------------
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodes.h,v 1.133 2002/12/14 00:17:59 tgl Exp $
+ * $Id: nodes.h,v 1.134 2002/12/16 16:22:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#define nodeTag(nodeptr) (((Node*)(nodeptr))->type)
/*
+ * newNode -
+ * create a new node of the specified size and tag the node with the
+ * specified tag.
+ *
+ * !WARNING!: Avoid using newNode directly. You should be using the
+ * macro makeNode. eg. to create a Query node, use makeNode(Query)
+ *
* There is no way to dereference the palloc'ed pointer to assign the
- * tag, and return the pointer itself, so we need a holder variable.
- * Fortunately, this function isn't recursive so we just define
+ * 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 Node *newNodeMacroHolder;
#define newNode(size, tag) \
( \
AssertMacro((size) >= sizeof(Node)), /* need the tag, at least */ \
-\
- newNodeMacroHolder = (Node *) palloc0(size), \
+ newNodeMacroHolder = (Node *) palloc0fast(size), \
newNodeMacroHolder->type = (tag), \
newNodeMacroHolder \
)
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: memutils.h,v 1.49 2002/12/15 21:01:34 tgl Exp $
+ * $Id: memutils.h,v 1.50 2002/12/16 16:22:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void MemoryContextDeleteChildren(MemoryContext context);
extern void MemoryContextResetAndDeleteChildren(MemoryContext context);
extern Size GetMemoryChunkSpace(void *pointer);
+extern MemoryContext GetMemoryChunkContext(void *pointer);
extern void MemoryContextStats(MemoryContext context);
#ifdef MEMORY_CONTEXT_CHECKING
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: palloc.h,v 1.23 2002/11/13 00:37:06 momjian Exp $
+ * $Id: palloc.h,v 1.24 2002/12/16 16:22:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* Fundamental memory-allocation operations (more are in utils/memutils.h)
*/
extern void *MemoryContextAlloc(MemoryContext context, Size size);
-extern void *MemoryContextAllocPalloc0(MemoryContext context, Size size);
+extern void *MemoryContextAllocZero(MemoryContext context, Size size);
+extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
#define palloc(sz) MemoryContextAlloc(CurrentMemoryContext, (sz))
-/* We assume palloc() is already int-aligned */
-#define palloc0(sz) \
- ( MemSetTest(0, (sz)) ? \
- MemoryContextAllocPalloc0(CurrentMemoryContext, (sz)) : \
- memset(palloc(sz), 0, (sz)))
+#define palloc0(sz) MemoryContextAllocZero(CurrentMemoryContext, (sz))
+
+/*
+ * 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) )
extern void pfree(void *pointer);