Commit 1c8f5500 authored by unknown's avatar unknown

InnoDB: Optimize rec_get_offsets(), rec_copy_prefix_to_buf() and

other rec_ functions based on OProfile measurements on GNU/Linux x86.


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