@@ -218,6 +218,8 @@ DoJumble(JumbleState *jstate, Node *node)
218
218
219
219
/*
220
220
* AppendJumbleInternal: Internal function for appending to the jumble buffer
221
+ *
222
+ * Note: Callers must ensure that size > 0.
221
223
*/
222
224
static pg_attribute_always_inline void
223
225
AppendJumbleInternal (JumbleState * jstate ,const unsignedchar * item ,
@@ -226,16 +228,36 @@ AppendJumbleInternal(JumbleState *jstate, const unsigned char *item,
226
228
unsignedchar * jumble = jstate -> jumble ;
227
229
Size jumble_len = jstate -> jumble_len ;
228
230
231
+ /* Ensure the caller didn't mess up */
232
+ Assert (size > 0 );
233
+
234
+ /*
235
+ * Fast path for when there's enough space left in the buffer. This is
236
+ * worthwhile as means the memcpy can be inlined into very efficient code
237
+ * when 'size' is a compile-time constant.
238
+ */
239
+ if (likely (size <=JUMBLE_SIZE - jumble_len ))
240
+ {
241
+ memcpy (jumble + jumble_len ,item ,size );
242
+ jstate -> jumble_len += size ;
243
+
244
+ #ifdef USE_ASSERT_CHECKING
245
+ jstate -> total_jumble_len += size ;
246
+ #endif
247
+
248
+ return ;
249
+ }
250
+
229
251
/*
230
252
* Whenever the jumble buffer is full, we hash the current contents and
231
253
* reset the buffer to contain just that hash value, thus relying on the
232
254
* hash to summarize everything so far.
233
255
*/
234
- while ( size > 0 )
256
+ do
235
257
{
236
258
Size part_size ;
237
259
238
- if (jumble_len >=JUMBLE_SIZE )
260
+ if (unlikely ( jumble_len >=JUMBLE_SIZE ) )
239
261
{
240
262
uint64 start_hash ;
241
263
@@ -253,7 +275,7 @@ AppendJumbleInternal(JumbleState *jstate, const unsigned char *item,
253
275
#ifdef USE_ASSERT_CHECKING
254
276
jstate -> total_jumble_len += part_size ;
255
277
#endif
256
- }
278
+ }while ( size > 0 );
257
279
258
280
jstate -> jumble_len = jumble_len ;
259
281
}
@@ -281,6 +303,61 @@ AppendJumbleNull(JumbleState *jstate)
281
303
jstate -> pending_nulls ++ ;
282
304
}
283
305
306
+ /*
307
+ * AppendJumble8
308
+ *Add the first byte from the given 'value' pointer to the jumble state
309
+ */
310
+ static pg_noinline void
311
+ AppendJumble8 (JumbleState * jstate ,const unsignedchar * value )
312
+ {
313
+ if (jstate -> pending_nulls > 0 )
314
+ FlushPendingNulls (jstate );
315
+
316
+ AppendJumbleInternal (jstate ,value ,1 );
317
+ }
318
+
319
+ /*
320
+ * AppendJumble16
321
+ *Add the first 2 bytes from the given 'value' pointer to the jumble
322
+ *state.
323
+ */
324
+ static pg_noinline void
325
+ AppendJumble16 (JumbleState * jstate ,const unsignedchar * value )
326
+ {
327
+ if (jstate -> pending_nulls > 0 )
328
+ FlushPendingNulls (jstate );
329
+
330
+ AppendJumbleInternal (jstate ,value ,2 );
331
+ }
332
+
333
+ /*
334
+ * AppendJumble32
335
+ *Add the first 4 bytes from the given 'value' pointer to the jumble
336
+ *state.
337
+ */
338
+ static pg_noinline void
339
+ AppendJumble32 (JumbleState * jstate ,const unsignedchar * value )
340
+ {
341
+ if (jstate -> pending_nulls > 0 )
342
+ FlushPendingNulls (jstate );
343
+
344
+ AppendJumbleInternal (jstate ,value ,4 );
345
+ }
346
+
347
+ /*
348
+ * AppendJumble64
349
+ *Add the first 8 bytes from the given 'value' pointer to the jumble
350
+ *state.
351
+ */
352
+ static pg_noinline void
353
+ AppendJumble64 (JumbleState * jstate ,const unsignedchar * value )
354
+ {
355
+ if (jstate -> pending_nulls > 0 )
356
+ FlushPendingNulls (jstate );
357
+
358
+ AppendJumbleInternal (jstate ,value ,8 );
359
+ }
360
+
284
361
/*
285
362
* FlushPendingNulls
286
363
*Incorporate the pending_null value into the jumble buffer.
@@ -417,9 +494,18 @@ IsSquashableConstList(List *elements, Node **firstExpr, Node **lastExpr)
417
494
#define JUMBLE_LOCATION (location ) \
418
495
RecordConstLocation(jstate, expr->location, false)
419
496
#define JUMBLE_FIELD (item ) \
420
- AppendJumble(jstate, (const unsigned char *) &(expr->item), sizeof(expr->item))
421
- #define JUMBLE_FIELD_SINGLE (item ) \
422
- AppendJumble(jstate, (const unsigned char *) &(item), sizeof(item))
497
+ do { \
498
+ if (sizeof(expr->item) == 8) \
499
+ AppendJumble64(jstate, (const unsigned char *) &(expr->item)); \
500
+ else if (sizeof(expr->item) == 4) \
501
+ AppendJumble32(jstate, (const unsigned char *) &(expr->item)); \
502
+ else if (sizeof(expr->item) == 2) \
503
+ AppendJumble16(jstate, (const unsigned char *) &(expr->item)); \
504
+ else if (sizeof(expr->item) == 1) \
505
+ AppendJumble8(jstate, (const unsigned char *) &(expr->item)); \
506
+ else \
507
+ AppendJumble(jstate, (const unsigned char *) &(expr->item), sizeof(expr->item)); \
508
+ } while (0)
423
509
#define JUMBLE_STRING (str ) \
424
510
do { \
425
511
if (expr->str) \
@@ -551,15 +637,15 @@ _jumbleList(JumbleState *jstate, Node *node)
551
637
break ;
552
638
case T_IntList :
553
639
foreach (l ,expr )
554
- JUMBLE_FIELD_SINGLE ( lfirst_int (l ));
640
+ AppendJumble32 ( jstate , ( const unsigned char * ) & lfirst_int (l ));
555
641
break ;
556
642
case T_OidList :
557
643
foreach (l ,expr )
558
- JUMBLE_FIELD_SINGLE ( lfirst_oid (l ));
644
+ AppendJumble32 ( jstate , ( const unsigned char * ) & lfirst_oid (l ));
559
645
break ;
560
646
case T_XidList :
561
647
foreach (l ,expr )
562
- JUMBLE_FIELD_SINGLE ( lfirst_xid (l ));
648
+ AppendJumble32 ( jstate , ( const unsigned char * ) & lfirst_xid (l ));
563
649
break ;
564
650
default :
565
651
elog (ERROR ,"unrecognized list node type: %d" ,