diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-03-27 14:56:10 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-03-27 14:56:10 -0300 |
commit | d12262068d689eacc452a459a021df0ad8f6d46c (patch) | |
tree | d3e839cd1ddf3daf5e12c8f472c10a980b7d9d8c | |
parent | 0443ad9e288825b6e4441eb11104bcdb4ff4593a (diff) | |
download | lua-d12262068d689eacc452a459a021df0ad8f6d46c.tar.gz lua-d12262068d689eacc452a459a021df0ad8f6d46c.tar.bz2 lua-d12262068d689eacc452a459a021df0ad8f6d46c.zip |
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.
-rw-r--r-- | lapi.c | 10 | ||||
-rw-r--r-- | ltable.c | 10 | ||||
-rw-r--r-- | ltablib.c | 8 | ||||
-rw-r--r-- | testes/utf8.lua | 3 |
4 files changed, 20 insertions, 11 deletions
@@ -936,8 +936,8 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { | |||
936 | api_checknelems(L, 1); | 936 | api_checknelems(L, 1); |
937 | o = index2value(L, idx); | 937 | o = index2value(L, idx); |
938 | api_check(L, ttisfulluserdata(o), "full userdata expected"); | 938 | api_check(L, ttisfulluserdata(o), "full userdata expected"); |
939 | if (!(0 < n && n <= uvalue(o)->nuvalue)) | 939 | if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue))) |
940 | res = 0; | 940 | res = 0; /* 'n' not in [1, uvalue(o)->nuvalue] */ |
941 | else { | 941 | else { |
942 | setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1)); | 942 | setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1)); |
943 | luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); | 943 | luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); |
@@ -1313,7 +1313,8 @@ static const char *aux_upvalue (TValue *fi, int n, TValue **val, | |||
1313 | switch (ttypetag(fi)) { | 1313 | switch (ttypetag(fi)) { |
1314 | case LUA_TCCL: { /* C closure */ | 1314 | case LUA_TCCL: { /* C closure */ |
1315 | CClosure *f = clCvalue(fi); | 1315 | CClosure *f = clCvalue(fi); |
1316 | if (!(1 <= n && n <= f->nupvalues)) return NULL; | 1316 | if (!(cast_uint(n) - 1u < cast_uint(f->nupvalues))) |
1317 | return NULL; /* 'n' not in [1, f->nupvalues] */ | ||
1317 | *val = &f->upvalue[n-1]; | 1318 | *val = &f->upvalue[n-1]; |
1318 | if (owner) *owner = obj2gco(f); | 1319 | if (owner) *owner = obj2gco(f); |
1319 | return ""; | 1320 | return ""; |
@@ -1322,7 +1323,8 @@ static const char *aux_upvalue (TValue *fi, int n, TValue **val, | |||
1322 | LClosure *f = clLvalue(fi); | 1323 | LClosure *f = clLvalue(fi); |
1323 | TString *name; | 1324 | TString *name; |
1324 | Proto *p = f->p; | 1325 | Proto *p = f->p; |
1325 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; | 1326 | if (!(cast_uint(n) - 1u < cast_uint(p->sizeupvalues))) |
1327 | return NULL; /* 'n' not in [1, p->sizeupvalues] */ | ||
1326 | *val = f->upvals[n-1]->v; | 1328 | *val = f->upvals[n-1]->v; |
1327 | if (owner) *owner = obj2gco(f->upvals[n - 1]); | 1329 | if (owner) *owner = obj2gco(f->upvals[n - 1]); |
1328 | name = p->upvalues[n-1].name; | 1330 | name = p->upvalues[n-1].name; |
@@ -48,8 +48,8 @@ | |||
48 | 48 | ||
49 | /* | 49 | /* |
50 | ** MAXASIZE is the maximum size of the array part. It is the minimum | 50 | ** MAXASIZE is the maximum size of the array part. It is the minimum |
51 | ** between 2^MAXABITS and the maximum size such that, measured in bytes, | 51 | ** between 2^MAXABITS and the maximum size that, measured in bytes, |
52 | ** it fits in a 'size_t'. | 52 | ** fits in a 'size_t'. |
53 | */ | 53 | */ |
54 | #define MAXASIZE luaM_limitN(1u << MAXABITS, TValue) | 54 | #define MAXASIZE luaM_limitN(1u << MAXABITS, TValue) |
55 | 55 | ||
@@ -269,7 +269,7 @@ static const TValue *getgeneric (Table *t, const TValue *key) { | |||
269 | ** the array part of a table, 0 otherwise. | 269 | ** the array part of a table, 0 otherwise. |
270 | */ | 270 | */ |
271 | static unsigned int arrayindex (lua_Integer k) { | 271 | static unsigned int arrayindex (lua_Integer k) { |
272 | if (0 < k && l_castS2U(k) <= MAXASIZE) | 272 | if (l_castS2U(k) - 1u < MAXASIZE) /* 'k' in [1, MAXASIZE]? */ |
273 | return cast_uint(k); /* 'key' is an appropriate array index */ | 273 | return cast_uint(k); /* 'key' is an appropriate array index */ |
274 | else | 274 | else |
275 | return 0; | 275 | return 0; |
@@ -286,7 +286,7 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key, | |||
286 | unsigned int i; | 286 | unsigned int i; |
287 | if (ttisnil(key)) return 0; /* first iteration */ | 287 | if (ttisnil(key)) return 0; /* first iteration */ |
288 | i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0; | 288 | i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0; |
289 | if (i != 0 && i <= asize) /* is 'key' inside array part? */ | 289 | if (i - 1u < asize) /* is 'key' inside array part? */ |
290 | return i; /* yes; that's the index */ | 290 | return i; /* yes; that's the index */ |
291 | else { | 291 | else { |
292 | const TValue *n = getgeneric(t, key); | 292 | const TValue *n = getgeneric(t, key); |
@@ -678,7 +678,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
678 | ** changing the real size of the array). | 678 | ** changing the real size of the array). |
679 | */ | 679 | */ |
680 | const TValue *luaH_getint (Table *t, lua_Integer key) { | 680 | const TValue *luaH_getint (Table *t, lua_Integer key) { |
681 | if (l_castS2U(key) - 1u < t->alimit) /* (1 <= key && key <= t->alimit)? */ | 681 | if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */ |
682 | return &t->array[key - 1]; | 682 | return &t->array[key - 1]; |
683 | else if (!limitequalsasize(t) && /* key still may be in the array part? */ | 683 | else if (!limitequalsasize(t) && /* key still may be in the array part? */ |
684 | (l_castS2U(key) == t->alimit + 1 || | 684 | (l_castS2U(key) == t->alimit + 1 || |
@@ -69,7 +69,9 @@ static int tinsert (lua_State *L) { | |||
69 | case 3: { | 69 | case 3: { |
70 | lua_Integer i; | 70 | lua_Integer i; |
71 | pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ | 71 | pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ |
72 | luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); | 72 | /* check whether 'pos' is in [1, e] */ |
73 | luaL_argcheck(L, (lua_Unsigned)pos - 1u < (lua_Unsigned)e, 2, | ||
74 | "position out of bounds"); | ||
73 | for (i = e; i > pos; i--) { /* move up elements */ | 75 | for (i = e; i > pos; i--) { /* move up elements */ |
74 | lua_geti(L, 1, i - 1); | 76 | lua_geti(L, 1, i - 1); |
75 | lua_seti(L, 1, i); /* t[i] = t[i - 1] */ | 77 | lua_seti(L, 1, i); /* t[i] = t[i - 1] */ |
@@ -89,7 +91,9 @@ static int tremove (lua_State *L) { | |||
89 | lua_Integer size = aux_getn(L, 1, TAB_RW); | 91 | lua_Integer size = aux_getn(L, 1, TAB_RW); |
90 | lua_Integer pos = luaL_optinteger(L, 2, size); | 92 | lua_Integer pos = luaL_optinteger(L, 2, size); |
91 | if (pos != size) /* validate 'pos' if given */ | 93 | if (pos != size) /* validate 'pos' if given */ |
92 | luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); | 94 | /* check whether 'pos' is in [1, size + 1] */ |
95 | luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 1, | ||
96 | "position out of bounds"); | ||
93 | lua_geti(L, 1, pos); /* result = t[pos] */ | 97 | lua_geti(L, 1, pos); /* result = t[pos] */ |
94 | for ( ; pos < size; pos++) { | 98 | for ( ; pos < size; pos++) { |
95 | lua_geti(L, 1, pos + 1); | 99 | lua_geti(L, 1, pos + 1); |
diff --git a/testes/utf8.lua b/testes/utf8.lua index 86ec1b00..b3b7687f 100644 --- a/testes/utf8.lua +++ b/testes/utf8.lua | |||
@@ -123,6 +123,9 @@ checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) | |||
123 | checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) | 123 | checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) |
124 | checkerror("continuation byte", utf8.offset, "\x80", 1) | 124 | checkerror("continuation byte", utf8.offset, "\x80", 1) |
125 | 125 | ||
126 | -- error in indices for len | ||
127 | checkerror("out of string", utf8.len, "abc", 0, 2) | ||
128 | checkerror("out of string", utf8.len, "abc", 1, 4) | ||
126 | 129 | ||
127 | 130 | ||
128 | local s = "hello World" | 131 | local s = "hello World" |