Coverage Report

Created: 2025-01-28 06:45

/src/tarantool/third_party/luajit/src/lj_meta.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** Metamethod handling.
3
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
4
**
5
** Portions taken verbatim or adapted from the Lua interpreter.
6
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
7
*/
8
9
#define lj_meta_c
10
#define LUA_CORE
11
12
#include "lj_obj.h"
13
#include "lj_gc.h"
14
#include "lj_err.h"
15
#include "lj_buf.h"
16
#include "lj_str.h"
17
#include "lj_tab.h"
18
#include "lj_meta.h"
19
#include "lj_frame.h"
20
#include "lj_bc.h"
21
#include "lj_vm.h"
22
#include "lj_strscan.h"
23
#include "lj_strfmt.h"
24
#include "lj_lib.h"
25
26
/* -- Metamethod handling ------------------------------------------------- */
27
28
/* String interning of metamethod names for fast indexing. */
29
void lj_meta_init(lua_State *L)
30
4.20k
{
31
8.41k
#define MMNAME(name)  "__" #name
32
8.41k
  const char *metanames = MMDEF(MMNAME);
33
4.20k
#undef MMNAME
34
4.20k
  global_State *g = G(L);
35
4.20k
  const char *p, *q;
36
4.20k
  uint32_t mm;
37
96.8k
  for (mm = 0, p = metanames; *p; mm++, p = q) {
38
92.5k
    GCstr *s;
39
471k
    for (q = p+2; *q && *q != '_'; q++) ;
40
92.5k
    s = lj_str_new(L, p, (size_t)(q-p));
41
    /* NOBARRIER: g->gcroot[] is a GC root. */
42
92.5k
    setgcref(g->gcroot[GCROOT_MMNAME+mm], obj2gco(s));
43
92.5k
  }
44
4.20k
}
45
46
/* Negative caching of a few fast metamethods. See the lj_meta_fast() macro. */
47
cTValue *lj_meta_cache(GCtab *mt, MMS mm, GCstr *name)
48
145k
{
49
145k
  cTValue *mo = lj_tab_getstr(mt, name);
50
145k
  lj_assertX(mm <= MM_FAST, "bad metamethod %d", mm);
51
145k
  if (!mo || tvisnil(mo)) {  /* No metamethod? */
52
1.57k
    mt->nomm |= (uint8_t)(1u<<mm);  /* Set negative cache flag. */
53
1.57k
    return NULL;
54
1.57k
  }
55
143k
  return mo;
56
145k
}
57
58
/* Lookup metamethod for object. */
59
cTValue *lj_meta_lookup(lua_State *L, cTValue *o, MMS mm)
60
1.30M
{
61
1.30M
  GCtab *mt;
62
1.30M
  if (tvistab(o))
63
568k
    mt = tabref(tabV(o)->metatable);
64
733k
  else if (tvisudata(o))
65
0
    mt = tabref(udataV(o)->metatable);
66
733k
  else
67
733k
    mt = tabref(basemt_obj(G(L), o));
68
1.30M
  if (mt) {
69
1.30M
    cTValue *mo = lj_tab_getstr(mt, mmname_str(G(L), mm));
70
1.30M
    if (mo)
71
1.15M
      return mo;
72
1.30M
  }
73
145k
  return niltv(L);
74
145k
}
75
76
#if LJ_HASFFI
77
/* Tailcall from C function. */
78
int lj_meta_tailcall(lua_State *L, cTValue *tv)
79
0
{
80
0
  TValue *base = L->base;
81
0
  TValue *top = L->top;
82
0
  const BCIns *pc = frame_pc(base-1);  /* Preserve old PC from frame. */
83
0
  copyTV(L, base-1-LJ_FR2, tv);  /* Replace frame with new object. */
84
0
  if (LJ_FR2)
85
0
    (top++)->u64 = LJ_CONT_TAILCALL;
86
0
  else
87
0
    top->u32.lo = LJ_CONT_TAILCALL;
88
0
  setframe_pc(top++, pc);
89
0
  setframe_gc(top, obj2gco(L), LJ_TTHREAD);  /* Dummy frame object. */
90
0
  if (LJ_FR2) top++;
91
0
  setframe_ftsz(top, ((char *)(top+1) - (char *)base) + FRAME_CONT);
92
0
  L->base = L->top = top+1;
93
  /*
94
  ** before:   [old_mo|PC]    [... ...]
95
  **                         ^base     ^top
96
  ** after:    [new_mo|itype] [... ...] [NULL|PC] [dummy|delta]
97
  **                                                           ^base/top
98
  ** tailcall: [new_mo|PC]    [... ...]
99
  **                         ^base     ^top
100
  */
101
0
  return 0;
102
0
}
103
#endif
104
105
/* Setup call to metamethod to be run by Assembler VM. */
106
static TValue *mmcall(lua_State *L, ASMFunction cont, cTValue *mo,
107
        cTValue *a, cTValue *b)
108
395k
{
109
  /*
110
  **           |-- framesize -> top       top+1       top+2 top+3
111
  ** before:   [func slots ...]
112
  ** mm setup: [func slots ...] [cont|?]  [mo|tmtype] [a]   [b]
113
  ** in asm:   [func slots ...] [cont|PC] [mo|delta]  [a]   [b]
114
  **           ^-- func base                          ^-- mm base
115
  ** after mm: [func slots ...]           [result]
116
  **                ^-- copy to base[PC_RA] --/     for lj_cont_ra
117
  **                          istruecond + branch   for lj_cont_cond*
118
  **                                       ignore   for lj_cont_nop
119
  ** next PC:  [func slots ...]
120
  */
121
395k
  TValue *top = L->top;
122
395k
  if (curr_funcisL(L)) top = curr_topL(L);
123
395k
  setcont(top++, cont);  /* Assembler VM stores PC in upper word or FR2. */
124
395k
  if (LJ_FR2) setnilV(top++);
125
395k
  copyTV(L, top++, mo);  /* Store metamethod and two arguments. */
126
395k
  if (LJ_FR2) setnilV(top++);
127
395k
  copyTV(L, top, a);
128
395k
  copyTV(L, top+1, b);
129
395k
  return top;  /* Return new base. */
130
395k
}
131
132
/* -- C helpers for some instructions, called from assembler VM ----------- */
133
134
/* Helper for TGET*. __index chain and metamethod. */
135
cTValue *lj_meta_tget(lua_State *L, cTValue *o, cTValue *k)
136
144k
{
137
144k
  int loop;
138
144k
  for (loop = 0; loop < LJ_MAX_IDXCHAIN; loop++) {
139
144k
    cTValue *mo;
140
144k
    if (LJ_LIKELY(tvistab(o))) {
141
75.1k
      GCtab *t = tabV(o);
142
0
      cTValue *tv = lj_tab_get(L, t, k);
143
75.1k
      if (!tvisnil(tv) ||
144
75.1k
    !(mo = lj_meta_fast(L, tabref(t->metatable), MM_index)))
145
75.1k
  return tv;
146
75.1k
    } else if (tvisnil(mo = lj_meta_lookup(L, o, MM_index))) {
147
0
      lj_err_optype(L, o, LJ_ERR_OPINDEX);
148
0
      return NULL;  /* unreachable */
149
0
    }
150
68.9k
    if (tvisfunc(mo)) {
151
68.9k
      L->top = mmcall(L, lj_cont_ra, mo, o, k);
152
68.9k
      return NULL;  /* Trigger metamethod call. */
153
68.9k
    }
154
0
    o = mo;
155
0
  }
156
0
  lj_err_msg(L, LJ_ERR_GETLOOP);
157
0
  return NULL;  /* unreachable */
158
144k
}
159
160
/* Helper for TSET*. __newindex chain and metamethod. */
161
TValue *lj_meta_tset(lua_State *L, cTValue *o, cTValue *k)
162
544k
{
163
544k
  TValue tmp;
164
544k
  int loop;
165
544k
  for (loop = 0; loop < LJ_MAX_IDXCHAIN; loop++) {
166
544k
    cTValue *mo;
167
544k
    if (LJ_LIKELY(tvistab(o))) {
168
460k
      GCtab *t = tabV(o);
169
0
      cTValue *tv = lj_tab_get(L, t, k);
170
460k
      if (LJ_LIKELY(!tvisnil(tv))) {
171
7.40k
  t->nomm = 0;  /* Invalidate negative metamethod cache. */
172
7.40k
  lj_gc_anybarriert(L, t);
173
7.40k
  return (TValue *)tv;
174
453k
      } else if (!(mo = lj_meta_fast(L, tabref(t->metatable), MM_newindex))) {
175
367k
  t->nomm = 0;  /* Invalidate negative metamethod cache. */
176
367k
  lj_gc_anybarriert(L, t);
177
367k
  if (tv != niltv(L))
178
1.10k
    return (TValue *)tv;
179
365k
  if (tvisnil(k)) lj_err_msg(L, LJ_ERR_NILIDX);
180
365k
  else if (tvisint(k)) { setnumV(&tmp, (lua_Number)intV(k)); k = &tmp; }
181
365k
  else if (tvisnum(k) && tvisnan(k)) lj_err_msg(L, LJ_ERR_NANIDX);
182
365k
  return lj_tab_newkey(L, t, k);
183
365k
      }
184
460k
    } else if (tvisnil(mo = lj_meta_lookup(L, o, MM_newindex))) {
185
0
      lj_err_optype(L, o, LJ_ERR_OPINDEX);
186
0
      return NULL;  /* unreachable */
187
0
    }
188
170k
    if (tvisfunc(mo)) {
189
170k
      L->top = mmcall(L, lj_cont_nop, mo, o, k);
190
      /* L->top+2 = v filled in by caller. */
191
170k
      return NULL;  /* Trigger metamethod call. */
192
170k
    }
193
0
    copyTV(L, &tmp, mo);
194
0
    o = &tmp;
195
0
  }
196
0
  lj_err_msg(L, LJ_ERR_SETLOOP);
197
0
  return NULL;  /* unreachable */
198
544k
}
199
200
static cTValue *str2num(cTValue *o, TValue *n)
201
254k
{
202
254k
  if (tvisnum(o))
203
81.6k
    return o;
204
172k
  else if (tvisint(o))
205
0
    return (setnumV(n, (lua_Number)intV(o)), n);
206
172k
  else if (tvisstr(o) && lj_strscan_num(strV(o), n))
207
25.1k
    return n;
208
147k
  else
209
147k
    return NULL;
210
254k
}
211
212
/* Helper for arithmetic instructions. Coercion, metamethod. */
213
TValue *lj_meta_arith(lua_State *L, TValue *ra, cTValue *rb, cTValue *rc,
214
          BCReg op)
215
156k
{
216
156k
  MMS mm = bcmode_mm(op);
217
156k
  TValue tempb, tempc;
218
156k
  cTValue *b, *c;
219
156k
  if ((b = str2num(rb, &tempb)) != NULL &&
220
156k
      (c = str2num(rc, &tempc)) != NULL) {  /* Try coercion first. */
221
8.80k
    setnumV(ra, lj_vm_foldarith(numV(b), numV(c), (int)mm-MM_add));
222
0
    return NULL;
223
147k
  } else {
224
147k
    cTValue *mo = lj_meta_lookup(L, rb, mm);
225
147k
    if (tvisnil(mo)) {
226
19.2k
      mo = lj_meta_lookup(L, rc, mm);
227
19.2k
      if (tvisnil(mo)) {
228
3
  if (str2num(rb, &tempb) == NULL) rc = rb;
229
3
  lj_err_optype(L, rc, LJ_ERR_OPARITH);
230
0
  return NULL;  /* unreachable */
231
3
      }
232
19.2k
    }
233
147k
    return mmcall(L, lj_cont_ra, mo, rb, rc);
234
147k
  }
235
156k
}
236
237
/* Helper for CAT. Coercion, iterative concat, __concat metamethod. */
238
TValue *lj_meta_cat(lua_State *L, TValue *top, int left)
239
125k
{
240
125k
  int fromc = 0;
241
125k
  if (left < 0) { left = -left; fromc = 1; }
242
127k
  do {
243
127k
    if (!(tvisstr(top) || tvisnumber(top)) ||
244
127k
  !(tvisstr(top-1) || tvisnumber(top-1))) {
245
49.4k
      cTValue *mo = lj_meta_lookup(L, top-1, MM_concat);
246
49.4k
      if (tvisnil(mo)) {
247
4.54k
  mo = lj_meta_lookup(L, top, MM_concat);
248
4.54k
  if (tvisnil(mo)) {
249
13
    if (tvisstr(top-1) || tvisnumber(top-1)) top++;
250
13
    lj_err_optype(L, top-1, LJ_ERR_OPCAT);
251
0
    return NULL;  /* unreachable */
252
13
  }
253
4.54k
      }
254
      /* One of the top two elements is not a string, call __cat metamethod:
255
      **
256
      ** before:    [...][CAT stack .........................]
257
      **                                 top-1     top         top+1 top+2
258
      ** pick two:  [...][CAT stack ...] [o1]      [o2]
259
      ** setup mm:  [...][CAT stack ...] [cont|?]  [mo|tmtype] [o1]  [o2]
260
      ** in asm:    [...][CAT stack ...] [cont|PC] [mo|delta]  [o1]  [o2]
261
      **            ^-- func base                              ^-- mm base
262
      ** after mm:  [...][CAT stack ...] <--push-- [result]
263
      ** next step: [...][CAT stack .............]
264
      */
265
49.4k
      copyTV(L, top+2*LJ_FR2+2, top);  /* Carefully ordered stack copies! */
266
49.4k
      copyTV(L, top+2*LJ_FR2+1, top-1);
267
49.4k
      copyTV(L, top+LJ_FR2, mo);
268
49.4k
      setcont(top-1, lj_cont_cat);
269
49.4k
      if (LJ_FR2) { setnilV(top); setnilV(top+2); top += 2; }
270
49.4k
      return top+1;  /* Trigger metamethod call. */
271
78.4k
    } else {
272
      /* Pick as many strings as possible from the top and concatenate them:
273
      **
274
      ** before:    [...][CAT stack ...........................]
275
      ** pick str:  [...][CAT stack ...] [...... strings ......]
276
      ** concat:    [...][CAT stack ...] [result]
277
      ** next step: [...][CAT stack ............]
278
      */
279
78.4k
      TValue *e, *o = top;
280
137k
      uint64_t tlen = tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM;
281
78.4k
      SBuf *sb;
282
90.8k
      do {
283
152k
  o--; tlen += tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM;
284
90.8k
      } while (--left > 0 && (tvisstr(o-1) || tvisnumber(o-1)));
285
78.4k
      if (tlen >= LJ_MAX_STR) lj_err_msg(L, LJ_ERR_STROV);
286
78.4k
      sb = lj_buf_tmp_(L);
287
78.4k
      lj_buf_more(sb, (MSize)tlen);
288
247k
      for (e = top, top = o; o <= e; o++) {
289
169k
  if (tvisstr(o)) {
290
144k
    GCstr *s = strV(o);
291
0
    MSize len = s->len;
292
144k
    lj_buf_putmem(sb, strdata(s), len);
293
144k
  } else if (tvisint(o)) {
294
0
    lj_strfmt_putint(sb, intV(o));
295
24.5k
  } else {
296
24.5k
    lj_strfmt_putfnum(sb, STRFMT_G14, numV(o));
297
24.5k
  }
298
169k
      }
299
78.4k
      setstrV(L, top, lj_buf_str(L, sb));
300
78.4k
    }
301
127k
  } while (left >= 1);
302
75.6k
  if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) {
303
18.3k
    if (!fromc) L->top = curr_topL(L);
304
18.3k
    lj_gc_step(L);
305
18.3k
  }
306
75.6k
  return NULL;
307
75.6k
}
308
309
/* Helper for LEN. __len metamethod. */
310
TValue * LJ_FASTCALL lj_meta_len(lua_State *L, cTValue *o)
311
7.69k
{
312
7.69k
  cTValue *mo = lj_meta_lookup(L, o, MM_len);
313
7.69k
  if (tvisnil(mo)) {
314
0
    if (LJ_52 && tvistab(o))
315
0
      tabref(tabV(o)->metatable)->nomm |= (uint8_t)(1u<<MM_len);
316
0
    else
317
0
      lj_err_optype(L, o, LJ_ERR_OPLEN);
318
0
    return NULL;
319
0
  }
320
7.69k
  return mmcall(L, lj_cont_ra, mo, o, LJ_52 ? o : niltv(L));
321
7.69k
}
322
323
/* Helper for equality comparisons. __eq metamethod. */
324
TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne)
325
62
{
326
  /* Field metatable must be at same offset for GCtab and GCudata! */
327
62
  cTValue *mo = lj_meta_fast(L, tabref(o1->gch.metatable), MM_eq);
328
62
  if (mo) {
329
0
    TValue *top;
330
0
    uint32_t it;
331
0
    if (tabref(o1->gch.metatable) != tabref(o2->gch.metatable)) {
332
0
      cTValue *mo2 = lj_meta_fast(L, tabref(o2->gch.metatable), MM_eq);
333
0
      if (mo2 == NULL || !lj_obj_equal(mo, mo2))
334
0
  return (TValue *)(intptr_t)ne;
335
0
    }
336
0
    top = curr_top(L);
337
0
    setcont(top++, ne ? lj_cont_condf : lj_cont_condt);
338
0
    if (LJ_FR2) setnilV(top++);
339
0
    copyTV(L, top++, mo);
340
0
    if (LJ_FR2) setnilV(top++);
341
0
    it = ~(uint32_t)o1->gch.gct;
342
0
    setgcV(L, top, o1, it);
343
0
    setgcV(L, top+1, o2, it);
344
0
    return top;  /* Trigger metamethod call. */
345
0
  }
346
62
  return (TValue *)(intptr_t)ne;
347
62
}
348
349
#if LJ_HASFFI
350
TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins)
351
0
{
352
0
  ASMFunction cont = (bc_op(ins) & 1) ? lj_cont_condf : lj_cont_condt;
353
0
  int op = (int)bc_op(ins) & ~1;
354
0
  TValue tv;
355
0
  cTValue *mo, *o2, *o1 = &L->base[bc_a(ins)];
356
0
  cTValue *o1mm = o1;
357
0
  if (op == BC_ISEQV) {
358
0
    o2 = &L->base[bc_d(ins)];
359
0
    if (!tviscdata(o1mm)) o1mm = o2;
360
0
  } else if (op == BC_ISEQS) {
361
0
    setstrV(L, &tv, gco2str(proto_kgc(curr_proto(L), ~(ptrdiff_t)bc_d(ins))));
362
0
    o2 = &tv;
363
0
  } else if (op == BC_ISEQN) {
364
0
    o2 = &mref(curr_proto(L)->k, cTValue)[bc_d(ins)];
365
0
  } else {
366
0
    lj_assertL(op == BC_ISEQP, "bad bytecode op %d", op);
367
0
    setpriV(&tv, ~bc_d(ins));
368
0
    o2 = &tv;
369
0
  }
370
0
  mo = lj_meta_lookup(L, o1mm, MM_eq);
371
0
  if (LJ_LIKELY(!tvisnil(mo)))
372
0
    return mmcall(L, cont, mo, o1, o2);
373
0
  else
374
0
    return (TValue *)(intptr_t)(bc_op(ins) & 1);
375
0
}
376
#endif
377
378
/* Helper for ordered comparisons. String compare, __lt/__le metamethods. */
379
TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op)
380
3.15k
{
381
3.15k
  if (LJ_HASFFI && (tviscdata(o1) || tviscdata(o2))) {
382
0
    ASMFunction cont = (op & 1) ? lj_cont_condf : lj_cont_condt;
383
0
    MMS mm = (op & 2) ? MM_le : MM_lt;
384
0
    cTValue *mo = lj_meta_lookup(L, tviscdata(o1) ? o1 : o2, mm);
385
0
    if (LJ_UNLIKELY(tvisnil(mo))) goto err;
386
0
    return mmcall(L, cont, mo, o1, o2);
387
3.15k
  } else if (LJ_52 || itype(o1) == itype(o2)) {
388
    /* Never called with two numbers. */
389
3.13k
    if (tvisstr(o1) && tvisstr(o2)) {
390
2.21k
      int32_t res = lj_str_cmp(strV(o1), strV(o2));
391
2.21k
      return (TValue *)(intptr_t)(((op&2) ? res <= 0 : res < 0) ^ (op&1));
392
2.21k
    } else {
393
917
    trymt:
394
917
      while (1) {
395
917
  ASMFunction cont = (op & 1) ? lj_cont_condf : lj_cont_condt;
396
917
  MMS mm = (op & 2) ? MM_le : MM_lt;
397
917
  cTValue *mo = lj_meta_lookup(L, o1, mm);
398
#if LJ_52
399
  if (tvisnil(mo) && tvisnil((mo = lj_meta_lookup(L, o2, mm))))
400
#else
401
917
  cTValue *mo2 = lj_meta_lookup(L, o2, mm);
402
917
  if (tvisnil(mo) || !lj_obj_equal(mo, mo2))
403
0
#endif
404
0
  {
405
0
    if (op & 2) {  /* MM_le not found: retry with MM_lt. */
406
0
      cTValue *ot = o1; o1 = o2; o2 = ot;  /* Swap operands. */
407
0
      op ^= 3;  /* Use LT and flip condition. */
408
0
      continue;
409
0
    }
410
0
    goto err;
411
0
  }
412
917
  return mmcall(L, cont, mo, o1, o2);
413
917
      }
414
917
    }
415
3.13k
  } else if (tvisbool(o1) && tvisbool(o2)) {
416
0
    goto trymt;
417
18
  } else {
418
18
  err:
419
18
    lj_err_comp(L, o1, o2);
420
0
    return NULL;
421
18
  }
422
3.15k
}
423
424
/* Helper for ISTYPE and ISNUM. Implicit coercion or error. */
425
void lj_meta_istype(lua_State *L, BCReg ra, BCReg tp)
426
0
{
427
0
  L->top = curr_topL(L);
428
0
  ra++; tp--;
429
0
  lj_assertL(LJ_DUALNUM || tp != ~LJ_TNUMX, "bad type for ISTYPE");
430
0
  if (LJ_DUALNUM && tp == ~LJ_TNUMX) lj_lib_checkint(L, ra);
431
0
  else if (tp == ~LJ_TNUMX+1) lj_lib_checknum(L, ra);
432
0
  else if (tp == ~LJ_TSTR) lj_lib_checkstr(L, ra);
433
0
  else lj_err_argtype(L, ra, lj_obj_itypename[tp]);
434
0
}
435
436
/* Helper for calls. __call metamethod. */
437
void lj_meta_call(lua_State *L, TValue *func, TValue *top)
438
797k
{
439
797k
  cTValue *mo = lj_meta_lookup(L, func, MM_call);
440
797k
  TValue *p;
441
797k
  if (!tvisfunc(mo))
442
4
    lj_err_optype_call(L, func);
443
1.21M
  for (p = top; p > func+2*LJ_FR2; p--) copyTV(L, p, p-1);
444
797k
  if (LJ_FR2) copyTV(L, func+2, func);
445
797k
  copyTV(L, func, mo);
446
797k
}
447
448
/* Helper for FORI. Coercion. */
449
void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o)
450
60.7k
{
451
60.7k
  if (!lj_strscan_numberobj(o)) lj_err_msg(L, LJ_ERR_FORINIT);
452
60.7k
  if (!lj_strscan_numberobj(o+1)) lj_err_msg(L, LJ_ERR_FORLIM);
453
60.7k
  if (!lj_strscan_numberobj(o+2)) lj_err_msg(L, LJ_ERR_FORSTEP);
454
60.7k
  if (LJ_DUALNUM) {
455
    /* Ensure all slots are integers or all slots are numbers. */
456
0
    int32_t k[3];
457
0
    int nint = 0;
458
0
    ptrdiff_t i;
459
0
    for (i = 0; i <= 2; i++) {
460
0
      if (tvisint(o+i)) {
461
0
  k[i] = intV(o+i); nint++;
462
0
      } else {
463
0
  k[i] = lj_num2int(numV(o+i)); nint += ((lua_Number)k[i] == numV(o+i));
464
0
      }
465
0
    }
466
0
    if (nint == 3) {  /* Narrow to integers. */
467
0
      setintV(o, k[0]);
468
0
      setintV(o+1, k[1]);
469
0
      setintV(o+2, k[2]);
470
0
    } else if (nint != 0) {  /* Widen to numbers. */
471
0
      if (tvisint(o)) setnumV(o, (lua_Number)intV(o));
472
0
      if (tvisint(o+1)) setnumV(o+1, (lua_Number)intV(o+1));
473
0
      if (tvisint(o+2)) setnumV(o+2, (lua_Number)intV(o+2));
474
0
    }
475
0
  }
476
60.7k
}
477