Code generator improvements.
This commit is contained in:
@@ -104,11 +104,17 @@ public class Slots {
|
|||||||
|
|
||||||
switch ( Lua.GET_OPCODE(ins) ) {
|
switch ( Lua.GET_OPCODE(ins) ) {
|
||||||
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_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
|
case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
|
||||||
|
case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */
|
||||||
|
case Lua.OP_GETGLOBAL: /* A Bx R(A):= Gbl[Kst(Bx)] */
|
||||||
s[a] |= BIT_ASSIGN;
|
s[a] |= BIT_ASSIGN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */
|
||||||
|
case Lua.OP_SETGLOBAL: /* A Bx Gbl[Kst(Bx)]:= R(A) */
|
||||||
|
s[a] |= BIT_REFER;
|
||||||
|
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) */
|
||||||
@@ -117,14 +123,8 @@ public class Slots {
|
|||||||
s[b] |= BIT_REFER;
|
s[b] |= BIT_REFER;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */
|
|
||||||
case Lua.OP_GETGLOBAL: /* A Bx R(A):= Gbl[Kst(Bx)] */
|
|
||||||
case Lua.OP_SETGLOBAL: /* A Bx Gbl[Kst(Bx)]:= R(A) */
|
|
||||||
s[a] |= BIT_ASSIGN;
|
|
||||||
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++] |= BIT_ASSIGN;
|
s[a++] |= BIT_ASSIGN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -166,11 +166,12 @@ public class Slots {
|
|||||||
|
|
||||||
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] |= BIT_ASSIGN;
|
s[a] |= BIT_ASSIGN;
|
||||||
if ( c!=0 ) branchdest[index+2] = true;
|
//if ( c!=0 ) branchdest[index+2] = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Lua.OP_JMP: /* sBx pc+=sBx */
|
case Lua.OP_JMP: /* sBx pc+=sBx */
|
||||||
branchdest[index+1+sbx] = true;
|
if ( sbx < 0 )
|
||||||
|
branchdest[index+1+sbx] = true;
|
||||||
ins = p.code[index+0+sbx];
|
ins = p.code[index+0+sbx];
|
||||||
if ( Lua.GET_OPCODE(ins) == Lua.OP_TFORLOOP ) {
|
if ( Lua.GET_OPCODE(ins) == Lua.OP_TFORLOOP ) {
|
||||||
a = Lua.GETARG_A(ins);
|
a = Lua.GETARG_A(ins);
|
||||||
@@ -185,34 +186,36 @@ public class Slots {
|
|||||||
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] |= BIT_REFER;
|
if (bx<=0xff) s[bx] |= BIT_REFER;
|
||||||
if (c<=0xff) s[c] |= BIT_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] |= BIT_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] |= BIT_REFER;
|
s[a] |= BIT_REFER;
|
||||||
s[b] |= BIT_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)) */
|
||||||
for ( int i=0; i<c-1; i++ )
|
s[a] |= BIT_ASSIGN | BIT_REFER;
|
||||||
s[a+i] |= BIT_ASSIGN;
|
for ( int i=1; i<b; i++ )
|
||||||
for ( int i=0; i<b; i++ )
|
|
||||||
s[a+i] |= BIT_REFER;
|
s[a+i] |= BIT_REFER;
|
||||||
for ( a+=c; a<m; a++ )
|
for ( int i=1; i<c-1; i++ )
|
||||||
s[a++] |= BIT_INVALID;
|
s[++a] |= BIT_ASSIGN;
|
||||||
|
while ( ++a<m )
|
||||||
|
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 )
|
s[a] |= BIT_REFER;
|
||||||
s[a++] |= BIT_REFER;
|
for ( int i=1; i<b; i++ )
|
||||||
while ( a < m )
|
s[++a] |= BIT_REFER;
|
||||||
s[a++] |= BIT_INVALID;
|
while ( ++a<m )
|
||||||
|
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) */
|
||||||
@@ -355,8 +358,9 @@ public class Slots {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void promoteUpvalueBefore(int index, int j) {
|
private void promoteUpvalueBefore(int index, int j) {
|
||||||
int begin = prevUndefined(index,j);
|
int undef = prevUndefined(index,j);
|
||||||
int assign = firstAssignAfter(begin,index,j);
|
int branch = firstBranchAfter(undef,index,j);
|
||||||
|
int assign = lastAssignBefore(branch,undef,j);
|
||||||
slots[assign][j] |= BIT_UP_CREATE;
|
slots[assign][j] |= BIT_UP_CREATE;
|
||||||
while ( index>assign)
|
while ( index>assign)
|
||||||
promoteUpvalue( slots[index--], j );
|
promoteUpvalue( slots[index--], j );
|
||||||
@@ -377,16 +381,23 @@ public class Slots {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int prevUndefined(int index, int j) {
|
private int prevUndefined(int index, int j) {
|
||||||
while ( index>0 && ((slots[index][j] & BIT_INVALID) == 0) )
|
for ( ; index>=0; --index )
|
||||||
--index;
|
if ( ((slots[index][j] & BIT_INVALID) != 0) )
|
||||||
|
return 0;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int firstAssignAfter(int index, int limit, int j) {
|
private int firstBranchAfter(int index, int limit, int j) {
|
||||||
for ( ; index<limit; ++index ) {
|
for ( ; ++index<limit; )
|
||||||
if ( (slots[index][j] & BIT_ASSIGN) != 0 )
|
if ( index>0 && this.branchdest[index-1] )
|
||||||
return index;
|
return index;
|
||||||
}
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int lastAssignBefore(int index, int limit, int j) {
|
||||||
|
for ( int i=index-1; i>limit; --i )
|
||||||
|
if ( (slots[i][j] & (BIT_ASSIGN | BIT_NIL)) != 0 )
|
||||||
|
return i;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,10 +408,9 @@ public class Slots {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int lastAccessBefore(int index, int limit, int j) {
|
private int lastAccessBefore(int index, int limit, int j) {
|
||||||
for ( --index; index>limit; --index ) {
|
for ( --index; index>limit; --index )
|
||||||
if ( (slots[index][j] & (BIT_ASSIGN|BIT_REFER)) != 0 )
|
if ( (slots[index][j] & (BIT_ASSIGN|BIT_REFER)) != 0 )
|
||||||
return index;
|
return index;
|
||||||
}
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -291,4 +291,47 @@ public class FragmentsTest extends TestCase {
|
|||||||
"end\n" +
|
"end\n" +
|
||||||
"return foo().a\n" );
|
"return foo().a\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testLoadNilUpvalue() {
|
||||||
|
runFragment( LuaValue.NIL,
|
||||||
|
"tostring = function() end\n" +
|
||||||
|
"local pc \n" +
|
||||||
|
"local pcall = function(...)\n" +
|
||||||
|
" pc(...)\n" +
|
||||||
|
"end\n" +
|
||||||
|
"return NIL\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpvalueClosure() {
|
||||||
|
runFragment( LuaValue.NIL,
|
||||||
|
"print()\n"+
|
||||||
|
"local function f2() end\n"+
|
||||||
|
"local function f3()\n"+
|
||||||
|
" return f3\n"+
|
||||||
|
"end\n" +
|
||||||
|
"return NIL\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUninitializedUpvalue() {
|
||||||
|
runFragment( LuaValue.NIL,
|
||||||
|
"local f\n"+
|
||||||
|
"do\n"+
|
||||||
|
" function g()\n"+
|
||||||
|
" print(f())\n"+
|
||||||
|
" end\n"+
|
||||||
|
"end\n" +
|
||||||
|
"return NIL\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTestOpUpvalues() {
|
||||||
|
runFragment( LuaValue.varargsOf(LuaValue.valueOf(1),LuaValue.valueOf(2),LuaValue.valueOf(3)),
|
||||||
|
"print( nil and 'T' or 'F' )\n"+
|
||||||
|
"local a,b,c = 1,2,3\n"+
|
||||||
|
"function foo()\n"+
|
||||||
|
" return a,b,c\n"+
|
||||||
|
"end\n" +
|
||||||
|
"return foo()\n" );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user