Skip to content

Commit 67532d5

Browse files
committed
constant folding and API arithmetic with integers
1 parent 6920a7f commit 67532d5

4 files changed

Lines changed: 83 additions & 31 deletions

File tree

lapi.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lapi.c,v 2.177 2013/04/26 19:51:17 roberto Exp roberto $
2+
** $Id: lapi.c,v 2.178 2013/04/29 17:12:50 roberto Exp roberto $
33
** Lua API
44
** See Copyright Notice in lua.h
55
*/
@@ -297,9 +297,6 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
297297

298298

299299
LUA_API void lua_arith (lua_State *L, int op) {
300-
StkId o1; /* 1st operand */
301-
StkId o2; /* 2nd operand */
302-
lua_Number n1, n2;
303300
lua_lock(L);
304301
if (op != LUA_OPUNM) /* all other operations expect two operands */
305302
api_checknelems(L, 2);
@@ -308,13 +305,9 @@ LUA_API void lua_arith (lua_State *L, int op) {
308305
setobjs2s(L, L->top, L->top - 1);
309306
L->top++;
310307
}
311-
o1 = L->top - 2;
312-
o2 = L->top - 1;
313-
if (tonumber(o1, &n1) && tonumber(o2, &n2)) {
314-
setnvalue(o1, luaO_numarith(op, n1, n2));
315-
}
316-
else luaT_trybinTM(L, o1, o2, o1, cast(TMS, op - LUA_OPADD + TM_ADD));
317-
L->top--;
308+
/* first operand at top - 2, second at top - 1; result go to top - 2 */
309+
luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
310+
L->top--; /* remove second operand */
318311
lua_unlock(L);
319312
}
320313

lcode.c

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lcode.c,v 2.66 2013/04/26 13:07:53 roberto Exp roberto $
2+
** $Id: lcode.c,v 2.67 2013/04/29 16:57:48 roberto Exp roberto $
33
** Code generator for Lua
44
** See Copyright Notice in lua.h
55
*/
@@ -29,8 +29,18 @@
2929
#define hasjumps(e) ((e)->t != (e)->f)
3030

3131

32-
static int isnumeral(expdesc *e) {
33-
return (e->k == VKFLT && e->t == NO_JUMP && e->f == NO_JUMP);
32+
static int tonumeral(expdesc *e, TValue *v) {
33+
if (e->t != NO_JUMP || e->f != NO_JUMP)
34+
return 0; /* not a numeral */
35+
switch (e->k) {
36+
case VKINT:
37+
if (v) setivalue(v, e->u.ival);
38+
return 1;
39+
case VKFLT:
40+
if (v) setnvalue(v, e->u.nval);
41+
return 1;
42+
default: return 0;
43+
}
3444
}
3545

3646

@@ -730,21 +740,28 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
730740

731741

732742
static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
733-
lua_Number r;
734-
if (!isnumeral(e1) || !isnumeral(e2)) return 0;
735-
if ((op == OP_DIV || op == OP_IDIV || op == OP_MOD) && e2->u.nval == 0)
736-
return 0; /* do not attempt to divide by 0 */
737-
r = luaO_numarith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval);
738-
e1->u.nval = r;
743+
TValue v1, v2, res;
744+
lua_Integer i2;
745+
if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2))
746+
return 0;
747+
if ((op == OP_IDIV || op == OP_MOD) && tointeger(&v2, &i2) && i2 == 0)
748+
return 0; /* avoid division by 0 at compile time */
749+
luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res);
750+
if (ttisinteger(&res)) {
751+
e1->k = VKINT;
752+
e1->u.ival = ivalue(&res);
753+
}
754+
else {
755+
e1->k = VKFLT;
756+
e1->u.nval = fltvalue(&res);
757+
}
739758
return 1;
740759
}
741760

742761

743762
static void codearith (FuncState *fs, OpCode op,
744763
expdesc *e1, expdesc *e2, int line) {
745-
if (constfolding(op, e1, e2))
746-
return;
747-
else {
764+
if (!constfolding(op, e1, e2)) { /* could not fold operation? */
748765
int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
749766
int o1 = luaK_exp2RK(fs, e1);
750767
if (o1 > o2) {
@@ -783,9 +800,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
783800
e2.t = e2.f = NO_JUMP; e2.k = VKFLT; e2.u.nval = 0;
784801
switch (op) {
785802
case OPR_MINUS: {
786-
if (isnumeral(e)) /* minus constant? */
787-
e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */
788-
else {
803+
if (!constfolding(OP_UNM, e, e)) { /* cannot fold it? */
789804
luaK_exp2anyreg(fs, e);
790805
codearith(fs, OP_UNM, e, &e2, line);
791806
}
@@ -819,7 +834,7 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
819834
case OPR_ADD: case OPR_SUB:
820835
case OPR_MUL: case OPR_DIV: case OPR_IDIV:
821836
case OPR_MOD: case OPR_POW: {
822-
if (!isnumeral(v)) luaK_exp2RK(fs, v);
837+
if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v);
823838
break;
824839
}
825840
default: {

lobject.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lobject.c,v 2.60 2013/04/25 13:53:13 roberto Exp roberto $
2+
** $Id: lobject.c,v 2.61 2013/04/29 16:57:28 roberto Exp roberto $
33
** Some generic functions over Lua objects
44
** See Copyright Notice in lua.h
55
*/
@@ -70,7 +70,21 @@ int luaO_ceillog2 (unsigned int x) {
7070
}
7171

7272

73-
lua_Number luaO_numarith (int op, lua_Number v1, lua_Number v2) {
73+
static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
74+
lua_Integer v2) {
75+
switch (op) {
76+
case LUA_OPADD: return intop(+, v1, v2);
77+
case LUA_OPSUB:return intop(-, v1, v2);
78+
case LUA_OPMUL:return intop(*, v1, v2);
79+
case LUA_OPMOD: return luaV_mod(L, v1, v2);
80+
case LUA_OPPOW: return luaV_pow(v1, v2);
81+
case LUA_OPUNM: return -v1;
82+
default: lua_assert(0); return 0;
83+
}
84+
}
85+
86+
87+
static lua_Number numarith (int op, lua_Number v1, lua_Number v2) {
7488
switch (op) {
7589
case LUA_OPADD: return luai_numadd(NULL, v1, v2);
7690
case LUA_OPSUB: return luai_numsub(NULL, v1, v2);
@@ -84,6 +98,35 @@ lua_Number luaO_numarith (int op, lua_Number v1, lua_Number v2) {
8498
}
8599

86100

101+
void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
102+
TValue *res) {
103+
if (op == LUA_OPIDIV) { /* operates only on integers */
104+
lua_Integer i1; lua_Integer i2;
105+
if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
106+
setivalue(res, luaV_div(L, i1, i2));
107+
return;
108+
}
109+
/* else go to the end */
110+
}
111+
else { /* other operations */
112+
lua_Number n1; lua_Number n2;
113+
if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV &&
114+
(op != LUA_OPPOW || ivalue(p2) >= 0)) {
115+
setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
116+
return;
117+
}
118+
else if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
119+
setnvalue(res, numarith(op, n1, n2));
120+
return;
121+
}
122+
/* else go to the end */
123+
}
124+
/* could not perform raw operation; try metmethod */
125+
lua_assert(L != NULL); /* cannot fail when folding (compile time) */
126+
luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD));
127+
}
128+
129+
87130
int luaO_hexavalue (int c) {
88131
if (lisdigit(c)) return c - '0';
89132
else return ltolower(c) - 'a' + 10;

lobject.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lobject.h,v 2.74 2013/04/16 18:46:28 roberto Exp roberto $
2+
** $Id: lobject.h,v 2.75 2013/04/29 16:57:28 roberto Exp roberto $
33
** Type definitions for Lua objects
44
** See Copyright Notice in lua.h
55
*/
@@ -496,7 +496,8 @@ LUAI_DDEC const TValue luaO_nilobject_;
496496
LUAI_FUNC int luaO_int2fb (unsigned int x);
497497
LUAI_FUNC int luaO_fb2int (int x);
498498
LUAI_FUNC int luaO_ceillog2 (unsigned int x);
499-
LUAI_FUNC lua_Number luaO_numarith (int op, lua_Number v1, lua_Number v2);
499+
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
500+
const TValue *p2, TValue *res);
500501
LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result);
501502
LUAI_FUNC int luaO_str2int (const char *s, lua_Integer *result);
502503
LUAI_FUNC int luaO_hexavalue (int c);

0 commit comments

Comments
 (0)