Make type Datum be 8 bytes wide everywhere.

This patch makes sizeof(Datum) be 8 on all platforms including
32-bit ones.  The objective is to allow USE_FLOAT8_BYVAL to be true
everywhere, and in consequence to remove a lot of code that is
specific to pass-by-reference handling of float8, int8, etc.  The
code for abbreviated sort keys can be simplified similarly.  In this
way we can reduce the maintenance effort involved in supporting 32-bit
platforms, without going so far as to actually desupport them.  Since
Datum is strictly an in-memory concept, this has no impact on on-disk
storage, though an initdb or pg_upgrade will be needed to fix affected
catalog entries.

We have required platforms to support [u]int64 for ages, so this
breaks no supported platform.  We can expect that this change will
make 32-bit builds a bit slower and more memory-hungry, although being
able to use pass-by-value handling of 8-byte types may buy back some
of that.  But we stopped optimizing for 32-bit cases a long time ago,
and this seems like just another step on that path.

This initial patch simply forces the correct type definition and
USE_FLOAT8_BYVAL setting, and cleans up a couple of minor compiler
complaints that ensued.  This is sufficient for testing purposes.
In the wake of a bunch of Datum-conversion cleanups by Peter
Eisentraut, this now compiles cleanly with gcc on a 32-bit platform.
(I'd only tested the previous version with clang, which it turns out
is less picky than gcc about width-changing coercions.)

There is a good deal of now-dead code that I'll remove in separate
follow-up patches.

A catversion bump is required because this affects initial catalog
contents (on 32-bit machines) in two ways: pg_type.typbyval changes
for some built-in types, and Const nodes in stored views/rules will
now have 8 bytes not 4 for pass-by-value types.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://postgr.es/m/1749799.1752797397@sss.pgh.pa.us
pull/239/head
Tom Lane 1 month ago
parent 66f8765c53
commit 2a600a93c7
  1. 2
      src/backend/storage/ipc/ipc.c
  2. 7
      src/backend/utils/resowner/resowner.c
  3. 2
      src/include/catalog/catversion.h
  4. 8
      src/include/nodes/nodes.h
  5. 13
      src/include/pg_config_manual.h
  6. 21
      src/include/postgres.h

@ -399,7 +399,7 @@ cancel_before_shmem_exit(pg_on_exit_callback function, Datum arg)
before_shmem_exit_list[before_shmem_exit_index - 1].arg == arg) before_shmem_exit_list[before_shmem_exit_index - 1].arg == arg)
--before_shmem_exit_index; --before_shmem_exit_index;
else else
elog(ERROR, "before_shmem_exit callback (%p,0x%" PRIxPTR ") is not the latest entry", elog(ERROR, "before_shmem_exit callback (%p,0x%" PRIx64 ") is not the latest entry",
function, arg); function, arg);
} }

@ -231,11 +231,8 @@ hash_resource_elem(Datum value, const ResourceOwnerDesc *kind)
* 'kind' into the hash. Just add it with hash_combine(), it perturbs the * 'kind' into the hash. Just add it with hash_combine(), it perturbs the
* result enough for our purposes. * result enough for our purposes.
*/ */
#if SIZEOF_DATUM == 8 return hash_combine64(murmurhash64((uint64) value),
return hash_combine64(murmurhash64((uint64) value), (uint64) kind); (uint64) (uintptr_t) kind);
#else
return hash_combine(murmurhash32((uint32) value), (uint32) kind);
#endif
} }
/* /*

@ -57,6 +57,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 202508051 #define CATALOG_VERSION_NO 202508131
#endif #endif

@ -188,6 +188,8 @@ castNodeImpl(NodeTag type, void *ptr)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
#ifndef FRONTEND
/* /*
* nodes/{outfuncs.c,print.c} * nodes/{outfuncs.c,print.c}
*/ */
@ -198,7 +200,7 @@ extern void outNode(struct StringInfoData *str, const void *obj);
extern void outToken(struct StringInfoData *str, const char *s); extern void outToken(struct StringInfoData *str, const char *s);
extern void outBitmapset(struct StringInfoData *str, extern void outBitmapset(struct StringInfoData *str,
const struct Bitmapset *bms); const struct Bitmapset *bms);
extern void outDatum(struct StringInfoData *str, uintptr_t value, extern void outDatum(struct StringInfoData *str, Datum value,
int typlen, bool typbyval); int typlen, bool typbyval);
extern char *nodeToString(const void *obj); extern char *nodeToString(const void *obj);
extern char *nodeToStringWithLocations(const void *obj); extern char *nodeToStringWithLocations(const void *obj);
@ -212,7 +214,7 @@ extern void *stringToNode(const char *str);
extern void *stringToNodeWithLocations(const char *str); extern void *stringToNodeWithLocations(const char *str);
#endif #endif
extern struct Bitmapset *readBitmapset(void); extern struct Bitmapset *readBitmapset(void);
extern uintptr_t readDatum(bool typbyval); extern Datum readDatum(bool typbyval);
extern bool *readBoolCols(int numCols); extern bool *readBoolCols(int numCols);
extern int *readIntCols(int numCols); extern int *readIntCols(int numCols);
extern Oid *readOidCols(int numCols); extern Oid *readOidCols(int numCols);
@ -235,6 +237,8 @@ extern void *copyObjectImpl(const void *from);
*/ */
extern bool equal(const void *a, const void *b); extern bool equal(const void *a, const void *b);
#endif /* !FRONTEND */
/* /*
* Typedef for parse location. This is just an int, but this way * Typedef for parse location. This is just an int, but this way

@ -74,17 +74,12 @@
#define PARTITION_MAX_KEYS 32 #define PARTITION_MAX_KEYS 32
/* /*
* Decide whether built-in 8-byte types, including float8, int8, and * This symbol is now vestigial: built-in 8-byte types, including float8,
* timestamp, are passed by value. This is on by default if sizeof(Datum) >= * int8, and timestamp, are always passed by value since we require Datum
* 8 (that is, on 64-bit platforms). If sizeof(Datum) < 8 (32-bit platforms), * to be wide enough to permit that. We continue to define the symbol here
* this must be off. We keep this here as an option so that it is easy to * so as not to unnecessarily break extension code.
* test the pass-by-reference code paths on 64-bit platforms.
*
* Changing this requires an initdb.
*/ */
#if SIZEOF_VOID_P >= 8
#define USE_FLOAT8_BYVAL 1 #define USE_FLOAT8_BYVAL 1
#endif
/* /*

@ -58,15 +58,22 @@
/* /*
* A Datum contains either a value of a pass-by-value type or a pointer to a * A Datum contains either a value of a pass-by-value type or a pointer to a
* value of a pass-by-reference type. Therefore, we require: * value of a pass-by-reference type. Therefore, we must have
* * sizeof(Datum) >= sizeof(void *). No current or foreseeable Postgres
* sizeof(Datum) == sizeof(void *) == 4 or 8 * platform has pointers wider than 8 bytes, and standardizing on Datum being
* exactly 8 bytes has advantages in reducing cross-platform differences.
* *
* The functions below and the analogous functions for other types should be used to * The functions below and the analogous functions for other types should be used to
* convert between a Datum and the appropriate C type. * convert between a Datum and the appropriate C type.
*/ */
typedef uintptr_t Datum; typedef uint64_t Datum;
/*
* This symbol is now vestigial, but we continue to define it so as not to
* unnecessarily break extension code.
*/
#define SIZEOF_DATUM 8
/* /*
* A NullableDatum is used in places where both a Datum and its nullness needs * A NullableDatum is used in places where both a Datum and its nullness needs
@ -83,8 +90,6 @@ typedef struct NullableDatum
/* due to alignment padding this could be used for flags for free */ /* due to alignment padding this could be used for flags for free */
} NullableDatum; } NullableDatum;
#define SIZEOF_DATUM SIZEOF_VOID_P
/* /*
* DatumGetBool * DatumGetBool
* Returns boolean value of a datum. * Returns boolean value of a datum.
@ -316,7 +321,7 @@ CommandIdGetDatum(CommandId X)
static inline Pointer static inline Pointer
DatumGetPointer(Datum X) DatumGetPointer(Datum X)
{ {
return (Pointer) X; return (Pointer) (uintptr_t) X;
} }
/* /*
@ -326,7 +331,7 @@ DatumGetPointer(Datum X)
static inline Datum static inline Datum
PointerGetDatum(const void *X) PointerGetDatum(const void *X)
{ {
return (Datum) X; return (Datum) (uintptr_t) X;
} }
/* /*

Loading…
Cancel
Save