| 407 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); |
| 408 | #if defined LUA_HAS_FLOAT_NUMBERS |
| 409 | else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) |
| 410 | luaG_runerror(L, "table index is NaN"); |
| 411 | #endif |
| 412 | mp = mainposition(t, key); |
| 413 | if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ |
| 414 | Node *othern; |
| 415 | Node *n = getfreepos(t); /* get a free place */ |
| 416 | if (n == NULL) { /* cannot find a free place? */ |
| 417 | rehash(L, t, key); /* grow table */ |
| 418 | /* whatever called 'newkey' take care of TM cache and GC barrier */ |
| 419 | return luaH_set(L, t, key); /* insert key into grown table */ |
| 420 | } |
| 421 | lua_assert(!isdummy(n)); |
| 422 | othern = mainposition(t, gkey(mp)); |
| 423 | if (othern != mp) { /* is colliding node out of its main position? */ |
| 424 | /* yes; move colliding node into free position */ |
| 425 | while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ |
| 426 | gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ |
| 427 | *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ |
| 428 | gnext(mp) = NULL; /* now `mp' is free */ |
| 429 | setnilvalue(gval(mp)); |
| 430 | } |
| 431 | else { /* colliding node is in its own main position */ |
| 432 | /* new node will go into free position */ |
| 433 | gnext(n) = gnext(mp); /* chain new position */ |
| 434 | gnext(mp) = n; |
| 435 | mp = n; |
| 436 | } |
| 437 | } |
| 438 | setobj2t(L, gkey(mp), key); |
| 439 | luaC_barrierback(L, obj2gco(t), key); |
| 440 | lua_assert(ttisnil(gval(mp))); |
no test coverage detected