lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi,

Following up to myself:
>   A combined inline assembler replacement may speed up the code quite
>   a bit. Anyone know what the fastest way to determine whether a double
>   fits into an int is on x86?

Well, it's simpler than I thought: the FPU already stores overflow and
precision loss bits in the status word. You just have to check them after
the fistpl instruction.

>                 -O     -O2    -O3 -fomit-frame-pointer
> lua-5.0.2       3.30   3.40   3.60
> lua-5.1-work0   3.72   4.30   3.44
> lua-5.1-work2   4.03   4.18   3.50

Trying the same tests with the appended patch:

lua-5.1-work2a    3.82   4.07   3.28

Looks better now.

There are plenty more optimization opportunities in ltable.c and lvm.c,
but I'll leave that to someone with an immediate need. Dito for the
conversion of the GCC assembler macros to MSVC syntax.

Bye,
     Mike
--- lua-5.1-work2/include/luaconf.h	2004-09-21 13:11:00.000000000 +0200
+++ lua-5.1-work2a/include/luaconf.h	2004-09-25 17:56:50.000000000 +0200
@@ -170,6 +170,8 @@
 /* function to convert a lua_Number to int (with any rounding method) */
 #if defined(__GNUC__) && defined(__i386)
 #define lua_number2int(i,d)	__asm__ ("fistpl %0":"=m"(i):"t"(d):"st")
+#define lua_number2intcheck(i,d,st) \
+  {__asm__ ("fistpl %0; fnstsw %%ax":"=m"(i),"=a"(st):"t"(d):"st"); st&=0x3f;}
 #elif 0
 /* on machines compliant with C99, you can try `lrint' */
 #include <math.h>
@@ -178,6 +180,11 @@
 #define lua_number2int(i,d)	((i)=(int)(d))
 #endif
 
+#ifndef lua_number2intcheck
+#define lua_number2intcheck(i,d,st) \
+  {lua_number2int(i,d); st = (cast(lua_Number, i) != (d));}
+#endif
+
 /* function to convert a lua_Number to lua_Integer (with any rounding method) */
 #define lua_number2integer(i,n)		lua_number2int(i,n)
 
--- lua-5.1-work2/src/ltable.c	2004-08-31 19:57:33.000000000 +0200
+++ lua-5.1-work2a/src/ltable.c	2004-09-25 17:57:26.000000000 +0200
@@ -107,13 +107,11 @@
 ** returns the index for `key' if `key' is an appropriate key to live in
 ** the array part of the table, -1 otherwise.
 */
-static int arrayindex (const TValue *key, lua_Number lim) {
+static int arrayindex (const TValue *key, int lim) {
   if (ttisnumber(key)) {
-    lua_Number n = nvalue(key);
-    int k;
-    if (n <= 0 || n > lim) return -1;  /* out of range? */
-    lua_number2int(k, n);
-    if (cast(lua_Number, k) == nvalue(key))
+    int k, st;
+    lua_number2intcheck(k, nvalue(key), st)
+    if (!st && (unsigned int)(k-1) < (unsigned int)lim)
       return k;
   }
   return -1;  /* `key' did not match some condition */
@@ -195,7 +193,7 @@
   int nums[MAXBITS+1];
   int i, lg;
   int totaluse = 0;
-  lua_Number sizelimit;  /* an upper bound for the array size */
+  int sizelimit;  /* an upper bound for the array size */
   /* count elements in array part */
   for (i=0, lg=0; lg<=MAXBITS; lg++) {  /* for each slice [2^(lg-1) to 2^lg) */
     int ttlg = twoto(lg);  /* 2^lg */
@@ -216,7 +214,7 @@
   /* count elements in hash part */
   i = sizenode(t);
   /* array part cannot be larger than twice the maximum number of elements */
-  sizelimit = cast(lua_Number, totaluse + i) * 2;
+  sizelimit = (totaluse + i) * 2;
   if (sizelimit >= MAXASIZE) sizelimit = MAXASIZE;
   while (i--) {
     Node *n = &t->node[i];
@@ -397,7 +395,7 @@
 ** search function for integers
 */
 const TValue *luaH_getnum (Table *t, int key) {
-  if (1 <= key && key <= t->sizearray)
+  if ((unsigned int)(key-1) < (unsigned int)t->sizearray)
     return &t->array[key-1];
   else {
     lua_Number nk = cast(lua_Number, key);
@@ -425,30 +423,31 @@
   return &luaO_nilobject;
 }
 
+static const TValue *luaH_getany (Table *t, const TValue *key) {
+  if (!ttisnil(key)) {
+    Node *n = luaH_mainposition(t, key);
+    do {  /* check whether `key' is somewhere in the chain */
+      if (luaO_rawequalObj(gkey(n), key)) return gval(n);  /* that's it */
+      else n = n->next;
+    } while (n);
+  }
+  return &luaO_nilobject;
+}
 
 /*
 ** main search function
 */
 const TValue *luaH_get (Table *t, const TValue *key) {
-  switch (ttype(key)) {
-    case LUA_TNIL: return &luaO_nilobject;
-    case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
-    case LUA_TNUMBER: {
-      int k;
-      lua_number2int(k, (nvalue(key)));
-      if (cast(lua_Number, k) == nvalue(key))  /* is an integer index? */
-        return luaH_getnum(t, k);  /* use specialized version */
-      /* else go through */
-    }
-    default: {
-      Node *n = luaH_mainposition(t, key);
-      do {  /* check whether `key' is somewhere in the chain */
-        if (luaO_rawequalObj(gkey(n), key)) return gval(n);  /* that's it */
-        else n = n->next;
-      } while (n);
-      return &luaO_nilobject;
-    }
+  int tt = ttype(key);
+  if (tt == LUA_TNUMBER) {
+    int k, st;
+    lua_number2intcheck(k, nvalue(key), st)
+    if (!st) return luaH_getnum(t, k);  /* use specialized version for ints */
+    /* else go through */
+  } else if (tt == LUA_TSTRING) {
+    return luaH_getstr(t, rawtsvalue(key));
   }
+  return luaH_getany(t, key);
 }