Use bitfields for slots

This commit is contained in:
James Roseborough
2010-04-22 14:49:01 +00:00
parent 9b6c9e1326
commit 8926a94348
4 changed files with 166 additions and 150 deletions

View File

@@ -292,6 +292,11 @@ abstract public class LibFunction extends LuaFunction {
// allocate storage for upvalue, initialize with nil // allocate storage for upvalue, initialize with nil
protected static LuaValue[] newupn() { protected static LuaValue[] newupn() {
return new LuaValue[] { valueOf(777) }; return new LuaValue[] { NIL };
}
// allocate storage for upvalue, initialize with value
protected static LuaValue[] newupl(LuaValue v) {
return new LuaValue[] { v };
} }
} }

View File

@@ -320,7 +320,7 @@ public class JavaBuilder {
} }
public void storeLocal(int pc, int slot) { public void storeLocal(int pc, int slot) {
boolean isupval = slots.isUpvalue(pc, slot); boolean isupval = slots.isUpvalueAssign(pc, slot);
int index = findSlotIndex( slot, isupval ); int index = findSlotIndex( slot, isupval );
if (isupval) { if (isupval) {
boolean isupcreate = slots.isUpvalueCreate(pc, slot); boolean isupcreate = slots.isUpvalueCreate(pc, slot);

View File

@@ -58,6 +58,7 @@ public class JavaGen {
int vresultbase = -1; int vresultbase = -1;
for ( int pc=0, n=p.code.length; pc<n; pc++ ) { for ( int pc=0, n=p.code.length; pc<n; pc++ ) {
int pc0 = pc; // closure changes pc
int ins = p.code[pc]; int ins = p.code[pc];
int o = Lua.GET_OPCODE(ins); int o = Lua.GET_OPCODE(ins);
int a = Lua.GETARG_A(ins); int a = Lua.GETARG_A(ins);
@@ -175,14 +176,8 @@ public class JavaGen {
break; break;
case Lua.OP_JMP: /* sBx pc+=sBx */ case Lua.OP_JMP: /* sBx pc+=sBx */
{ builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+1+sbx);
int pc1 = pc+1+sbx;
ins = p.code[pc1];
if ( Lua.GET_OPCODE(ins) == Lua.OP_TFORLOOP )
builder.createUpvalues(pc, Lua.GETARG_A(ins)+3, Lua.GETARG_C(ins));
builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc1);
break; break;
}
case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
@@ -326,6 +321,7 @@ public class JavaGen {
* R(A+2)): if R(A+3) ~= nil then R(A+2)=R(A+3) * R(A+2)): if R(A+3) ~= nil then R(A+2)=R(A+3)
* else pc++ * else pc++
*/ */
builder.createUpvalues(pc, a+3, c);
builder.loadLocal(pc, a); builder.loadLocal(pc, a);
builder.loadLocal(pc, a+1); builder.loadLocal(pc, a+1);
builder.loadLocal(pc, a+2); builder.loadLocal(pc, a+2);
@@ -375,12 +371,12 @@ public class JavaGen {
for ( int up=0; up<nup; ++up ) { for ( int up=0; up<nup; ++up ) {
if ( up+1 < nup ) if ( up+1 < nup )
builder.dup(); builder.dup();
ins = p.code[pc+up+1]; ins = p.code[++pc];
b = Lua.GETARG_B(ins); b = Lua.GETARG_B(ins);
if ( (ins&4) != 0 ) { if ( (ins&4) != 0 ) {
builder.closureInitUpvalueFromUpvalue( protoname, up, b ); builder.closureInitUpvalueFromUpvalue( protoname, up, b );
} else { } else {
builder.closureInitUpvalueFromLocal( protoname, up, pc, b ); builder.closureInitUpvalueFromLocal( protoname, up, pc0, b );
} }
} }
} }
@@ -401,7 +397,7 @@ public class JavaGen {
} }
// let builder process branch instructions // let builder process branch instructions
builder.onEndOfLuaInstruction( pc ); builder.onEndOfLuaInstruction( pc0 );
} }
} }

View File

@@ -21,7 +21,11 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2.luajc; package org.luaj.vm2.luajc;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.luaj.vm2.Lua; import org.luaj.vm2.Lua;
import org.luaj.vm2.Print;
import org.luaj.vm2.Prototype; import org.luaj.vm2.Prototype;
/** /**
@@ -36,51 +40,32 @@ import org.luaj.vm2.Prototype;
*/ */
public class Slots { public class Slots {
private static final byte ASSIGN = 'a'; // assignment to a slot position private static final byte BIT_ASSIGN = 0x01; // assignment is made to this slot at this pc
private static final byte REFER = 'r'; // reference to a slot position private static final byte BIT_REFER = 0x02; // reference is made to this slot at this pc
private static final byte REFER_ASSIGN = 'b'; // i.e. "both" private static final byte BIT_UP_ASSIGN = 0x04; // upvalue assignment
private static final byte UPVAL_CREATE = 'U'; // where upvalue must be alloced private static final byte BIT_UP_REFER = 0x08; // upvalue reference
private static final byte UPVAL_USE = 'u'; // continuation of existing upvalue private static final byte BIT_UP_CREATE = 0x10; // upvalue storage must be created here
private static final byte UPVAL_USE_ASSIGN = 'c'; // on create closure only private static final byte BIT_INVALID = 0x20; // slot becomes invlaid at this pc
private static final byte UPVAL_USE_CREATE = 'C'; // on create closure only, create new upvalue private static final byte BIT_NIL = 0x40; // slot initialized to nil at this point
private static final byte INVALID = 'x'; // after call, etc
private static final byte INITIAL_NIL = 'n'; // above parameters at initial call
final int n,m; final int n,m;
public final byte[][] slots; public final byte[][] slots;
public final boolean[] branchdest; public final boolean[] branchdest;
public boolean isUpvalueCreate(int pc, int slot) { public boolean isUpvalueCreate(int pc, int slot) {
switch (slots[pc+1][slot]) { return (slots[pc+1][slot] & (BIT_UP_CREATE)) != 0;
case UPVAL_CREATE:
case UPVAL_USE_CREATE:
return true;
}
return false;
} }
public boolean isUpvalue(int pc, int slot) { public boolean isUpvalueAssign(int pc, int slot) {
switch (slots[pc+1][slot]) { return (slots[pc+1][slot] & (BIT_UP_ASSIGN | BIT_UP_CREATE)) != 0;
case UPVAL_USE:
case UPVAL_CREATE:
case UPVAL_USE_CREATE:
case UPVAL_USE_ASSIGN:
return true;
}
return false;
} }
public boolean isUpvalueRefer(int pc, int slot) { public boolean isUpvalueRefer(int pc, int slot) {
switch (slots[pc+1][slot]) { return (slots[pc+1][slot] & (BIT_UP_REFER)) != 0;
case UPVAL_USE:
case UPVAL_USE_ASSIGN:
return true;
}
return false;
} }
public boolean isInitialValueUsed(int slot) { public boolean isInitialValueUsed(int slot) {
return slots[0][slot] != INVALID; return (slots[0][slot] & (BIT_INVALID)) == 0;
} }
public Slots(Prototype p) { public Slots(Prototype p) {
@@ -95,32 +80,21 @@ public class Slots {
} }
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); return toString(null);
for ( int i=0; i<slots.length; i++ ) {
if ( i > 0 ) sb.append( "\n" );
byte[] s = slots[i];
for ( int j=s.length; --j>=0; ) {
if ( s[j] == 0 )
s[j] = ' ';
}
sb.append( i>0 && branchdest[i]? "D": " " );
sb.append( new String(s) );
}
return sb.toString();
} }
private void markassignments( Prototype p ) { private void markassignments( Prototype p ) {
// mark initial assignments and references // mark initial assignments and references
int j=0; int j=0;
for ( ; j<p.numparams; j++ ) for ( ; j<p.numparams; j++ )
slots[0][j] = ASSIGN; slots[0][j] = BIT_ASSIGN;
for ( ; j<m; j++ ) for ( ; j<m; j++ )
slots[0][j] = INITIAL_NIL; slots[0][j] = BIT_NIL;
for ( int index=1; index<=n; index++ ) { for ( int pc=0; pc<n; pc++ ) {
int index = pc+1;
byte[] s = slots[index]; byte[] s = slots[index];
int pc = index-1;
int ins = p.code[pc]; int ins = p.code[pc];
int a = Lua.GETARG_A(ins); int a = Lua.GETARG_A(ins);
int b = Lua.GETARG_B(ins); int b = Lua.GETARG_B(ins);
@@ -132,32 +106,32 @@ public class Slots {
case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */ case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */
case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */ case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */
case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */ case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
s[a] = ASSIGN; s[a] |= BIT_ASSIGN;
break; break;
case Lua.OP_MOVE:/* A B R(A):= R(B) */ case Lua.OP_MOVE:/* A B R(A):= R(B) */
case Lua.OP_UNM: /* A B R(A):= -R(B) */ case Lua.OP_UNM: /* A B R(A):= -R(B) */
case Lua.OP_NOT: /* A B R(A):= not R(B) */ case Lua.OP_NOT: /* A B R(A):= not R(B) */
case Lua.OP_LEN: /* A B R(A):= length of R(B) */ case Lua.OP_LEN: /* A B R(A):= length of R(B) */
s[a] = ASSIGN; s[a] |= BIT_ASSIGN;
s[b] = REFER; s[b] |= BIT_REFER;
break; break;
case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */ case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */
case Lua.OP_GETGLOBAL: /* A Bx R(A):= Gbl[Kst(Bx)] */ case Lua.OP_GETGLOBAL: /* A Bx R(A):= Gbl[Kst(Bx)] */
case Lua.OP_SETGLOBAL: /* A Bx Gbl[Kst(Bx)]:= R(A) */ case Lua.OP_SETGLOBAL: /* A Bx Gbl[Kst(Bx)]:= R(A) */
s[a] = ASSIGN; s[a] |= BIT_ASSIGN;
break; break;
case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(B):= nil */ case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(B):= nil */
while ( a<b ) while ( a<b )
s[a++] = ASSIGN; s[a++] |= BIT_ASSIGN;
break; break;
case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */ case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */
s[a] = ASSIGN; s[a] |= BIT_ASSIGN;
s[b] = REFER; s[b] |= BIT_REFER;
if (c<=0xff) s[c] = REFER; if (c<=0xff) s[c] |= BIT_REFER;
break; break;
case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */ case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */
@@ -167,26 +141,26 @@ public class Slots {
case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */ case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */
case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */ case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */ case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */
s[a] = ASSIGN; s[a] |= BIT_ASSIGN;
if (bx<=0xff) s[bx] = REFER; if (bx<=0xff) s[bx] |= BIT_REFER;
if (c<=0xff) s[c] = REFER; if (c<=0xff) s[c] |= BIT_REFER;
break; break;
case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */ case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */
s[a] = ASSIGN; s[a] |= BIT_ASSIGN;
s[a+1] = ASSIGN; s[a+1] |= BIT_ASSIGN;
s[b] = REFER; s[b] |= BIT_REFER;
if (c<=0xff) s[c] = REFER; if (c<=0xff) s[c] |= BIT_REFER;
break; break;
case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */ case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */
s[a] = ASSIGN; s[a] |= BIT_ASSIGN;
while ( b<=c ) while ( b<=c )
s[b++] = REFER; s[b++] |= BIT_REFER;
break; break;
case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */ case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */
s[a] = ASSIGN; s[a] |= BIT_ASSIGN;
if ( c!=0 ) branchdest[index+2] = true; if ( c!=0 ) branchdest[index+2] = true;
break; break;
@@ -197,52 +171,54 @@ public class Slots {
case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
if (bx<=0xff) s[bx] = REFER; if (bx<=0xff) s[bx] |= BIT_REFER;
if (c<=0xff) s[c] = REFER; if (c<=0xff) s[c] |= BIT_REFER;
branchdest[index+2] = true; branchdest[index+2] = true;
break; break;
case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */ case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
s[a] = REFER; s[a] |= BIT_REFER;
branchdest[index+2] = true; branchdest[index+2] = true;
break; break;
case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */ case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */
s[a] = REFER; s[a] |= BIT_REFER;
s[b] = REFER; s[b] |= BIT_REFER;
branchdest[index+2] = true; branchdest[index+2] = true;
break; break;
case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */ case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
while ( a < c-1 || a < b ) for ( int i=0; i<c-1; i++ )
s[a++] = (byte) (a<c-1 && a<b? REFER_ASSIGN: a<c-1? ASSIGN: REFER); s[a+i] |= BIT_ASSIGN;
while ( a < m ) for ( int i=0; i<b; i++ )
s[a++] = INVALID; s[a+i] |= BIT_REFER;
for ( a+=c; a<m; a++ )
s[a++] |= BIT_INVALID;
break; break;
case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
while ( a < b ) while ( a < b )
s[a++] = REFER; s[a++] |= BIT_REFER;
while ( a < m ) while ( a < m )
s[a++] = INVALID; s[a++] |= BIT_INVALID;
break; break;
case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */ case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
while ( a < b-1 ) while ( a < b-1 )
s[a++] = REFER; s[a++] |= BIT_REFER;
break; break;
case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */ case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */
s[a] = REFER_ASSIGN; s[a] |= BIT_REFER | BIT_ASSIGN;
s[a+2] = REFER; s[a+2] |= BIT_REFER;
branchdest[index+1+sbx] = true; branchdest[index+1+sbx] = true;
break; break;
case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) <?= R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/ case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) <?= R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/
s[a] = REFER_ASSIGN; s[a] |= BIT_REFER | BIT_ASSIGN;
s[a+1] = REFER; s[a+1] |= BIT_REFER;
s[a+2] = REFER; s[a+2] |= BIT_REFER;
s[a+3] = ASSIGN; s[a+3] |= BIT_ASSIGN;
branchdest[index+1+sbx] = true; branchdest[index+1+sbx] = true;
break; break;
@@ -251,25 +227,25 @@ public class Slots {
* R(A+2)): if R(A+3) ~= nil then R(A+2)=R(A+3) * R(A+2)): if R(A+3) ~= nil then R(A+2)=R(A+3)
* else pc++ * else pc++
*/ */
s[a] = REFER; s[a] |= BIT_REFER;
s[a+1] = REFER; s[a+1] |= BIT_REFER;
s[a+2] = REFER_ASSIGN; s[a+2] |= BIT_REFER | BIT_ASSIGN;
for ( int aa=a+3; aa<a+3+c; aa++ ) for ( int aa=a+3; aa<a+3+c; aa++ )
s[aa] = ASSIGN; s[aa] |= BIT_ASSIGN;
for ( int aa=a+3+c; aa<m; aa++ ) for ( int aa=a+3+c; aa<m; aa++ )
s[aa] = INVALID; s[aa] |= BIT_INVALID;
branchdest[index+2] = true; branchdest[index+2] = true;
break; break;
case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */ case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */
s[a] = REFER; s[a] |= BIT_REFER;
for ( int aa=1; aa<=b; aa++ ) for ( int aa=1; aa<=b; aa++ )
s[aa] = REFER; s[aa] |= BIT_REFER;
break; break;
case Lua.OP_CLOSE: /* A close all variables in the stack up to (>=) R(A)*/ case Lua.OP_CLOSE: /* A close all variables in the stack up to (>=) R(A)*/
while ( a<m ) while ( a<m )
s[a++] = INVALID; s[a++] |= BIT_INVALID;
break; break;
case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
@@ -281,15 +257,17 @@ public class Slots {
if ( (ins&4) != 0 ) { if ( (ins&4) != 0 ) {
// up : ups[b] // up : ups[b]
} else { } else {
s[b] = UPVAL_USE; s[b] |= BIT_REFER | BIT_UP_REFER;
} }
} }
s[a] = (byte) (s[a] == UPVAL_USE? UPVAL_USE_ASSIGN: ASSIGN); s[a] |= ((s[a] & BIT_UP_REFER) != 0 )?
(BIT_ASSIGN | BIT_UP_ASSIGN):
BIT_ASSIGN;
break; break;
} }
case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
while ( a<b ) while ( a<b )
s[a++] = ASSIGN; s[a++] |= BIT_ASSIGN;
break; break;
} }
} }
@@ -298,20 +276,15 @@ public class Slots {
private void markuninitialized(Prototype p) { private void markuninitialized(Prototype p) {
for ( int j=p.numparams; j<m; j++ ) for ( int j=p.numparams; j<m; j++ )
if ( ! isreferrededtofirst(j) ) if ( ! isreferrededtofirst(j) )
slots[0][j] = INVALID; slots[0][j] |= BIT_INVALID;
} }
private boolean isreferrededtofirst(int j) { private boolean isreferrededtofirst(int j) {
for ( int i=1; i<=n; i++ ) { for ( int i=1; i<=n; i++ ) {
switch (slots[i][j]) { if ( (slots[i][j] & (BIT_REFER | BIT_UP_REFER)) != 0 )
case REFER_ASSIGN:
case REFER:
case UPVAL_USE:
return true; return true;
case ASSIGN: if ( (slots[i][j] & (BIT_ASSIGN | BIT_UP_ASSIGN | BIT_UP_CREATE | BIT_INVALID)) != 0 )
case INVALID:
return false; return false;
}
} }
return false; return false;
} }
@@ -322,10 +295,10 @@ public class Slots {
int index = pc+1; int index = pc+1;
byte[] s = slots[index]; byte[] s = slots[index];
for ( int j=0; j<m; j++ ) for ( int j=0; j<m; j++ )
if ( s[j] == UPVAL_USE || s[j] == UPVAL_USE_ASSIGN ) { if ( (s[j] & BIT_REFER) != 0 ) {
promoteUpvalueBefore( s, index, j ); promoteUpvalueBefore( index, j );
if ( pc<n-1 ) if ( pc<n-1 )
promoteUpvalueAfter( s, index+1, j ); promoteUpvalueAfter( index+1, j );
} }
} }
} }
@@ -349,78 +322,120 @@ public class Slots {
} }
} }
} }
} }
private void checkPromoteLoopUpvalue(int index0, int index1, int slot) { private void checkPromoteLoopUpvalue(int index0, int index1, int slot) {
for ( int index=index0; index<=index1; ++index ) { for ( int index=index0; index<=index1; ++index ) {
switch (slots[index][slot]) { if ( (slots[index][slot] & BIT_UP_CREATE) != 0 ) {
case UPVAL_CREATE: for ( int i=index0+1; i<index1; ++i ) {
case UPVAL_USE_CREATE: promoteUpvalue(slots[i], slot);
case UPVAL_USE_ASSIGN: slots[i][slot] &= (~BIT_UP_CREATE);
case UPVAL_USE: }
int i = index0; slots[index1][slot] |= BIT_UP_CREATE;
slots[i][slot] = UPVAL_CREATE;
while ( ++i<=index1 )
slots[i][slot] = UPVAL_USE;
return; return;
} }
} }
} }
private void promoteUpvalueBefore(byte[] s, int index, int j) { private void promoteUpvalueBefore(int index, int j) {
int begin = prevUndefined(index,j); int begin = prevUndefined(index,j);
int assign = firstAssignAfter(begin,index,j); int assign = firstAssignAfter(begin,index,j);
slots[assign][j] = slots[assign][j]==UPVAL_USE_ASSIGN? UPVAL_USE_CREATE: UPVAL_CREATE; slots[assign][j] |= BIT_UP_CREATE;
while ( index>assign) while ( index>assign)
slots[index--][j] = UPVAL_USE; promoteUpvalue( slots[index--], j );
} }
private void promoteUpvalueAfter(byte[] s, int index, int j) { private void promoteUpvalueAfter(int index, int j) {
int end = nextUndefined(index,j); int end = nextUndefined(index,j);
int access = lastAccessBefore(end,index,j); int access = lastAccessBefore(end,index,j);
while ( index<=access ) while ( index<=access )
slots[index++][j] = UPVAL_USE; promoteUpvalue( slots[index++], j );
}
private void promoteUpvalue(byte[] s, int slot) {
if ( (s[slot] & BIT_REFER) != 0 )
s[slot] |= BIT_UP_REFER;
if ( (s[slot] & BIT_ASSIGN) != 0 )
s[slot] |= BIT_UP_ASSIGN;
} }
private int prevUndefined(int index, int j) { private int prevUndefined(int index, int j) {
while ( index>0 && slots[index][j] != INVALID ) while ( index>0 && ((slots[index][j] & BIT_INVALID) == 0) )
--index; --index;
return index; return index;
} }
private int firstAssignAfter(int index, int limit, int j) { private int firstAssignAfter(int index, int limit, int j) {
for ( ; index<limit; ++index ) { for ( ; index<limit; ++index ) {
switch (slots[index][j]) { if ( (slots[index][j] & BIT_ASSIGN) != 0 )
case ASSIGN:
case REFER_ASSIGN:
return index; return index;
case UPVAL_CREATE:
throw new IllegalStateException("overlapping upvalues");
}
} }
return index; return index;
} }
private int nextUndefined(int index, int j) { private int nextUndefined(int index, int j) {
while ( index+1<slots.length && slots[index+1][j] != INVALID ) while ( index<slots.length && ((slots[index][j] & BIT_INVALID) == 0) )
++index; ++index;
return index; return index;
} }
private int lastAccessBefore(int index, int limit, int j) { private int lastAccessBefore(int index, int limit, int j) {
for ( ; index>limit; --index ) { for ( --index; index>limit; --index ) {
switch (slots[index][j]) { if ( (slots[index][j] & (BIT_ASSIGN|BIT_REFER)) != 0 )
case ASSIGN:
case REFER_ASSIGN:
case REFER:
return index; return index;
case UPVAL_CREATE:
case UPVAL_USE:
throw new IllegalStateException("overlapping upvalues");
}
} }
return index; return index;
} }
// ------------- pretty-print slot info --------------
public static void printSlots(Prototype p) {
Slots s = new Slots(p);
System.out.println("slots for "+p.source+":\n"+s.toString(p) );
for ( int i=0; i<p.p.length; i++ )
printSlots(p.p[i]);
}
String[] toStrings() {
int n = slots.length;
int m = slots[0].length;
String[] strs = new String[n];
byte[] b = new byte[m+1];
for ( int i=0; i<n; i++ ) {
for ( int j=0; j<=m; j++ )
b[j] = ' ';
if ( branchdest[i] )
b[0] = 'D';
byte[] si = slots[i];
for ( int j=0; j<m; j++ ) {
byte s = si[j];
b[1+j] = (byte) (
((s & BIT_UP_CREATE) != 0)? 'C':
((s & BIT_UP_ASSIGN) != 0)?
(((s & BIT_UP_REFER) != 0)? 'B': 'A'):
((s & BIT_UP_REFER) != 0)? 'R':
((s & BIT_ASSIGN) != 0)?
(((s & BIT_REFER) != 0)? 'b': 'a'):
((s & BIT_REFER) != 0)? 'r':
((s & BIT_INVALID) != 0)? 'x':
((s & BIT_NIL) != 0)? 'n': ' ' );
}
strs[i] = new String(b);
}
return strs;
}
String toString(Prototype p) {
String[] s = toStrings();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream( baos );
for ( int i=0; i<s.length; i++ ) {
if ( i>0 ) ps.append( '\n' );
ps.append( s[i] );
if ( p != null && i>0 && i<=p.code.length )
Print.printOpCode(ps, p, i-1);
}
ps.close();
return baos.toString();
}
} }