Content-Length: 859939 | pFad | http://github.com/tonybelloni/postgres/commit/101c7ee3ee847bac970c74b73b4f2858484383e5

8D Use new overflow aware integer operations. · tonybelloni/postgres@101c7ee · GitHub
Skip to content

Commit 101c7ee

Browse files
committed
Use new overflow aware integer operations.
A previous commit added inline functions that provide fast(er) and correct overflow checks for signed integer math. Use them in a significant portion of backend code. There's more to touch in both backend and frontend code, but these were the easily identifiable cases. The old overflow checks are noticeable in integer heavy workloads. A secondary benefit is that getting rid of overflow checks that rely on signed integer overflow wrapping around, will allow us to get rid of -fwrapv in the future. Which in turn slows down other code. Author: Andres Freund Discussion: https://postgr.es/m/20171024103954.ztmatprlglz3rwke@alap3.anarazel.de
1 parent 4d6ad31 commit 101c7ee

14 files changed

+217
-539
lines changed

contrib/btree_gist/btree_cash.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "btree_gist.h"
77
#include "btree_utils_num.h"
8+
#include "common/int.h"
89
#include "utils/cash.h"
910

1011
typedef struct
@@ -99,15 +100,14 @@ cash_dist(PG_FUNCTION_ARGS)
99100
Cash r;
100101
Cash ra;
101102

102-
r = a - b;
103-
ra = Abs(r);
104-
105-
/* Overflow check. */
106-
if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
103+
if (pg_sub_s64_overflow(a, b, &r) ||
104+
r == INT64_MIN)
107105
ereport(ERROR,
108106
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
109107
errmsg("money out of range")));
110108

109+
ra = Abs(r);
110+
111111
PG_RETURN_CASH(ra);
112112
}
113113

contrib/btree_gist/btree_int2.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "btree_gist.h"
77
#include "btree_utils_num.h"
8+
#include "common/int.h"
89

910
typedef struct int16key
1011
{
@@ -98,15 +99,14 @@ int2_dist(PG_FUNCTION_ARGS)
9899
int16 r;
99100
int16 ra;
100101

101-
r = a - b;
102-
ra = Abs(r);
103-
104-
/* Overflow check. */
105-
if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
102+
if (pg_sub_s16_overflow(a, b, &r) ||
103+
r == INT16_MIN)
106104
ereport(ERROR,
107105
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
108106
errmsg("smallint out of range")));
109107

108+
ra = Abs(r);
109+
110110
PG_RETURN_INT16(ra);
111111
}
112112

contrib/btree_gist/btree_int4.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "btree_gist.h"
77
#include "btree_utils_num.h"
8+
#include "common/int.h"
89

910
typedef struct int32key
1011
{
@@ -99,15 +100,14 @@ int4_dist(PG_FUNCTION_ARGS)
99100
int32 r;
100101
int32 ra;
101102

102-
r = a - b;
103-
ra = Abs(r);
104-
105-
/* Overflow check. */
106-
if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
103+
if (pg_sub_s32_overflow(a, b, &r) ||
104+
r == INT32_MIN)
107105
ereport(ERROR,
108106
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
109107
errmsg("integer out of range")));
110108

109+
ra = Abs(r);
110+
111111
PG_RETURN_INT32(ra);
112112
}
113113

contrib/btree_gist/btree_int8.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "btree_gist.h"
77
#include "btree_utils_num.h"
8+
#include "common/int.h"
89

910
typedef struct int64key
1011
{
@@ -99,15 +100,14 @@ int8_dist(PG_FUNCTION_ARGS)
99100
int64 r;
100101
int64 ra;
101102

102-
r = a - b;
103-
ra = Abs(r);
104-
105-
/* Overflow check. */
106-
if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
103+
if (pg_sub_s64_overflow(a, b, &r) ||
104+
r == INT64_MIN)
107105
ereport(ERROR,
108106
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
109107
errmsg("bigint out of range")));
110108

109+
ra = Abs(r);
110+
111111
PG_RETURN_INT64(ra);
112112
}
113113

contrib/btree_gist/btree_utils_num.h

-2
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@ typedef struct
8989

9090
#define GET_FLOAT_DISTANCE(t, arg1, arg2) Abs( ((float8) *((const t *) (arg1))) - ((float8) *((const t *) (arg2))) )
9191

92-
#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
93-
9492
/*
9593
* check to see if a float4/8 val has underflowed or overflowed
9694
* borrowed from src/backend/utils/adt/float.c

src/backend/utils/adt/array_userfuncs.c

+4-9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "postgres.h"
1414

1515
#include "catalog/pg_type.h"
16+
#include "common/int.h"
1617
#include "utils/array.h"
1718
#include "utils/builtins.h"
1819
#include "utils/lsyscache.h"
@@ -118,15 +119,11 @@ array_append(PG_FUNCTION_ARGS)
118119
if (eah->ndims == 1)
119120
{
120121
/* append newelem */
121-
int ub;
122-
123122
lb = eah->lbound;
124123
dimv = eah->dims;
125-
ub = dimv[0] + lb[0] - 1;
126-
indx = ub + 1;
127124

128-
/* overflow? */
129-
if (indx < ub)
125+
/* index of added elem is at lb[0] + (dimv[0] - 1) + 1 */
126+
if (pg_add_s32_overflow(lb[0], dimv[0], &indx))
130127
ereport(ERROR,
131128
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
132129
errmsg("integer out of range")));
@@ -176,11 +173,9 @@ array_prepend(PG_FUNCTION_ARGS)
176173
{
177174
/* prepend newelem */
178175
lb = eah->lbound;
179-
indx = lb[0] - 1;
180176
lb0 = lb[0];
181177

182-
/* overflow? */
183-
if (indx > lb[0])
178+
if (pg_sub_s32_overflow(lb0, 1, &indx))
184179
ereport(ERROR,
185180
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
186181
errmsg("integer out of range")));

src/backend/utils/adt/cash.c

+19-20
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <ctype.h>
2323
#include <math.h>
2424

25+
#include "common/int.h"
2526
#include "libpq/pqformat.h"
2627
#include "utils/builtins.h"
2728
#include "utils/cash.h"
@@ -199,20 +200,21 @@ cash_in(PG_FUNCTION_ARGS)
199200

200201
for (; *s; s++)
201202
{
202-
/* we look for digits as long as we have found less */
203-
/* than the required number of decimal places */
203+
/*
204+
* We look for digits as long as we have found less than the required
205+
* number of decimal places.
206+
*/
204207
if (isdigit((unsigned char) *s) && (!seen_dot || dec < fpoint))
205208
{
206-
Cash newvalue = (value * 10) - (*s - '0');
209+
int8 digit = *s - '0';
207210

208-
if (newvalue / 10 != value)
211+
if (pg_mul_s64_overflow(value, 10, &value) ||
212+
pg_sub_s64_overflow(value, digit, &value))
209213
ereport(ERROR,
210214
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
211215
errmsg("value \"%s\" is out of range for type %s",
212216
str, "money")));
213217

214-
value = newvalue;
215-
216218
if (seen_dot)
217219
dec++;
218220
}
@@ -230,26 +232,23 @@ cash_in(PG_FUNCTION_ARGS)
230232

231233
/* round off if there's another digit */
232234
if (isdigit((unsigned char) *s) && *s >= '5')
233-
value--; /* remember we build the value in the negative */
234-
235-
if (value > 0)
236-
ereport(ERROR,
237-
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
238-
errmsg("value \"%s\" is out of range for type %s",
239-
str, "money")));
235+
{
236+
/* remember we build the value in the negative */
237+
if (pg_sub_s64_overflow(value, 1, &value))
238+
ereport(ERROR,
239+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
240+
errmsg("value \"%s\" is out of range for type %s",
241+
str, "money")));
242+
}
240243

241244
/* adjust for less than required decimal places */
242245
for (; dec < fpoint; dec++)
243246
{
244-
Cash newvalue = value * 10;
245-
246-
if (newvalue / 10 != value)
247+
if (pg_mul_s64_overflow(value, 10, &value))
247248
ereport(ERROR,
248249
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
249250
errmsg("value \"%s\" is out of range for type %s",
250251
str, "money")));
251-
252-
value = newvalue;
253252
}
254253

255254
/*
@@ -285,12 +284,12 @@ cash_in(PG_FUNCTION_ARGS)
285284
*/
286285
if (sgn > 0)
287286
{
288-
result = -value;
289-
if (result < 0)
287+
if (value == PG_INT64_MIN)
290288
ereport(ERROR,
291289
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
292290
errmsg("value \"%s\" is out of range for type %s",
293291
str, "money")));
292+
result = -value;
294293
}
295294
else
296295
result = value;

src/backend/utils/adt/float.c

+3-6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <limits.h>
2121

2222
#include "catalog/pg_type.h"
23+
#include "common/int.h"
2324
#include "libpq/pqformat.h"
2425
#include "utils/array.h"
2526
#include "utils/builtins.h"
@@ -3548,9 +3549,7 @@ width_bucket_float8(PG_FUNCTION_ARGS)
35483549
result = 0;
35493550
else if (operand >= bound2)
35503551
{
3551-
result = count + 1;
3552-
/* check for overflow */
3553-
if (result < count)
3552+
if (pg_add_s32_overflow(count, 1, &result))
35543553
ereport(ERROR,
35553554
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
35563555
errmsg("integer out of range")));
@@ -3564,9 +3563,7 @@ width_bucket_float8(PG_FUNCTION_ARGS)
35643563
result = 0;
35653564
else if (operand <= bound2)
35663565
{
3567-
result = count + 1;
3568-
/* check for overflow */
3569-
if (result < count)
3566+
if (pg_add_s32_overflow(count, 1, &result))
35703567
ereport(ERROR,
35713568
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
35723569
errmsg("integer out of range")));

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/tonybelloni/postgres/commit/101c7ee3ee847bac970c74b73b4f2858484383e5

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy