1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Move the sqlite3VdbeSerialType() routine in-line in the OP_MakeRecord opcode.

Optimizing compilers were doing this already.  By doing it manually, we can
omit some redundant tests and make the whole thing run a million cycles faster
and use about 80 bytes less code space.

FossilOrigin-Name: d837ab0da52632699abc09320980606aef020df5020c253f99c97e24bf3c6d00
This commit is contained in:
drh
2019-07-11 19:22:36 +00:00
parent ea7e83b780
commit c1da4397d6
5 changed files with 89 additions and 25 deletions

View File

@@ -2932,9 +2932,8 @@ case OP_MakeRecord: {
pRec = pLast;
do{
assert( memIsValid(pRec) );
serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
if( pRec->flags & MEM_Zero ){
if( serial_type==0 ){
if( pRec->flags & MEM_Null ){
if( pRec->flags & MEM_Zero ){
/* Values with MEM_Null and MEM_Zero are created by xColumn virtual
** table methods that never invoke sqlite3_result_xxxxx() while
** computing an unchanging column value in an UPDATE statement.
@@ -2942,19 +2941,78 @@ case OP_MakeRecord: {
** so that they can be passed through to xUpdate and have
** a true sqlite3_value_nochange(). */
assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB );
serial_type = 10;
}else if( nData ){
if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
pRec->uTemp = 10;
}else{
nZero += pRec->u.nZero;
len -= pRec->u.nZero;
pRec->uTemp = 0; /* Serial-type 0 means NULL */
}
nHdr++;
}else if( pRec->flags & (MEM_Int|MEM_IntReal) ){
/* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
i64 i = pRec->u.i;
u64 u;
testcase( pRec->flags & MEM_Int );
testcase( pRec->flags & MEM_IntReal );
if( i<0 ){
u = ~i;
}else{
u = i;
}
nHdr++;
if( u<=127 ){
if( (i&1)==i && file_format>=4 ){
pRec->uTemp = 8+(u32)u;
}else{
nData++;
pRec->uTemp = 1;
}
}else if( u<=32767 ){
nData += 2;
pRec->uTemp = 2;
}else if( u<=8388607 ){
nData += 3;
pRec->uTemp = 3;
}else if( u<=2147483647 ){
nData += 4;
pRec->uTemp = 4;
}else if( u<=140737488355327LL ){
nData += 6;
pRec->uTemp = 5;
}else{
nData += 8;
if( pRec->flags & MEM_IntReal ){
/* If the value is IntReal and is going to take up 8 bytes to store
** as an integer, then we might as well make it an 8-byte floating
** point value */
pRec->u.r = (double)pRec->u.i;
pRec->flags &= ~MEM_IntReal;
pRec->flags |= MEM_Real;
pRec->uTemp = 7;
}else{
pRec->uTemp = 6;
}
}
}else if( pRec->flags & MEM_Real ){
nHdr++;
nData += 8;
pRec->uTemp = 7;
}else{
assert( db->mallocFailed || pRec->flags&(MEM_Str|MEM_Blob) );
assert( pRec->n>=0 );
len = (u32)pRec->n;
serial_type = (len*2) + 12 + ((pRec->flags & MEM_Str)!=0);
if( pRec->flags & MEM_Zero ){
serial_type += pRec->u.nZero*2;
if( nData ){
if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
len += pRec->u.nZero;
}else{
nZero += pRec->u.nZero;
}
}
nData += len;
nHdr += sqlite3VarintLen(serial_type);
pRec->uTemp = serial_type;
}
nData += len;
testcase( serial_type==127 );
testcase( serial_type==128 );
nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
pRec->uTemp = serial_type;
if( pRec==pData0 ) break;
pRec--;
}while(1);