summaryrefslogtreecommitdiff
path: root/src/luac/opt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/luac/opt.c')
-rw-r--r--src/luac/opt.c326
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]);
}