Fossil SCM

Performance optimizations in the TH1 interpreter.

drh 2021-01-27 12:38 UTC trunk
Commit b26eea7ee0ffee30020e30f9cd103f46e405db873a00d520f9767f127f99a842
1 file changed +53 -40
+53 -40
--- src/th.c
+++ src/th.c
@@ -199,59 +199,72 @@
199199
char *zBuf;
200200
int nBuf;
201201
int nBufAlloc;
202202
};
203203
typedef struct Buffer Buffer;
204
-static int thBufferWrite(Th_Interp *interp, Buffer *, const char *, int);
205204
static void thBufferInit(Buffer *);
206205
static void thBufferFree(Th_Interp *interp, Buffer *);
207206
208207
/*
209208
** This version of memcpy() allows the first and second argument to
210209
** be NULL as long as the number of bytes to copy is zero.
211210
*/
212
-static void *th_memcpy(void *dest, const void *src, size_t n){
213
- return n>0 ? memcpy(dest,src,n) : dest;
211
+static void th_memcpy(void *dest, const void *src, size_t n){
212
+ if( n>0 ) memcpy(dest,src,n);
214213
}
215214
216215
/*
217216
** Append nAdd bytes of content copied from zAdd to the end of buffer
218217
** pBuffer. If there is not enough space currently allocated, resize
219218
** the allocation to make space.
220219
*/
221
-static int thBufferWrite(
220
+static void thBufferWriteResize(
221
+ Th_Interp *interp,
222
+ Buffer *pBuffer,
223
+ const char *zAdd,
224
+ int nAdd
225
+){
226
+ char *zNew;
227
+ int nNew = (pBuffer->nBuf+nAdd)*2+32;
228
+ zNew = (char *)Th_Malloc(interp, nNew);
229
+ th_memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf);
230
+ Th_Free(interp, pBuffer->zBuf);
231
+ pBuffer->nBufAlloc = nNew;
232
+ pBuffer->zBuf = zNew;
233
+ th_memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd);
234
+ pBuffer->nBuf += nAdd;
235
+}
236
+static void thBufferWriteFast(
222237
Th_Interp *interp,
223238
Buffer *pBuffer,
224239
const char *zAdd,
225240
int nAdd
226241
){
227
- int nReq;
228
-
229
- if( nAdd<0 ){
230
- nAdd = th_strlen(zAdd);
231
- }
232
- nReq = pBuffer->nBuf+nAdd+1;
233
-
234
- if( nReq>pBuffer->nBufAlloc ){
235
- char *zNew;
236
- int nNew;
237
-
238
- nNew = nReq*2;
239
- zNew = (char *)Th_Malloc(interp, nNew);
240
- th_memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf);
241
- Th_Free(interp, pBuffer->zBuf);
242
- pBuffer->nBufAlloc = nNew;
243
- pBuffer->zBuf = zNew;
244
- }
245
-
246
- th_memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd);
247
- pBuffer->nBuf += nAdd;
248
- pBuffer->zBuf[pBuffer->nBuf] = '\0';
249
-
250
- return TH_OK;
251
-}
252
-#define thBufferWrite(a,b,c,d) thBufferWrite(a,b,(const char *)c,d)
242
+ if( pBuffer->nBuf+nAdd > pBuffer->nBufAlloc ){
243
+ thBufferWriteResize(interp, pBuffer, zAdd, nAdd);
244
+ }else{
245
+ char *z = pBuffer->zBuf + pBuffer->nBuf;
246
+ pBuffer->nBuf += nAdd;
247
+ memcpy(z, zAdd, nAdd);
248
+ }
249
+}
250
+#define thBufferWrite(a,b,c,d) thBufferWriteFast(a,b,(const char *)c,d)
251
+
252
+/*
253
+** Add a single character to a buffer
254
+*/
255
+static void thBufferAddChar(
256
+ Th_Interp *interp,
257
+ Buffer *pBuffer,
258
+ char c
259
+){
260
+ if( pBuffer->nBuf+1 > pBuffer->nBufAlloc ){
261
+ thBufferWriteResize(interp, pBuffer, &c, 1);
262
+ }else{
263
+ pBuffer->zBuf[pBuffer->nBuf++] = c;
264
+ }
265
+}
253266
254267
/*
255268
** Initialize the Buffer structure pointed to by pBuffer.
256269
*/
257270
static void thBufferInit(Buffer *pBuffer){
@@ -627,11 +640,11 @@
627640
628641
zInner = Th_GetResult(interp, &nInner);
629642
thBufferInit(&varname);
630643
thBufferWrite(interp, &varname, &zWord[1], i);
631644
thBufferWrite(interp, &varname, zInner, nInner);
632
- thBufferWrite(interp, &varname, ")", 1);
645
+ thBufferAddChar(interp, &varname, ')');
633646
rc = Th_GetVar(interp, varname.zBuf, varname.nBuf);
634647
thBufferFree(interp, &varname);
635648
return rc;
636649
}
637650
}
@@ -689,11 +702,11 @@
689702
int i;
690703
691704
thBufferInit(&output);
692705
693706
if( nWord>1 && (zWord[0]=='{' && zWord[nWord-1]=='}') ){
694
- rc = thBufferWrite(interp, &output, &zWord[1], nWord-2);
707
+ thBufferWrite(interp, &output, &zWord[1], nWord-2);
695708
}else{
696709
697710
/* If the word is surrounded by double-quotes strip these away. */
698711
if( nWord>1 && (zWord[0]=='"' && zWord[nWord-1]=='"') ){
699712
zWord++;
@@ -719,11 +732,11 @@
719732
if( !interp->isListMode ){
720733
xGet = thNextVarname; xSubst = thSubstVarname;
721734
break;
722735
}
723736
default: {
724
- thBufferWrite(interp, &output, &zWord[i], 1);
737
+ thBufferAddChar(interp, &output, zWord[i]);
725738
continue; /* Go to the next iteration of the for(...) loop */
726739
}
727740
}
728741
729742
rc = xGet(interp, &zWord[i], nWord-i, &nGet);
@@ -732,11 +745,11 @@
732745
}
733746
if( rc==TH_OK ){
734747
const char *zRes;
735748
int nRes;
736749
zRes = Th_GetResult(interp, &nRes);
737
- rc = thBufferWrite(interp, &output, zRes, nRes);
750
+ thBufferWrite(interp, &output, zRes, nRes);
738751
i += (nGet-1);
739752
}
740753
}
741754
}
742755
@@ -830,11 +843,11 @@
830843
zInput = &zInput[nWord];
831844
nInput = nList-(zInput-zList);
832845
if( nWord>0 ){
833846
zWord = Th_GetResult(interp, &nWord);
834847
thBufferWrite(interp, &strbuf, zWord, nWord);
835
- thBufferWrite(interp, &strbuf, "\0", 1);
848
+ thBufferAddChar(interp, &strbuf, 0);
836849
thBufferWrite(interp, &lenbuf, &nWord, sizeof(int));
837850
nCount++;
838851
}
839852
}
840853
assert((lenbuf.nBuf/sizeof(int))==nCount);
@@ -1734,11 +1747,11 @@
17341747
17351748
if( nElem<0 ){
17361749
nElem = th_strlen(zElem);
17371750
}
17381751
if( output.nBuf>0 ){
1739
- thBufferWrite(interp, &output, " ", 1);
1752
+ thBufferAddChar(interp, &output, ' ');
17401753
}
17411754
17421755
for(i=0; i<nElem; i++){
17431756
char c = zElem[i];
17441757
if( th_isspecial(c) ) hasSpecialChar = 1;
@@ -1746,18 +1759,18 @@
17461759
if( c=='{' ) nBrace++;
17471760
if( c=='}' ) nBrace--;
17481761
}
17491762
17501763
if( nElem==0 || (!hasEscapeChar && hasSpecialChar && nBrace==0) ){
1751
- thBufferWrite(interp, &output, "{", 1);
1764
+ thBufferAddChar(interp, &output, '{');
17521765
thBufferWrite(interp, &output, zElem, nElem);
1753
- thBufferWrite(interp, &output, "}", 1);
1766
+ thBufferAddChar(interp, &output, '}');
17541767
}else{
17551768
for(i=0; i<nElem; i++){
17561769
char c = zElem[i];
1757
- if( th_isspecial(c) ) thBufferWrite(interp, &output, "\\", 1);
1758
- thBufferWrite(interp, &output, &c, 1);
1770
+ if( th_isspecial(c) ) thBufferAddChar(interp, &output, '\\');
1771
+ thBufferAddChar(interp, &output, c);
17591772
}
17601773
}
17611774
17621775
*pzList = output.zBuf;
17631776
*pnList = output.nBuf;
17641777
--- src/th.c
+++ src/th.c
@@ -199,59 +199,72 @@
199 char *zBuf;
200 int nBuf;
201 int nBufAlloc;
202 };
203 typedef struct Buffer Buffer;
204 static int thBufferWrite(Th_Interp *interp, Buffer *, const char *, int);
205 static void thBufferInit(Buffer *);
206 static void thBufferFree(Th_Interp *interp, Buffer *);
207
208 /*
209 ** This version of memcpy() allows the first and second argument to
210 ** be NULL as long as the number of bytes to copy is zero.
211 */
212 static void *th_memcpy(void *dest, const void *src, size_t n){
213 return n>0 ? memcpy(dest,src,n) : dest;
214 }
215
216 /*
217 ** Append nAdd bytes of content copied from zAdd to the end of buffer
218 ** pBuffer. If there is not enough space currently allocated, resize
219 ** the allocation to make space.
220 */
221 static int thBufferWrite(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222 Th_Interp *interp,
223 Buffer *pBuffer,
224 const char *zAdd,
225 int nAdd
226 ){
227 int nReq;
228
229 if( nAdd<0 ){
230 nAdd = th_strlen(zAdd);
231 }
232 nReq = pBuffer->nBuf+nAdd+1;
233
234 if( nReq>pBuffer->nBufAlloc ){
235 char *zNew;
236 int nNew;
237
238 nNew = nReq*2;
239 zNew = (char *)Th_Malloc(interp, nNew);
240 th_memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf);
241 Th_Free(interp, pBuffer->zBuf);
242 pBuffer->nBufAlloc = nNew;
243 pBuffer->zBuf = zNew;
244 }
245
246 th_memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd);
247 pBuffer->nBuf += nAdd;
248 pBuffer->zBuf[pBuffer->nBuf] = '\0';
249
250 return TH_OK;
251 }
252 #define thBufferWrite(a,b,c,d) thBufferWrite(a,b,(const char *)c,d)
253
254 /*
255 ** Initialize the Buffer structure pointed to by pBuffer.
256 */
257 static void thBufferInit(Buffer *pBuffer){
@@ -627,11 +640,11 @@
627
628 zInner = Th_GetResult(interp, &nInner);
629 thBufferInit(&varname);
630 thBufferWrite(interp, &varname, &zWord[1], i);
631 thBufferWrite(interp, &varname, zInner, nInner);
632 thBufferWrite(interp, &varname, ")", 1);
633 rc = Th_GetVar(interp, varname.zBuf, varname.nBuf);
634 thBufferFree(interp, &varname);
635 return rc;
636 }
637 }
@@ -689,11 +702,11 @@
689 int i;
690
691 thBufferInit(&output);
692
693 if( nWord>1 && (zWord[0]=='{' && zWord[nWord-1]=='}') ){
694 rc = thBufferWrite(interp, &output, &zWord[1], nWord-2);
695 }else{
696
697 /* If the word is surrounded by double-quotes strip these away. */
698 if( nWord>1 && (zWord[0]=='"' && zWord[nWord-1]=='"') ){
699 zWord++;
@@ -719,11 +732,11 @@
719 if( !interp->isListMode ){
720 xGet = thNextVarname; xSubst = thSubstVarname;
721 break;
722 }
723 default: {
724 thBufferWrite(interp, &output, &zWord[i], 1);
725 continue; /* Go to the next iteration of the for(...) loop */
726 }
727 }
728
729 rc = xGet(interp, &zWord[i], nWord-i, &nGet);
@@ -732,11 +745,11 @@
732 }
733 if( rc==TH_OK ){
734 const char *zRes;
735 int nRes;
736 zRes = Th_GetResult(interp, &nRes);
737 rc = thBufferWrite(interp, &output, zRes, nRes);
738 i += (nGet-1);
739 }
740 }
741 }
742
@@ -830,11 +843,11 @@
830 zInput = &zInput[nWord];
831 nInput = nList-(zInput-zList);
832 if( nWord>0 ){
833 zWord = Th_GetResult(interp, &nWord);
834 thBufferWrite(interp, &strbuf, zWord, nWord);
835 thBufferWrite(interp, &strbuf, "\0", 1);
836 thBufferWrite(interp, &lenbuf, &nWord, sizeof(int));
837 nCount++;
838 }
839 }
840 assert((lenbuf.nBuf/sizeof(int))==nCount);
@@ -1734,11 +1747,11 @@
1734
1735 if( nElem<0 ){
1736 nElem = th_strlen(zElem);
1737 }
1738 if( output.nBuf>0 ){
1739 thBufferWrite(interp, &output, " ", 1);
1740 }
1741
1742 for(i=0; i<nElem; i++){
1743 char c = zElem[i];
1744 if( th_isspecial(c) ) hasSpecialChar = 1;
@@ -1746,18 +1759,18 @@
1746 if( c=='{' ) nBrace++;
1747 if( c=='}' ) nBrace--;
1748 }
1749
1750 if( nElem==0 || (!hasEscapeChar && hasSpecialChar && nBrace==0) ){
1751 thBufferWrite(interp, &output, "{", 1);
1752 thBufferWrite(interp, &output, zElem, nElem);
1753 thBufferWrite(interp, &output, "}", 1);
1754 }else{
1755 for(i=0; i<nElem; i++){
1756 char c = zElem[i];
1757 if( th_isspecial(c) ) thBufferWrite(interp, &output, "\\", 1);
1758 thBufferWrite(interp, &output, &c, 1);
1759 }
1760 }
1761
1762 *pzList = output.zBuf;
1763 *pnList = output.nBuf;
1764
--- src/th.c
+++ src/th.c
@@ -199,59 +199,72 @@
199 char *zBuf;
200 int nBuf;
201 int nBufAlloc;
202 };
203 typedef struct Buffer Buffer;
 
204 static void thBufferInit(Buffer *);
205 static void thBufferFree(Th_Interp *interp, Buffer *);
206
207 /*
208 ** This version of memcpy() allows the first and second argument to
209 ** be NULL as long as the number of bytes to copy is zero.
210 */
211 static void th_memcpy(void *dest, const void *src, size_t n){
212 if( n>0 ) memcpy(dest,src,n);
213 }
214
215 /*
216 ** Append nAdd bytes of content copied from zAdd to the end of buffer
217 ** pBuffer. If there is not enough space currently allocated, resize
218 ** the allocation to make space.
219 */
220 static void thBufferWriteResize(
221 Th_Interp *interp,
222 Buffer *pBuffer,
223 const char *zAdd,
224 int nAdd
225 ){
226 char *zNew;
227 int nNew = (pBuffer->nBuf+nAdd)*2+32;
228 zNew = (char *)Th_Malloc(interp, nNew);
229 th_memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf);
230 Th_Free(interp, pBuffer->zBuf);
231 pBuffer->nBufAlloc = nNew;
232 pBuffer->zBuf = zNew;
233 th_memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd);
234 pBuffer->nBuf += nAdd;
235 }
236 static void thBufferWriteFast(
237 Th_Interp *interp,
238 Buffer *pBuffer,
239 const char *zAdd,
240 int nAdd
241 ){
242 if( pBuffer->nBuf+nAdd > pBuffer->nBufAlloc ){
243 thBufferWriteResize(interp, pBuffer, zAdd, nAdd);
244 }else{
245 char *z = pBuffer->zBuf + pBuffer->nBuf;
246 pBuffer->nBuf += nAdd;
247 memcpy(z, zAdd, nAdd);
248 }
249 }
250 #define thBufferWrite(a,b,c,d) thBufferWriteFast(a,b,(const char *)c,d)
251
252 /*
253 ** Add a single character to a buffer
254 */
255 static void thBufferAddChar(
256 Th_Interp *interp,
257 Buffer *pBuffer,
258 char c
259 ){
260 if( pBuffer->nBuf+1 > pBuffer->nBufAlloc ){
261 thBufferWriteResize(interp, pBuffer, &c, 1);
262 }else{
263 pBuffer->zBuf[pBuffer->nBuf++] = c;
264 }
265 }
 
 
266
267 /*
268 ** Initialize the Buffer structure pointed to by pBuffer.
269 */
270 static void thBufferInit(Buffer *pBuffer){
@@ -627,11 +640,11 @@
640
641 zInner = Th_GetResult(interp, &nInner);
642 thBufferInit(&varname);
643 thBufferWrite(interp, &varname, &zWord[1], i);
644 thBufferWrite(interp, &varname, zInner, nInner);
645 thBufferAddChar(interp, &varname, ')');
646 rc = Th_GetVar(interp, varname.zBuf, varname.nBuf);
647 thBufferFree(interp, &varname);
648 return rc;
649 }
650 }
@@ -689,11 +702,11 @@
702 int i;
703
704 thBufferInit(&output);
705
706 if( nWord>1 && (zWord[0]=='{' && zWord[nWord-1]=='}') ){
707 thBufferWrite(interp, &output, &zWord[1], nWord-2);
708 }else{
709
710 /* If the word is surrounded by double-quotes strip these away. */
711 if( nWord>1 && (zWord[0]=='"' && zWord[nWord-1]=='"') ){
712 zWord++;
@@ -719,11 +732,11 @@
732 if( !interp->isListMode ){
733 xGet = thNextVarname; xSubst = thSubstVarname;
734 break;
735 }
736 default: {
737 thBufferAddChar(interp, &output, zWord[i]);
738 continue; /* Go to the next iteration of the for(...) loop */
739 }
740 }
741
742 rc = xGet(interp, &zWord[i], nWord-i, &nGet);
@@ -732,11 +745,11 @@
745 }
746 if( rc==TH_OK ){
747 const char *zRes;
748 int nRes;
749 zRes = Th_GetResult(interp, &nRes);
750 thBufferWrite(interp, &output, zRes, nRes);
751 i += (nGet-1);
752 }
753 }
754 }
755
@@ -830,11 +843,11 @@
843 zInput = &zInput[nWord];
844 nInput = nList-(zInput-zList);
845 if( nWord>0 ){
846 zWord = Th_GetResult(interp, &nWord);
847 thBufferWrite(interp, &strbuf, zWord, nWord);
848 thBufferAddChar(interp, &strbuf, 0);
849 thBufferWrite(interp, &lenbuf, &nWord, sizeof(int));
850 nCount++;
851 }
852 }
853 assert((lenbuf.nBuf/sizeof(int))==nCount);
@@ -1734,11 +1747,11 @@
1747
1748 if( nElem<0 ){
1749 nElem = th_strlen(zElem);
1750 }
1751 if( output.nBuf>0 ){
1752 thBufferAddChar(interp, &output, ' ');
1753 }
1754
1755 for(i=0; i<nElem; i++){
1756 char c = zElem[i];
1757 if( th_isspecial(c) ) hasSpecialChar = 1;
@@ -1746,18 +1759,18 @@
1759 if( c=='{' ) nBrace++;
1760 if( c=='}' ) nBrace--;
1761 }
1762
1763 if( nElem==0 || (!hasEscapeChar && hasSpecialChar && nBrace==0) ){
1764 thBufferAddChar(interp, &output, '{');
1765 thBufferWrite(interp, &output, zElem, nElem);
1766 thBufferAddChar(interp, &output, '}');
1767 }else{
1768 for(i=0; i<nElem; i++){
1769 char c = zElem[i];
1770 if( th_isspecial(c) ) thBufferAddChar(interp, &output, '\\');
1771 thBufferAddChar(interp, &output, c);
1772 }
1773 }
1774
1775 *pzList = output.zBuf;
1776 *pnList = output.nBuf;
1777

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button