Group sequences of repeating literals into one write
Add a new "dumpn" pseudo-opcode that dumps N copies of the same value to the stage buffer. It's basically the same as "dump" but much faster when dumping the same value a lot of times, for example, when writing initial values for large arrays. On my Linux system the time it took to dump a 100000000 cell array went down from 20 to 8 seconds in Release configuration, i.e. 2.5 times faster! I haven't profiled further yet (Visual Studio 2017 profiler is broken, gprof won't output anything (I'm probably doing it wrong), I might try valgrind later).
This commit is contained in:
parent
092b07464b
commit
a99e649a6b
@ -327,7 +327,11 @@ char *pc_readasm(void *handle, char *string, int maxchars)
|
||||
*/
|
||||
void *pc_openbin(char *filename)
|
||||
{
|
||||
return fopen(filename,"wb");
|
||||
FILE *fbin;
|
||||
|
||||
fbin=fopen(filename,"wb");
|
||||
setvbuf(fbin,NULL,_IOFBF,1UL<<20);
|
||||
return fbin;
|
||||
}
|
||||
|
||||
void pc_closebin(void *handle,int deletefile)
|
||||
|
@ -639,6 +639,7 @@ SC_FUNC void ffabort(int reason);
|
||||
SC_FUNC void ffbounds(cell size);
|
||||
SC_FUNC void jumplabel(int number);
|
||||
SC_FUNC void defstorage(void);
|
||||
SC_FUNC void defcompactstorage(void);
|
||||
SC_FUNC void getfrm(void);
|
||||
SC_FUNC void modstk(int delta);
|
||||
SC_FUNC void setstk(cell value);
|
||||
|
@ -414,7 +414,11 @@ char *pc_readasm(void *handle, char *string, int maxchars)
|
||||
*/
|
||||
void *pc_openbin(char *filename)
|
||||
{
|
||||
return fopen(filename,"wb");
|
||||
FILE *fbin;
|
||||
|
||||
fbin=fopen(filename,"wb");
|
||||
setvbuf(fbin,NULL,_IOFBF,1UL<<20);
|
||||
return fbin;
|
||||
}
|
||||
|
||||
void pc_closebin(void *handle,int deletefile)
|
||||
@ -1716,29 +1720,42 @@ static void parse(void)
|
||||
*/
|
||||
static void dumplits(void)
|
||||
{
|
||||
int j,k;
|
||||
int i,j;
|
||||
static const int row_len=16;
|
||||
|
||||
if (sc_status==statSKIP)
|
||||
return;
|
||||
|
||||
k=0;
|
||||
while (k<litidx){
|
||||
i=0;
|
||||
while (i<litidx) {
|
||||
/* should be in the data segment */
|
||||
assert(curseg==2);
|
||||
defstorage();
|
||||
j=16; /* 16 values per line */
|
||||
while (j && k<litidx){
|
||||
outval(litq[k], FALSE);
|
||||
j=i+1;
|
||||
while (j<litidx && litq[j]==litq[i])
|
||||
j++;
|
||||
if (j-i>=row_len-1) {
|
||||
int count=j-i;
|
||||
defcompactstorage();
|
||||
outval(litq[i],FALSE);
|
||||
stgwrite(" ");
|
||||
k++;
|
||||
j--;
|
||||
if (j==0 || k>=litidx)
|
||||
stgwrite("\n"); /* force a newline after 10 dumps */
|
||||
/* Note: stgwrite() buffers a line until it is complete. It recognizes
|
||||
* the end of line as a sequence of "\n\0", so something like "\n\t"
|
||||
* so should not be passed to stgwrite().
|
||||
*/
|
||||
} /* while */
|
||||
outval(count,TRUE);
|
||||
i+=count;
|
||||
} else {
|
||||
defstorage();
|
||||
j=row_len; /* 16 values per line */
|
||||
while (j && i<litidx){
|
||||
outval(litq[i],FALSE);
|
||||
stgwrite(" ");
|
||||
i++;
|
||||
j--;
|
||||
if (j==0 || i>=litidx)
|
||||
stgwrite("\n"); /* force a newline after 10 dumps */
|
||||
/* Note: stgwrite() buffers a line until it is complete. It recognizes
|
||||
* the end of line as a sequence of "\n\0", so something like "\n\t"
|
||||
* so should not be passed to stgwrite().
|
||||
*/
|
||||
} /* while */
|
||||
} /* if */
|
||||
} /* while */
|
||||
}
|
||||
|
||||
@ -1748,20 +1765,13 @@ static void dumplits(void)
|
||||
*/
|
||||
static void dumpzero(int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (sc_status==statSKIP || count<=0)
|
||||
return;
|
||||
assert(curseg==2);
|
||||
defstorage();
|
||||
i=0;
|
||||
while (count-- > 0) {
|
||||
outval(0, FALSE);
|
||||
i=(i+1) % 16;
|
||||
stgwrite((i==0 || count==0) ? "\n" : " ");
|
||||
if (i==0 && count>0)
|
||||
defstorage();
|
||||
} /* while */
|
||||
defcompactstorage();
|
||||
outval(0, FALSE);
|
||||
stgwrite(" ");
|
||||
outval(count, TRUE);
|
||||
}
|
||||
|
||||
static void aligndata(int numbytes)
|
||||
|
@ -832,6 +832,15 @@ SC_FUNC void defstorage(void)
|
||||
stgwrite("dump ");
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as defstorage() but for repeating values.
|
||||
*/
|
||||
|
||||
SC_FUNC void defcompactstorage()
|
||||
{
|
||||
stgwrite("dumpn ");
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies frame address to primary register
|
||||
*/
|
||||
|
@ -382,7 +382,7 @@ static cell OPHANDLER_CALL parm5(FILE *fbin,char *params,cell opcode)
|
||||
static cell OPHANDLER_CALL do_dump(FILE *fbin,char *params,cell opcode)
|
||||
{
|
||||
ucell p;
|
||||
int num = 0;
|
||||
int num=0;
|
||||
|
||||
while (*params!='\0') {
|
||||
p=getparam(params,¶ms);
|
||||
@ -395,6 +395,19 @@ static cell OPHANDLER_CALL do_dump(FILE *fbin,char *params,cell opcode)
|
||||
return num*sizeof(cell);
|
||||
}
|
||||
|
||||
static cell OPHANDLER_CALL do_dumpn(FILE *fbin,char *params,cell opcode)
|
||||
{
|
||||
ucell value,num,i;
|
||||
|
||||
value=getparam(params,¶ms);
|
||||
num=getparam(params,NULL);
|
||||
if (fbin!=NULL) {
|
||||
for (i=0; i<num; i++)
|
||||
write_encoded(fbin,&value,1);
|
||||
} /* if */
|
||||
return num*sizeof(cell);
|
||||
}
|
||||
|
||||
static cell OPHANDLER_CALL do_call(FILE *fbin,char *params,cell opcode)
|
||||
{
|
||||
char name[sNAMEMAX+2]; /* +1 for a possible leading dot */
|
||||
@ -521,6 +534,7 @@ static OPCODE opcodelist[] = {
|
||||
{112, "dec.pri", sIN_CSEG, parm0 },
|
||||
{115, "dec.s", sIN_CSEG, parm1 },
|
||||
{ 0, "dump", sIN_DSEG, do_dump },
|
||||
{ 0, "dumpn", sIN_DSEG, do_dumpn },
|
||||
{ 95, "eq", sIN_CSEG, parm0 },
|
||||
{106, "eq.c.alt", sIN_CSEG, parm1 },
|
||||
{105, "eq.c.pri", sIN_CSEG, parm1 },
|
||||
|
Loading…
x
Reference in New Issue
Block a user