Small optimizations in range checks

Checks of the form '1 <= x && x <= M' were rewritten in the form
'(unsigned)x - 1 < (unsigned)M', which is usually more efficient.
(Other similar checks have similar translations.) Although
some compilers do these optimizations, that does not happen
for all compilers or all cases.
This commit is contained in:
Roberto Ierusalimschy 2019-03-27 14:56:10 -03:00
parent 0443ad9e28
commit d12262068d
4 changed files with 20 additions and 11 deletions

10
lapi.c
View File

@ -936,8 +936,8 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) {
api_checknelems(L, 1);
o = index2value(L, idx);
api_check(L, ttisfulluserdata(o), "full userdata expected");
if (!(0 < n && n <= uvalue(o)->nuvalue))
res = 0;
if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue)))
res = 0; /* 'n' not in [1, uvalue(o)->nuvalue] */
else {
setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1));
luaC_barrierback(L, gcvalue(o), s2v(L->top - 1));
@ -1313,7 +1313,8 @@ static const char *aux_upvalue (TValue *fi, int n, TValue **val,
switch (ttypetag(fi)) {
case LUA_TCCL: { /* C closure */
CClosure *f = clCvalue(fi);
if (!(1 <= n && n <= f->nupvalues)) return NULL;
if (!(cast_uint(n) - 1u < cast_uint(f->nupvalues)))
return NULL; /* 'n' not in [1, f->nupvalues] */
*val = &f->upvalue[n-1];
if (owner) *owner = obj2gco(f);
return "";
@ -1322,7 +1323,8 @@ static const char *aux_upvalue (TValue *fi, int n, TValue **val,
LClosure *f = clLvalue(fi);
TString *name;
Proto *p = f->p;
if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
if (!(cast_uint(n) - 1u < cast_uint(p->sizeupvalues)))
return NULL; /* 'n' not in [1, p->sizeupvalues] */
*val = f->upvals[n-1]->v;
if (owner) *owner = obj2gco(f->upvals[n - 1]);
name = p->upvalues[n-1].name;

View File

@ -48,8 +48,8 @@
/*
** MAXASIZE is the maximum size of the array part. It is the minimum
** between 2^MAXABITS and the maximum size such that, measured in bytes,
** it fits in a 'size_t'.
** between 2^MAXABITS and the maximum size that, measured in bytes,
** fits in a 'size_t'.
*/
#define MAXASIZE luaM_limitN(1u << MAXABITS, TValue)
@ -269,7 +269,7 @@ static const TValue *getgeneric (Table *t, const TValue *key) {
** the array part of a table, 0 otherwise.
*/
static unsigned int arrayindex (lua_Integer k) {
if (0 < k && l_castS2U(k) <= MAXASIZE)
if (l_castS2U(k) - 1u < MAXASIZE) /* 'k' in [1, MAXASIZE]? */
return cast_uint(k); /* 'key' is an appropriate array index */
else
return 0;
@ -286,7 +286,7 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key,
unsigned int i;
if (ttisnil(key)) return 0; /* first iteration */
i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0;
if (i != 0 && i <= asize) /* is 'key' inside array part? */
if (i - 1u < asize) /* is 'key' inside array part? */
return i; /* yes; that's the index */
else {
const TValue *n = getgeneric(t, key);
@ -678,7 +678,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
** changing the real size of the array).
*/
const TValue *luaH_getint (Table *t, lua_Integer key) {
if (l_castS2U(key) - 1u < t->alimit) /* (1 <= key && key <= t->alimit)? */
if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */
return &t->array[key - 1];
else if (!limitequalsasize(t) && /* key still may be in the array part? */
(l_castS2U(key) == t->alimit + 1 ||

View File

@ -69,7 +69,9 @@ static int tinsert (lua_State *L) {
case 3: {
lua_Integer i;
pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */
luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
/* check whether 'pos' is in [1, e] */
luaL_argcheck(L, (lua_Unsigned)pos - 1u < (lua_Unsigned)e, 2,
"position out of bounds");
for (i = e; i > pos; i--) { /* move up elements */
lua_geti(L, 1, i - 1);
lua_seti(L, 1, i); /* t[i] = t[i - 1] */
@ -89,7 +91,9 @@ static int tremove (lua_State *L) {
lua_Integer size = aux_getn(L, 1, TAB_RW);
lua_Integer pos = luaL_optinteger(L, 2, size);
if (pos != size) /* validate 'pos' if given */
luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
/* check whether 'pos' is in [1, size + 1] */
luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 1,
"position out of bounds");
lua_geti(L, 1, pos); /* result = t[pos] */
for ( ; pos < size; pos++) {
lua_geti(L, 1, pos + 1);

View File

@ -123,6 +123,9 @@ checkerror("continuation byte", utf8.offset, "𦧺", 1, 2)
checkerror("continuation byte", utf8.offset, "𦧺", 1, 2)
checkerror("continuation byte", utf8.offset, "\x80", 1)
-- error in indices for len
checkerror("out of string", utf8.len, "abc", 0, 2)
checkerror("out of string", utf8.len, "abc", 1, 4)
local s = "hello World"