diff options
Diffstat (limited to 'src/luac/opt.c')
| -rw-r--r-- | src/luac/opt.c | 326 |
1 files changed, 86 insertions, 240 deletions
diff --git a/src/luac/opt.c b/src/luac/opt.c index e2becc2a..e51a0868 100644 --- a/src/luac/opt.c +++ b/src/luac/opt.c @@ -1,5 +1,5 @@ /* -** $Id: opt.c,v 1.12 1999/07/02 19:34:26 lhf Exp $ +** $Id: opt.c,v 1.22 2000/10/31 16:57:23 lhf Exp $ ** optimize bytecodes ** See Copyright Notice in lua.h */ @@ -7,275 +7,121 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "luac.h" -static void FixArg(Byte* p, int i, int j, int isconst) -{ - if (j==i) - ; - else if (i<=MAX_BYTE) /* j<i, so j fits where i did */ - p[1]=j; - else if (i<=MAX_WORD) - { - if (isconst && j<=MAX_BYTE) /* may use byte variant instead */ - { - p[0]++; /* byte variant follows word variant */ - p[1]=j; - p[2]=NOP; - } - else /* stuck with word variant */ - { - p[1]=j>>8; - p[2]=j; - } - } - else /* previous instruction must've been LONGARG */ - { - if (isconst && j<=MAX_WORD) p[-2]=p[-1]=NOP; else p[-1]=j>>16; - p[1]=j>>8; - p[2]=j; - } -} +#include "luac.h" -static void FixConstants(TProtoFunc* tf, int* C) +static int MapConstant(Hash* t, int j, const TObject* key) { - Byte* code=tf->code; - Byte* p=code; - int longarg=0; - for (;;) + const TObject* o=luaH_get(L,t,key); + if (ttype(o)==LUA_TNUMBER) + return (int) nvalue(o); + else { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - int i=OP.arg+longarg; - longarg=0; - if (op==PUSHCONSTANT || op==GETGLOBAL || op==GETDOTTED || - op==PUSHSELF || op==SETGLOBAL || op==CLOSURE) - FixArg(p,i,C[i],1); - else if (op==LONGARG) longarg=i<<16; - else if (op==ENDCODE) break; - p+=n; + TObject val; + ttype(&val)=LUA_TNUMBER; + nvalue(&val)=j; + *luaH_set(L,t,key)=val; + LUA_ASSERT(j>=0,"MapConstant returns negative!"); + return j; } } -#define UNREF 1 /* "type" of unused constants */ -#define BIAS 128 /* mark for used constants */ - -static void NoUnrefs(TProtoFunc* tf) +static int MapConstants(Proto* tf, Hash* map) { - int i,n=tf->nconsts; - Byte* code=tf->code; - Byte* p=code; - int longarg=0; - for (;;) /* mark all used constants */ - { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - int i=OP.arg+longarg; - longarg=0; - if (op==PUSHCONSTANT || op==GETGLOBAL || op==GETDOTTED || - op==PUSHSELF || op==SETGLOBAL || op==CLOSURE) - { - TObject* o=tf->consts+i; - if (ttype(o)<=0) ttype(o)+=BIAS; /* mark as used */ - } - else if (op==LONGARG) longarg=i<<16; - else if (op==ENDCODE) break; - p+=n; - } - for (i=0; i<n; i++) /* mark all unused constants */ + int i,j,k,n,m=0; + TObject o; + j=0; n=tf->nknum; ttype(&o)=LUA_TNUMBER; + for (i=0; i<n; i++) { - TObject* o=tf->consts+i; - if (ttype(o)<=0) - ttype(o)=UNREF; /* mark as unused */ - else - ttype(o)-=BIAS; /* unmark used constant */ + nvalue(&o)=tf->knum[i]; + k=MapConstant(map,j,&o); + if (k==j) j++; } -} - -#define CMP(oa,ob,f) memcmp(&f(oa),&f(ob),sizeof(f(oa))) - -static int compare(TProtoFunc* tf, int ia, int ib) -{ - TObject* oa=tf->consts+ia; - TObject* ob=tf->consts+ib; - int t=ttype(oa)-ttype(ob); - if (t) return t; - switch (ttype(oa)) + m=j; + j=0; n=tf->nkstr; ttype(&o)=LUA_TSTRING; + for (i=0; i<n; i++) { - case LUA_T_NUMBER: return CMP(oa,ob,nvalue); - case LUA_T_STRING: return CMP(oa,ob,tsvalue); - case LUA_T_PROTO: return CMP(oa,ob,tfvalue); - case LUA_T_NIL: return 0; - case UNREF: return 0; - default: return ia-ib; /* cannot happen */ + tsvalue(&o)=tf->kstr[i]; + k=MapConstant(map,j,&o); + if (k==j) j++; } + return m+j; } -static TProtoFunc* TF; /* for sort */ - -static int compare1(const void* a, const void* b) -{ - int ia=*(int*)a; - int ib=*(int*)b; - int t=compare(TF,ia,ib); - return (t) ? t : ia-ib; -} - -static void OptConstants(TProtoFunc* tf) +static void PackConstants(Proto* tf, Hash* map) { - static int* C=NULL; - static int* D=NULL; - int i,k; - int n=tf->nconsts; - if (n==0) return; - luaM_reallocvector(C,n,int); - luaM_reallocvector(D,n,int); - NoUnrefs(tf); - for (i=0; i<n; i++) C[i]=D[i]=i; /* group duplicates */ - TF=tf; qsort(C,n,sizeof(C[0]),compare1); - k=C[0]; /* build duplicate table */ - for (i=1; i<n; i++) - { - int j=C[i]; - if (compare(tf,k,j)==0) D[j]=k; else k=j; - } - k=0; /* build rename map & pack constants */ + int i,j,k,n; + TObject o; +#ifdef DEBUG + printf("%p before pack nknum=%d nkstr=%d\n",tf,tf->nknum,tf->nkstr); +#endif + j=0; n=tf->nknum; ttype(&o)=LUA_TNUMBER; for (i=0; i<n; i++) { - if (D[i]==i) /* new value */ - { - TObject* o=tf->consts+i; - if (ttype(o)!=UNREF) - { - tf->consts[k]=tf->consts[i]; - C[i]=k++; - } - } - else C[i]=C[D[i]]; + nvalue(&o)=tf->knum[i]; + k=MapConstant(map,-1,&o); + if (k==j) tf->knum[j++]=tf->knum[i]; } - if (k<n) + tf->nknum=j; + j=0; n=tf->nkstr; ttype(&o)=LUA_TSTRING; + for (i=0; i<n; i++) { -printf("\t" SOURCE " reduced constants from %d to %d\n", - tf->source->str,tf->lineDefined,n,k); - FixConstants(tf,C); - tf->nconsts=k; + tsvalue(&o)=tf->kstr[i]; + k=MapConstant(map,-1,&o); + if (k==j) tf->kstr[j++]=tf->kstr[i]; } + tf->nkstr=j; +#ifdef DEBUG + printf("%p after pack nknum=%d nkstr=%d\n",tf,tf->nknum,tf->nkstr); +#endif } -static int NoDebug(TProtoFunc* tf) +static void OptConstants(Proto* tf) { - Byte* code=tf->code; - Byte* p=code; - int lop=NOP; /* last opcode */ - int nop=0; - for (;;) /* change SETLINE to NOP */ + Instruction* p; + int n=tf->nknum+tf->nkstr; + Hash* map=luaH_new(L,n); + int m=MapConstants(tf,map); +#ifdef DEBUG + printf("%p n=%d m=%d %s\n",tf,n,m,(m==n)?"nothing to optimize":"yes!"); +#endif + if (m==n) return; + for (p=tf->code;; p++) { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - if (op==NOP) ++nop; - else if (op==SETLINE) + Instruction i=*p; + int op=GET_OPCODE(i); + switch (op) { - int m; - if (lop==LONGARG) m=2; else if (lop==LONGARGW) m=3; else m=0; - nop+=n+m; memset(p-m,NOP,n+m); + TObject o; + int j,k; + case OP_PUSHNUM: case OP_PUSHNEGNUM: + j=GETARG_U(i); + ttype(&o)=LUA_TNUMBER; nvalue(&o)=tf->knum[j]; + k=MapConstant(map,-1,&o); + if (k!=j) *p=CREATE_U(op,k); + break; + case OP_PUSHSTRING: case OP_GETGLOBAL: case OP_GETDOTTED: + case OP_PUSHSELF: case OP_SETGLOBAL: + j=GETARG_U(i); + ttype(&o)=LUA_TSTRING; tsvalue(&o)=tf->kstr[j]; + k=MapConstant(map,-1,&o); + if (k!=j) *p=CREATE_U(op,k); + break; + case OP_END: + PackConstants(tf,map); + luaH_free(L,map); + return; + default: + break; } - else if (op==ENDCODE) break; - lop=OP.op; - p+=n; } - return nop; } -static int FixJump(TProtoFunc* tf, Byte* a, Byte* b) -{ - Byte* p; - int nop=0; - for (p=a; p<b; ) - { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - if (op==NOP) ++nop; - else if (op==ENDCODE) break; - p+=n; - } - return nop; -} +#define OptFunction luaU_optchunk -static void FixJumps(TProtoFunc* tf) -{ - Byte* code=tf->code; - Byte* p=code; - int longarg=0; - for (;;) - { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - int i=OP.arg+longarg; - int nop=0; - longarg=0; - if (op==ENDCODE) break; - else if (op==IFTUPJMP || op==IFFUPJMP) - nop=FixJump(tf,p-i+n,p); - else if (op==ONTJMP || op==ONFJMP || op==JMP || op==IFFJMP) - nop=FixJump(tf,p,p+i+n); - else if (op==LONGARG) longarg=i<<16; - if (nop>0) FixArg(p,i,i-nop,0); - p+=n; - } -} - -static void PackCode(TProtoFunc* tf) -{ - Byte* code=tf->code; - Byte* p=code; - Byte* q=code; - for (;;) - { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - if (op!=NOP) { memcpy(q,p,n); q+=n; } - p+=n; - if (op==ENDCODE) break; - } -printf("\t" SOURCE " reduced code from %d to %d\n", - tf->source->str,tf->lineDefined,(int)(p-code),(int)(q-code)); -} - -static void OptCode(TProtoFunc* tf) -{ - if (NoDebug(tf)==0) return; /* cannot improve code */ - FixJumps(tf); - PackCode(tf); -} - -static void OptFunction(TProtoFunc* tf); - -static void OptFunctions(TProtoFunc* tf) -{ - int i,n=tf->nconsts; - for (i=0; i<n; i++) - { - TObject* o=tf->consts+i; - if (ttype(o)==LUA_T_PROTO) OptFunction(tfvalue(o)); - } -} - -static void OptFunction(TProtoFunc* tf) +void OptFunction(Proto* tf) { + int i,n=tf->nkproto; OptConstants(tf); - OptCode(tf); - OptFunctions(tf); - tf->source=luaS_new(""); - tf->locvars=NULL; -} - -void luaU_optchunk(TProtoFunc* Main) -{ - OptFunction(Main); + for (i=0; i<n; i++) OptFunction(tf->kproto[i]); } |
