diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h index 134c37c8030..3c150d6601d 100644 --- a/innobase/include/rem0rec.h +++ b/innobase/include/rem0rec.h @@ -51,7 +51,7 @@ rec_get_next_offs( /* out: the page offset of the next chained record */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the next record offset field of the record. */ @@ -60,7 +60,7 @@ void rec_set_next_offs( /*==============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint next); /* in: offset of the next record */ /********************************************************** The following function is used to get the number of fields @@ -90,7 +90,7 @@ rec_get_n_owned( /*============*/ /* out: number of owned records */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the number of owned records. */ @@ -99,7 +99,7 @@ void rec_set_n_owned( /*============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint n_owned); /* in: the number of owned */ /********************************************************** The following function is used to retrieve the info bits of @@ -110,7 +110,7 @@ rec_get_info_bits( /*==============*/ /* out: info bits */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the info bits of a record. */ UNIV_INLINE @@ -118,7 +118,7 @@ void rec_set_info_bits( /*==============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint bits); /* in: info bits */ /********************************************************** The following function retrieves the status bits of a new-style record. */ @@ -147,7 +147,7 @@ rec_get_info_and_status_bits( /*=========================*/ /* out: info bits */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the info and status bits of a record. (Only compact records have status bits.) */ @@ -156,7 +156,7 @@ void rec_set_info_and_status_bits( /*=========================*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint bits); /* in: info bits */ /********************************************************** @@ -167,7 +167,7 @@ rec_get_deleted_flag( /*=================*/ /* out: TRUE if delete marked */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the deleted bit. */ UNIV_INLINE @@ -175,7 +175,7 @@ void rec_set_deleted_flag( /*=================*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ibool flag); /* in: TRUE if delete marked */ /********************************************************** The following function tells if a new-style record is a node pointer. */ @@ -186,14 +186,6 @@ rec_get_node_ptr_flag( /* out: TRUE if node pointer */ rec_t* rec); /* in: physical record */ /********************************************************** -The following function is used to flag a record as a node pointer. */ -UNIV_INLINE -void -rec_set_node_ptr_flag( -/*=================*/ - rec_t* rec, /* in: physical record */ - ibool flag); /* in: TRUE if the record is a node pointer */ -/********************************************************** The following function is used to get the order number of the record in the heap of the index page. */ UNIV_INLINE @@ -202,7 +194,7 @@ rec_get_heap_no( /*=============*/ /* out: heap order number */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the heap number field in the record. */ @@ -211,7 +203,7 @@ void rec_set_heap_no( /*=============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint heap_no);/* in: the heap number */ /********************************************************** The following function is used to test whether the data offsets @@ -305,7 +297,7 @@ rec_get_nth_field( Determine if the offsets are for a record in the new compact format. */ UNIV_INLINE -ibool +ulint rec_offs_comp( /*==========*/ /* out: TRUE if compact format */ diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 2593fb8edeb..cd742aef6a6 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -265,7 +265,7 @@ rec_get_next_offs( /* out: the page offset of the next chained record, or 0 if none */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { ulint field_value; @@ -312,7 +312,7 @@ void rec_set_next_offs( /*==============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint next) /* in: offset of the next record, or 0 if none */ { ut_ad(rec); @@ -414,7 +414,7 @@ rec_get_n_fields( { ut_ad(rec); ut_ad(index); - if (!index->table->comp) { + if (UNIV_UNLIKELY(!index->table->comp)) { return(rec_get_n_fields_old(rec)); } switch (rec_get_status(rec)) { @@ -440,7 +440,7 @@ rec_get_n_owned( /*============*/ /* out: number of owned records */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { ulint ret; @@ -461,7 +461,7 @@ void rec_set_n_owned( /*============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint n_owned) /* in: the number of owned */ { ut_ad(rec); @@ -480,7 +480,7 @@ rec_get_info_bits( /*==============*/ /* out: info bits */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { ulint ret; @@ -501,7 +501,7 @@ void rec_set_info_bits( /*==============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint bits) /* in: info bits */ { ut_ad(rec); @@ -537,14 +537,14 @@ rec_get_info_and_status_bits( /*=========================*/ /* out: info bits */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { ulint bits; #if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \ & (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT) # error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap" #endif - if (comp) { + if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) { bits = rec_get_info_bits(rec, TRUE) | rec_get_status(rec); } else { bits = rec_get_info_bits(rec, FALSE); @@ -560,7 +560,7 @@ void rec_set_info_and_status_bits( /*=========================*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint bits) /* in: info bits */ { #if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \ @@ -583,14 +583,15 @@ rec_get_deleted_flag( /*=================*/ /* out: TRUE if delete marked */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { - if (REC_INFO_DELETED_FLAG & rec_get_info_bits(rec, comp)) { - - return(TRUE); + if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) { + return(0 != rec_get_bit_field_1(rec, REC_NEW_INFO_BITS, + REC_INFO_DELETED_FLAG, REC_INFO_BITS_SHIFT)); + } else { + return(0 != rec_get_bit_field_1(rec, REC_OLD_INFO_BITS, + REC_INFO_DELETED_FLAG, REC_INFO_BITS_SHIFT)); } - - return(FALSE); } /********************************************************** @@ -600,24 +601,23 @@ void rec_set_deleted_flag( /*=================*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ibool flag) /* in: TRUE if delete marked */ { - ulint old_val; - ulint new_val; + ulint val; ut_ad(TRUE == 1); ut_ad(flag <= TRUE); - old_val = rec_get_info_bits(rec, comp); + val = rec_get_info_bits(rec, comp); if (flag) { - new_val = REC_INFO_DELETED_FLAG | old_val; + val |= REC_INFO_DELETED_FLAG; } else { - new_val = ~REC_INFO_DELETED_FLAG & old_val; + val &= ~REC_INFO_DELETED_FLAG; } - rec_set_info_bits(rec, comp, new_val); + rec_set_info_bits(rec, comp, val); } /********************************************************** @@ -632,26 +632,6 @@ rec_get_node_ptr_flag( return(REC_STATUS_NODE_PTR == rec_get_status(rec)); } -/********************************************************** -The following function is used to flag a record as a node pointer. */ -UNIV_INLINE -void -rec_set_node_ptr_flag( -/*=================*/ - rec_t* rec, /* in: physical record */ - ibool flag) /* in: TRUE if the record is a node pointer */ -{ - ulint status; - ut_ad(flag <= TRUE); - ut_ad(REC_STATUS_NODE_PTR >= rec_get_status(rec)); - if (flag) { - status = REC_STATUS_NODE_PTR; - } else { - status = REC_STATUS_ORDINARY; - } - rec_set_status(rec, status); -} - /********************************************************** The following function is used to get the order number of the record in the heap of the index page. */ @@ -661,7 +641,7 @@ rec_get_heap_no( /*=============*/ /* out: heap order number */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { ulint ret; @@ -682,7 +662,7 @@ void rec_set_heap_no( /*=============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint heap_no)/* in: the heap number */ { ut_ad(heap_no <= REC_MAX_HEAP_NO); @@ -843,7 +823,7 @@ rec_offs_validate( { ulint i = rec_offs_n_fields(offsets); ulint last = ULINT_MAX; - ibool comp = (*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0; + ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT; if (rec) { ut_ad((ulint) rec == offsets[2]); @@ -926,7 +906,7 @@ rec_get_nth_field( ut_ad(n < rec_offs_n_fields(offsets)); ut_ad(len); - if (n == 0) { + if (UNIV_UNLIKELY(n == 0)) { field = rec; } else { field = rec + (rec_offs_base(offsets)[n] & REC_OFFS_MASK); @@ -1037,7 +1017,7 @@ rec_set_nth_field_extern_bit( where rec is, or NULL; in the NULL case we do not write to log about the change */ { - if (index->table->comp) { + if (UNIV_LIKELY(index->table->comp)) { rec_set_nth_field_extern_bit_new(rec, index, i, val, mtr); } else { rec_set_nth_field_extern_bit_old(rec, i, val, mtr); @@ -1048,7 +1028,7 @@ rec_set_nth_field_extern_bit( Returns the offset of n - 1th field end if the record is stored in the 1-byte offsets form. If the field is SQL null, the flag is ORed in the returned value. This function and the 2-byte counterpart are defined here because the -C-compilerwas not able to sum negative and positive constant offsets, and +C-compiler was not able to sum negative and positive constant offsets, and warned of constant arithmetic overflow within the compiler. */ UNIV_INLINE ulint @@ -1452,7 +1432,7 @@ rec_get_converted_size( ? dict_index_get_n_unique_in_tree(index) + 1 : dict_index_get_n_fields(index))); - if (index->table->comp) { + if (UNIV_LIKELY(index->table->comp)) { return(rec_get_converted_size_new(index, dtuple)); } diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c index a8f75072e65..a1e7e348781 100644 --- a/innobase/rem/rem0rec.c +++ b/innobase/rem/rem0rec.c @@ -159,22 +159,20 @@ rec_init_offsets( ulint* offsets)/* in/out: array of offsets; in: n=rec_offs_n_fields(offsets) */ { - ulint n_fields = rec_offs_n_fields(offsets); ulint i = 0; ulint offs; rec_offs_make_valid(rec, index, offsets); - if (index->table->comp) { + if (UNIV_LIKELY(index->table->comp)) { const byte* nulls; const byte* lens; dict_field_t* field; - dtype_t* type; ulint null_mask; ulint status = rec_get_status(rec); ulint n_node_ptr_field = ULINT_UNDEFINED; - switch (status) { + switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) { case REC_STATUS_INFIMUM: case REC_STATUS_SUPREMUM: /* the field is 8 bytes long */ @@ -196,56 +194,74 @@ rec_init_offsets( null_mask = 1; /* read the lengths of fields 0..n */ - for (; i < n_fields; i++) { - ibool is_null = FALSE, is_external = FALSE; + do { ulint len; - if (i == n_node_ptr_field) { - len = 4; + if (UNIV_UNLIKELY(i == n_node_ptr_field)) { + len = offs += 4; goto resolved; } field = dict_index_get_nth_field(index, i); - type = dict_col_get_type(dict_field_get_col(field)); - if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { + if (!(dtype_get_prtype(dict_col_get_type( + dict_field_get_col(field))) + & DATA_NOT_NULL)) { /* nullable field => read the null flag */ - is_null = (*nulls & null_mask) != 0; - null_mask <<= 1; - if (null_mask == 0x100) { + + if (UNIV_UNLIKELY(!(byte) null_mask)) { nulls--; null_mask = 1; } + + if (*nulls & null_mask) { + null_mask <<= 1; + /* No length is stored for NULL fields. + We do not advance offs, and we set + the length to zero and enable the + SQL NULL flag in offsets[]. */ + len = REC_OFFS_SQL_NULL; + goto resolved; + } + null_mask <<= 1; + + ut_ad(!field->fixed_len); + goto variable_length; } - if (is_null) { - /* No length is stored for NULL fields. */ - len = 0; - } else if (!field->fixed_len) { + if (UNIV_UNLIKELY(!field->fixed_len)) { + dtype_t* type; + variable_length: /* Variable-length field: read the length */ + type = dict_col_get_type( + dict_field_get_col(field)); len = *lens--; - if (dtype_get_len(type) > 255 - || dtype_get_mtype(type) == DATA_BLOB) { + if (UNIV_UNLIKELY(dtype_get_len(type) > 255) + || UNIV_UNLIKELY(dtype_get_mtype(type) + == DATA_BLOB)) { if (len & 0x80) { /* 1exxxxxxx xxxxxxxx */ - is_external = !!(len & 0x40); - len &= 0x3f; len <<= 8; len |= *lens--; + + offs += len & 0x3fff; + if (UNIV_UNLIKELY(len + & 0x4000)) { + len = offs + | REC_OFFS_EXTERNAL; + } else { + len = offs; + } + + goto resolved; } } + + len = offs += len; } else { - len = field->fixed_len; + len = offs += field->fixed_len; } resolved: - offs += len; - len = offs; - if (is_external) { - len |= REC_OFFS_EXTERNAL; - } - if (is_null) { - len |= REC_OFFS_SQL_NULL; - } rec_offs_base(offsets)[i + 1] = len; - } + } while (++i < rec_offs_n_fields(offsets)); *rec_offs_base(offsets) = (rec - (lens + 1)) | REC_OFFS_COMPACT; @@ -253,22 +269,22 @@ rec_init_offsets( /* Old-style record: determine extra size and end offsets */ offs = REC_N_OLD_EXTRA_BYTES; if (rec_get_1byte_offs_flag(rec)) { - offs += n_fields; + offs += rec_offs_n_fields(offsets); *rec_offs_base(offsets) = offs; /* Determine offsets to fields */ - for (; i < n_fields; i++) { + do { offs = rec_1_get_field_end_info(rec, i); if (offs & REC_1BYTE_SQL_NULL_MASK) { offs &= ~REC_1BYTE_SQL_NULL_MASK; offs |= REC_OFFS_SQL_NULL; } rec_offs_base(offsets)[1 + i] = offs; - } + } while (++i < rec_offs_n_fields(offsets)); } else { - offs += 2 * n_fields; + offs += 2 * rec_offs_n_fields(offsets); *rec_offs_base(offsets) = offs; /* Determine offsets to fields */ - for (; i < n_fields; i++) { + do { offs = rec_2_get_field_end_info(rec, i); if (offs & REC_2BYTE_SQL_NULL_MASK) { offs &= ~REC_2BYTE_SQL_NULL_MASK; @@ -279,7 +295,7 @@ rec_init_offsets( offs |= REC_OFFS_EXTERNAL; } rec_offs_base(offsets)[1 + i] = offs; - } + } while (++i < rec_offs_n_fields(offsets)); } } } @@ -310,8 +326,9 @@ rec_get_offsets_func( ut_ad(index); ut_ad(heap); - if (index->table->comp) { - switch (rec_get_status(rec)) { + if (UNIV_LIKELY(index->table->comp)) { + switch (UNIV_EXPECT(rec_get_status(rec), + REC_STATUS_ORDINARY)) { case REC_STATUS_ORDINARY: n = dict_index_get_n_fields(index); break; @@ -331,13 +348,14 @@ rec_get_offsets_func( n = rec_get_n_fields_old(rec); } - if (n_fields < n) { + if (UNIV_UNLIKELY(n_fields < n)) { n = n_fields; } size = n + (1 + REC_OFFS_HEADER_SIZE); - if (!offsets || rec_offs_get_n_alloc(offsets) < size) { + if (UNIV_UNLIKELY(!offsets) || + UNIV_UNLIKELY(rec_offs_get_n_alloc(offsets) < size)) { if (!*heap) { *heap = mem_heap_create_func(size * sizeof(ulint), NULL, MEM_HEAP_DYNAMIC, file, line); @@ -652,9 +670,17 @@ rec_set_field_extern_bits( to log about the change */ { ulint i; - - for (i = 0; i < n_fields; i++) { - rec_set_nth_field_extern_bit(rec, index, vec[i], TRUE, mtr); + + if (UNIV_LIKELY(index->table->comp)) { + for (i = 0; i < n_fields; i++) { + rec_set_nth_field_extern_bit_new(rec, index, vec[i], + TRUE, mtr); + } + } else { + for (i = 0; i < n_fields; i++) { + rec_set_nth_field_extern_bit_old(rec, vec[i], + TRUE, mtr); + } } } @@ -949,7 +975,7 @@ rec_convert_dtuple_to_rec( ut_ad(dtuple_validate(dtuple)); ut_ad(dtuple_check_typed(dtuple)); - if (index->table->comp) { + if (UNIV_LIKELY(index->table->comp)) { rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple); } else { rec = rec_convert_dtuple_to_rec_old(buf, dtuple); @@ -1078,17 +1104,19 @@ rec_copy_prefix_to_buf( for the copied prefix, or NULL */ ulint* buf_size) /* in/out: buffer size */ { - byte* nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); - byte* lens = nulls - (index->n_nullable + 7) / 8; + byte* nulls; + byte* lens; dict_field_t* field; dtype_t* type; ulint i; - ulint prefix_len = 0; + ulint prefix_len; ibool is_null; - ulint null_mask = 1; + ulint null_mask; ulint status; - if (!index->table->comp) { + UNIV_PREFETCH_RW(*buf); + + if (UNIV_UNLIKELY(!index->table->comp)) { ut_ad(rec_validate_old(rec)); return(rec_copy_prefix_to_buf_old(rec, n_fields, rec_get_field_start_offs(rec, n_fields), @@ -1109,10 +1137,16 @@ rec_copy_prefix_to_buf( case REC_STATUS_SUPREMUM: /* infimum or supremum record: no sense to copy anything */ default: - ut_a(0); + ut_error; return(NULL); } + nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); + lens = nulls - (index->n_nullable + 7) / 8; + UNIV_PREFETCH_R(lens); + prefix_len = 0; + null_mask = 1; + /* read the lengths of fields 0..n */ for (i = 0; i < n_fields; i++) { field = dict_index_get_nth_field(index, i); @@ -1122,8 +1156,11 @@ rec_copy_prefix_to_buf( /* nullable field => read the null flag */ is_null = !!(*nulls & null_mask); null_mask <<= 1; - if (null_mask == 0x100) - nulls--, null_mask = 1; + if (null_mask == 0x100) { + --nulls; + UNIV_PREFETCH_R(nulls); + null_mask = 1; + } } if (is_null) { @@ -1138,12 +1175,15 @@ rec_copy_prefix_to_buf( len &= 0x3f; len <<= 8; len |= *lens--; + UNIV_PREFETCH_R(lens); } } prefix_len += len; } } + UNIV_PREFETCH_R(rec + prefix_len); + prefix_len += rec - (lens + 1); if ((*buf == NULL) || (*buf_size < prefix_len)) {