diff options
Diffstat (limited to 'src/lib_jit.c')
-rw-r--r-- | src/lib_jit.c | 589 |
1 files changed, 589 insertions, 0 deletions
diff --git a/src/lib_jit.c b/src/lib_jit.c new file mode 100644 index 00000000..4a57f3b4 --- /dev/null +++ b/src/lib_jit.c | |||
@@ -0,0 +1,589 @@ | |||
1 | /* | ||
2 | ** JIT library. | ||
3 | ** Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h | ||
4 | */ | ||
5 | |||
6 | #define lib_jit_c | ||
7 | #define LUA_LIB | ||
8 | |||
9 | #include "lua.h" | ||
10 | #include "lauxlib.h" | ||
11 | #include "lualib.h" | ||
12 | |||
13 | #include "lj_arch.h" | ||
14 | #include "lj_obj.h" | ||
15 | #include "lj_err.h" | ||
16 | #include "lj_str.h" | ||
17 | #include "lj_tab.h" | ||
18 | #if LJ_HASJIT | ||
19 | #include "lj_ir.h" | ||
20 | #include "lj_jit.h" | ||
21 | #include "lj_iropt.h" | ||
22 | #endif | ||
23 | #include "lj_dispatch.h" | ||
24 | #include "lj_vm.h" | ||
25 | #include "lj_vmevent.h" | ||
26 | #include "lj_lib.h" | ||
27 | |||
28 | #include "luajit.h" | ||
29 | |||
30 | /* -- jit.* functions ----------------------------------------------------- */ | ||
31 | |||
32 | #define LJLIB_MODULE_jit | ||
33 | |||
34 | static int setjitmode(lua_State *L, int mode) | ||
35 | { | ||
36 | int idx = 0; | ||
37 | if (L->base == L->top || tvisnil(L->base)) { /* jit.on/off/flush([nil]) */ | ||
38 | mode |= LUAJIT_MODE_ENGINE; | ||
39 | } else { | ||
40 | /* jit.on/off/flush(func|proto, nil|true|false) */ | ||
41 | if (tvisfunc(L->base) || tvisproto(L->base)) | ||
42 | idx = 1; | ||
43 | else if (!tvistrue(L->base)) /* jit.on/off/flush(true, nil|true|false) */ | ||
44 | goto err; | ||
45 | if (L->base+1 < L->top && tvisbool(L->base+1)) | ||
46 | mode |= boolV(L->base+1) ? LUAJIT_MODE_ALLFUNC : LUAJIT_MODE_ALLSUBFUNC; | ||
47 | else | ||
48 | mode |= LUAJIT_MODE_FUNC; | ||
49 | } | ||
50 | if (luaJIT_setmode(L, idx, mode) != 1) { | ||
51 | err: | ||
52 | #if LJ_HASJIT | ||
53 | lj_err_arg(L, 1, LJ_ERR_NOLFUNC); | ||
54 | #else | ||
55 | lj_err_caller(L, LJ_ERR_NOJIT); | ||
56 | #endif | ||
57 | } | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | LJLIB_CF(jit_on) | ||
62 | { | ||
63 | return setjitmode(L, LUAJIT_MODE_ON); | ||
64 | } | ||
65 | |||
66 | LJLIB_CF(jit_off) | ||
67 | { | ||
68 | return setjitmode(L, LUAJIT_MODE_OFF); | ||
69 | } | ||
70 | |||
71 | LJLIB_CF(jit_flush) | ||
72 | { | ||
73 | #if LJ_HASJIT | ||
74 | if (L->base < L->top && (tvisnum(L->base) || tvisstr(L->base))) { | ||
75 | int traceno = lj_lib_checkint(L, 1); | ||
76 | luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE); | ||
77 | return 0; | ||
78 | } | ||
79 | #endif | ||
80 | return setjitmode(L, LUAJIT_MODE_FLUSH); | ||
81 | } | ||
82 | |||
83 | #if LJ_HASJIT | ||
84 | /* Push a string for every flag bit that is set. */ | ||
85 | static void flagbits_to_strings(lua_State *L, uint32_t flags, uint32_t base, | ||
86 | const char *str) | ||
87 | { | ||
88 | for (; *str; base <<= 1, str += 1+*str) | ||
89 | if (flags & base) | ||
90 | setstrV(L, L->top++, lj_str_new(L, str+1, *(uint8_t *)str)); | ||
91 | } | ||
92 | #endif | ||
93 | |||
94 | LJLIB_CF(jit_status) | ||
95 | { | ||
96 | #if LJ_HASJIT | ||
97 | jit_State *J = L2J(L); | ||
98 | L->top = L->base; | ||
99 | setboolV(L->top++, (J->flags & JIT_F_ON) ? 1 : 0); | ||
100 | flagbits_to_strings(L, J->flags, JIT_F_CPU_FIRST, JIT_F_CPUSTRING); | ||
101 | flagbits_to_strings(L, J->flags, JIT_F_OPT_FIRST, JIT_F_OPTSTRING); | ||
102 | return L->top - L->base; | ||
103 | #else | ||
104 | setboolV(L->top++, 0); | ||
105 | return 1; | ||
106 | #endif | ||
107 | } | ||
108 | |||
109 | LJLIB_CF(jit_attach) | ||
110 | { | ||
111 | #ifdef LUAJIT_DISABLE_VMEVENT | ||
112 | luaL_error(L, "vmevent API disabled"); | ||
113 | #else | ||
114 | GCfunc *fn = lj_lib_checkfunc(L, 1); | ||
115 | GCstr *s = lj_lib_optstr(L, 2); | ||
116 | luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE); | ||
117 | if (s) { /* Attach to given event. */ | ||
118 | lua_pushvalue(L, 1); | ||
119 | lua_rawseti(L, -2, VMEVENT_HASHIDX(s->hash)); | ||
120 | G(L)->vmevmask = VMEVENT_NOCACHE; /* Invalidate cache. */ | ||
121 | } else { /* Detach if no event given. */ | ||
122 | setnilV(L->top++); | ||
123 | while (lua_next(L, -2)) { | ||
124 | L->top--; | ||
125 | if (tvisfunc(L->top) && funcV(L->top) == fn) { | ||
126 | setnilV(lj_tab_set(L, tabV(L->top-2), L->top-1)); | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | #endif | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | LJLIB_PUSH(top-4) LJLIB_SET(arch) | ||
135 | LJLIB_PUSH(top-3) LJLIB_SET(version_num) | ||
136 | LJLIB_PUSH(top-2) LJLIB_SET(version) | ||
137 | |||
138 | #include "lj_libdef.h" | ||
139 | |||
140 | /* -- jit.util.* functions ------------------------------------------------ */ | ||
141 | |||
142 | #define LJLIB_MODULE_jit_util | ||
143 | |||
144 | /* -- Reflection API for Lua functions ------------------------------------ */ | ||
145 | |||
146 | /* Return prototype of first argument (Lua function or prototype object) */ | ||
147 | static GCproto *check_Lproto(lua_State *L, int nolua) | ||
148 | { | ||
149 | TValue *o = L->base; | ||
150 | if (L->top > o) { | ||
151 | if (tvisproto(o)) { | ||
152 | return protoV(o); | ||
153 | } else if (tvisfunc(o)) { | ||
154 | if (isluafunc(funcV(o))) | ||
155 | return funcproto(funcV(o)); | ||
156 | else if (nolua) | ||
157 | return NULL; | ||
158 | } | ||
159 | } | ||
160 | lj_err_argt(L, 1, LUA_TFUNCTION); | ||
161 | return NULL; /* unreachable */ | ||
162 | } | ||
163 | |||
164 | static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val) | ||
165 | { | ||
166 | setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val); | ||
167 | } | ||
168 | |||
169 | /* local info = jit.util.funcinfo(func [,pc]) */ | ||
170 | LJLIB_CF(jit_util_funcinfo) | ||
171 | { | ||
172 | GCproto *pt = check_Lproto(L, 1); | ||
173 | if (pt) { | ||
174 | BCPos pc = (BCPos)lj_lib_optint(L, 2, 0); | ||
175 | GCtab *t; | ||
176 | lua_createtable(L, 0, 16); /* Increment hash size if fields are added. */ | ||
177 | t = tabV(L->top-1); | ||
178 | setintfield(L, t, "linedefined", pt->linedefined); | ||
179 | setintfield(L, t, "lastlinedefined", pt->lastlinedefined); | ||
180 | setintfield(L, t, "stackslots", pt->framesize); | ||
181 | setintfield(L, t, "params", pt->numparams); | ||
182 | setintfield(L, t, "bytecodes", (int32_t)pt->sizebc); | ||
183 | setintfield(L, t, "gcconsts", (int32_t)pt->sizekgc); | ||
184 | setintfield(L, t, "nconsts", (int32_t)pt->sizekn); | ||
185 | setintfield(L, t, "upvalues", (int32_t)pt->sizeuv); | ||
186 | if (pc > 0) | ||
187 | setintfield(L, t, "currentline", pt->lineinfo ? pt->lineinfo[pc-1] : 0); | ||
188 | lua_pushboolean(L, (pt->flags & PROTO_IS_VARARG)); | ||
189 | lua_setfield(L, -2, "isvararg"); | ||
190 | setstrV(L, L->top++, pt->chunkname); | ||
191 | lua_setfield(L, -2, "source"); | ||
192 | lj_err_pushloc(L, pt, pc); | ||
193 | lua_setfield(L, -2, "loc"); | ||
194 | } else { | ||
195 | GCfunc *fn = funcV(L->base); | ||
196 | GCtab *t; | ||
197 | lua_createtable(L, 0, 2); /* Increment hash size if fields are added. */ | ||
198 | t = tabV(L->top-1); | ||
199 | setintfield(L, t, "ffid", fn->c.ffid); | ||
200 | setintfield(L, t, "upvalues", fn->c.nupvalues); | ||
201 | } | ||
202 | return 1; | ||
203 | } | ||
204 | |||
205 | /* local ins, m = jit.util.funcbc(func, pc) */ | ||
206 | LJLIB_CF(jit_util_funcbc) | ||
207 | { | ||
208 | GCproto *pt = check_Lproto(L, 0); | ||
209 | BCPos pc = (BCPos)lj_lib_checkint(L, 2) - 1; | ||
210 | if (pc < pt->sizebc) { | ||
211 | BCIns ins = pt->bc[pc]; | ||
212 | BCOp op = bc_op(ins); | ||
213 | lua_assert(op < BC__MAX); | ||
214 | setintV(L->top, ins); | ||
215 | setintV(L->top+1, lj_bc_mode[op]); | ||
216 | L->top += 2; | ||
217 | return 2; | ||
218 | } | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* local k = jit.util.funck(func, idx) */ | ||
223 | LJLIB_CF(jit_util_funck) | ||
224 | { | ||
225 | GCproto *pt = check_Lproto(L, 0); | ||
226 | MSize idx = (MSize)lj_lib_checkint(L, 2); | ||
227 | if ((int32_t)idx >= 0) { | ||
228 | if (idx < pt->sizekn) { | ||
229 | setnumV(L->top-1, pt->k.n[idx]); | ||
230 | return 1; | ||
231 | } | ||
232 | } else { | ||
233 | if (~idx < pt->sizekgc) { | ||
234 | GCobj *gc = gcref(pt->k.gc[idx]); | ||
235 | setgcV(L, L->top-1, &gc->gch, ~gc->gch.gct); | ||
236 | return 1; | ||
237 | } | ||
238 | } | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | /* local name = jit.util.funcuvname(func, idx) */ | ||
243 | LJLIB_CF(jit_util_funcuvname) | ||
244 | { | ||
245 | GCproto *pt = check_Lproto(L, 0); | ||
246 | uint32_t idx = (uint32_t)lj_lib_checkint(L, 2); | ||
247 | if (idx < pt->sizeuvname) { | ||
248 | setstrV(L, L->top-1, pt->uvname[idx]); | ||
249 | return 1; | ||
250 | } | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | /* -- Reflection API for traces ------------------------------------------- */ | ||
255 | |||
256 | #if LJ_HASJIT | ||
257 | |||
258 | /* Check trace argument. Must not throw for non-existent trace numbers. */ | ||
259 | static Trace *jit_checktrace(lua_State *L) | ||
260 | { | ||
261 | TraceNo tr = (TraceNo)lj_lib_checkint(L, 1); | ||
262 | jit_State *J = L2J(L); | ||
263 | if (tr > 0 && tr < J->sizetrace) | ||
264 | return J->trace[tr]; | ||
265 | return NULL; | ||
266 | } | ||
267 | |||
268 | /* local info = jit.util.traceinfo(tr) */ | ||
269 | LJLIB_CF(jit_util_traceinfo) | ||
270 | { | ||
271 | Trace *T = jit_checktrace(L); | ||
272 | if (T) { | ||
273 | GCtab *t; | ||
274 | lua_createtable(L, 0, 4); /* Increment hash size if fields are added. */ | ||
275 | t = tabV(L->top-1); | ||
276 | setintfield(L, t, "nins", (int32_t)T->nins - REF_BIAS - 1); | ||
277 | setintfield(L, t, "nk", REF_BIAS - (int32_t)T->nk); | ||
278 | setintfield(L, t, "link", T->link); | ||
279 | setintfield(L, t, "nexit", T->nsnap); | ||
280 | /* There are many more fields. Add them only when needed. */ | ||
281 | return 1; | ||
282 | } | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | /* local m, ot, op1, op2, prev = jit.util.traceir(tr, idx) */ | ||
287 | LJLIB_CF(jit_util_traceir) | ||
288 | { | ||
289 | Trace *T = jit_checktrace(L); | ||
290 | IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS; | ||
291 | if (T && ref >= REF_BIAS && ref < T->nins) { | ||
292 | IRIns *ir = &T->ir[ref]; | ||
293 | int32_t m = lj_ir_mode[ir->o]; | ||
294 | setintV(L->top-2, m); | ||
295 | setintV(L->top-1, ir->ot); | ||
296 | setintV(L->top++, (int32_t)ir->op1 - (irm_op1(m)==IRMref ? REF_BIAS : 0)); | ||
297 | setintV(L->top++, (int32_t)ir->op2 - (irm_op2(m)==IRMref ? REF_BIAS : 0)); | ||
298 | setintV(L->top++, ir->prev); | ||
299 | return 5; | ||
300 | } | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | /* local k, t [, slot] = jit.util.tracek(tr, idx) */ | ||
305 | LJLIB_CF(jit_util_tracek) | ||
306 | { | ||
307 | Trace *T = jit_checktrace(L); | ||
308 | IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS; | ||
309 | if (T && ref >= T->nk && ref < REF_BIAS) { | ||
310 | IRIns *ir = &T->ir[ref]; | ||
311 | int32_t slot = -1; | ||
312 | if (ir->o == IR_KSLOT) { | ||
313 | slot = ir->op2; | ||
314 | ir = &T->ir[ir->op1]; | ||
315 | } | ||
316 | lj_ir_kvalue(L, L->top-2, ir); | ||
317 | setintV(L->top-1, (int32_t)irt_type(ir->t)); | ||
318 | if (slot == -1) | ||
319 | return 2; | ||
320 | setintV(L->top++, slot); | ||
321 | return 3; | ||
322 | } | ||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | /* local snap = jit.util.tracesnap(tr, sn) */ | ||
327 | LJLIB_CF(jit_util_tracesnap) | ||
328 | { | ||
329 | Trace *T = jit_checktrace(L); | ||
330 | SnapNo sn = (SnapNo)lj_lib_checkint(L, 2); | ||
331 | if (T && sn < T->nsnap) { | ||
332 | SnapShot *snap = &T->snap[sn]; | ||
333 | IRRef2 *map = &T->snapmap[snap->mapofs]; | ||
334 | BCReg s, nslots = snap->nslots; | ||
335 | GCtab *t; | ||
336 | lua_createtable(L, nslots ? (int)nslots : 1, 0); | ||
337 | t = tabV(L->top-1); | ||
338 | setintV(lj_tab_setint(L, t, 0), (int32_t)snap->ref - REF_BIAS); | ||
339 | for (s = 0; s < nslots; s++) { | ||
340 | TValue *o = lj_tab_setint(L, t, (int32_t)(s+1)); | ||
341 | IRRef ref = snap_ref(map[s]); | ||
342 | if (ref) | ||
343 | setintV(o, (int32_t)ref - REF_BIAS); | ||
344 | else | ||
345 | setboolV(o, 0); | ||
346 | } | ||
347 | return 1; | ||
348 | } | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | /* local mcode, addr, loop = jit.util.tracemc(tr) */ | ||
353 | LJLIB_CF(jit_util_tracemc) | ||
354 | { | ||
355 | Trace *T = jit_checktrace(L); | ||
356 | if (T && T->mcode != NULL) { | ||
357 | setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode)); | ||
358 | setnumV(L->top++, cast_num((intptr_t)T->mcode)); | ||
359 | setintV(L->top++, T->mcloop); | ||
360 | return 3; | ||
361 | } | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | /* local addr = jit.util.traceexitstub(idx) */ | ||
366 | LJLIB_CF(jit_util_traceexitstub) | ||
367 | { | ||
368 | ExitNo exitno = (ExitNo)lj_lib_checkint(L, 1); | ||
369 | jit_State *J = L2J(L); | ||
370 | if (exitno < EXITSTUBS_PER_GROUP*LJ_MAX_EXITSTUBGR) { | ||
371 | setnumV(L->top-1, cast_num((intptr_t)exitstub_addr(J, exitno))); | ||
372 | return 1; | ||
373 | } | ||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | #else | ||
378 | |||
379 | static int trace_nojit(lua_State *L) | ||
380 | { | ||
381 | UNUSED(L); | ||
382 | return 0; | ||
383 | } | ||
384 | #define lj_cf_jit_util_traceinfo trace_nojit | ||
385 | #define lj_cf_jit_util_traceir trace_nojit | ||
386 | #define lj_cf_jit_util_tracek trace_nojit | ||
387 | #define lj_cf_jit_util_tracesnap trace_nojit | ||
388 | #define lj_cf_jit_util_tracemc trace_nojit | ||
389 | #define lj_cf_jit_util_traceexitstub trace_nojit | ||
390 | |||
391 | #endif | ||
392 | |||
393 | #include "lj_libdef.h" | ||
394 | |||
395 | /* -- jit.opt module ------------------------------------------------------ */ | ||
396 | |||
397 | #define LJLIB_MODULE_jit_opt | ||
398 | |||
399 | #if LJ_HASJIT | ||
400 | /* Parse optimization level. */ | ||
401 | static int jitopt_level(jit_State *J, const char *str) | ||
402 | { | ||
403 | if (str[0] >= '0' && str[0] <= '9' && str[1] == '\0') { | ||
404 | uint32_t flags; | ||
405 | if (str[0] == '0') flags = JIT_F_OPT_0; | ||
406 | else if (str[0] == '1') flags = JIT_F_OPT_1; | ||
407 | else if (str[0] == '2') flags = JIT_F_OPT_2; | ||
408 | else flags = JIT_F_OPT_3; | ||
409 | J->flags = (J->flags & ~JIT_F_OPT_MASK) | flags; | ||
410 | return 1; /* Ok. */ | ||
411 | } | ||
412 | return 0; /* No match. */ | ||
413 | } | ||
414 | |||
415 | /* Parse optimization flag. */ | ||
416 | static int jitopt_flag(jit_State *J, const char *str) | ||
417 | { | ||
418 | const char *lst = JIT_F_OPTSTRING; | ||
419 | uint32_t opt; | ||
420 | int set = 1; | ||
421 | if (str[0] == '+') { | ||
422 | str++; | ||
423 | } else if (str[0] == '-') { | ||
424 | str++; | ||
425 | set = 0; | ||
426 | } else if (str[0] == 'n' && str[1] == 'o') { | ||
427 | str += str[2] == '-' ? 3 : 2; | ||
428 | set = 0; | ||
429 | } | ||
430 | for (opt = JIT_F_OPT_FIRST; ; opt <<= 1) { | ||
431 | size_t len = *(const uint8_t *)lst; | ||
432 | if (len == 0) | ||
433 | break; | ||
434 | if (strncmp(str, lst+1, len) == 0 && str[len] == '\0') { | ||
435 | if (set) J->flags |= opt; else J->flags &= ~opt; | ||
436 | return 1; /* Ok. */ | ||
437 | } | ||
438 | lst += 1+len; | ||
439 | } | ||
440 | return 0; /* No match. */ | ||
441 | } | ||
442 | |||
443 | /* Forward declaration. */ | ||
444 | static void jit_init_hotcount(jit_State *J); | ||
445 | |||
446 | /* Parse optimization parameter. */ | ||
447 | static int jitopt_param(jit_State *J, const char *str) | ||
448 | { | ||
449 | const char *lst = JIT_P_STRING; | ||
450 | int i; | ||
451 | for (i = 0; i < JIT_P__MAX; i++) { | ||
452 | size_t len = *(const uint8_t *)lst; | ||
453 | TValue tv; | ||
454 | lua_assert(len != 0); | ||
455 | if (strncmp(str, lst+1, len) == 0 && str[len] == '=' && | ||
456 | lj_str_numconv(&str[len+1], &tv)) { | ||
457 | J->param[i] = lj_num2int(tv.n); | ||
458 | if (i == JIT_P_hotloop) | ||
459 | jit_init_hotcount(J); | ||
460 | return 1; /* Ok. */ | ||
461 | } | ||
462 | lst += 1+len; | ||
463 | } | ||
464 | return 0; /* No match. */ | ||
465 | } | ||
466 | #endif | ||
467 | |||
468 | /* jit.opt.start(flags...) */ | ||
469 | LJLIB_CF(jit_opt_start) | ||
470 | { | ||
471 | #if LJ_HASJIT | ||
472 | jit_State *J = L2J(L); | ||
473 | int nargs = (int)(L->top - L->base); | ||
474 | if (nargs == 0) { | ||
475 | J->flags = (J->flags & ~JIT_F_OPT_MASK) | JIT_F_OPT_DEFAULT; | ||
476 | } else { | ||
477 | int i; | ||
478 | for (i = 1; i <= nargs; i++) { | ||
479 | const char *str = strdata(lj_lib_checkstr(L, i)); | ||
480 | if (!jitopt_level(J, str) && | ||
481 | !jitopt_flag(J, str) && | ||
482 | !jitopt_param(J, str)) | ||
483 | lj_err_callerv(L, LJ_ERR_JITOPT, str); | ||
484 | } | ||
485 | } | ||
486 | #else | ||
487 | lj_err_caller(L, LJ_ERR_NOJIT); | ||
488 | #endif | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | #include "lj_libdef.h" | ||
493 | |||
494 | /* -- JIT compiler initialization ----------------------------------------- */ | ||
495 | |||
496 | #if LJ_HASJIT | ||
497 | /* Default values for JIT parameters. */ | ||
498 | static const int32_t jit_param_default[JIT_P__MAX+1] = { | ||
499 | #define JIT_PARAMINIT(len, name, value) (value), | ||
500 | JIT_PARAMDEF(JIT_PARAMINIT) | ||
501 | #undef JIT_PARAMINIT | ||
502 | 0 | ||
503 | }; | ||
504 | |||
505 | /* Initialize hotcount table. */ | ||
506 | static void jit_init_hotcount(jit_State *J) | ||
507 | { | ||
508 | HotCount start = (HotCount)J->param[JIT_P_hotloop]; | ||
509 | HotCount *hotcount = J2GG(J)->hotcount; | ||
510 | uint32_t i; | ||
511 | for (i = 0; i < HOTCOUNT_SIZE; i++) | ||
512 | hotcount[i] = start; | ||
513 | } | ||
514 | #endif | ||
515 | |||
516 | /* Arch-dependent CPU detection. */ | ||
517 | static uint32_t jit_cpudetect(lua_State *L) | ||
518 | { | ||
519 | uint32_t flags = 0; | ||
520 | #if LJ_TARGET_X86ORX64 | ||
521 | uint32_t vendor[4]; | ||
522 | uint32_t features[4]; | ||
523 | if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) { | ||
524 | #if !LJ_HASJIT | ||
525 | #define JIT_F_CMOV 1 | ||
526 | #endif | ||
527 | flags |= ((features[3] >> 15)&1) * JIT_F_CMOV; | ||
528 | #if LJ_HASJIT | ||
529 | flags |= ((features[3] >> 26)&1) * JIT_F_SSE2; | ||
530 | flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1; | ||
531 | if (vendor[2] == 0x6c65746e) { /* Intel. */ | ||
532 | if ((features[0] & 0x0ff00f00) == 0x00000f00) /* P4. */ | ||
533 | flags |= JIT_F_P4; /* Currently unused. */ | ||
534 | else if ((features[0] & 0x0fff0ff0) == 0x000106c0) /* Atom. */ | ||
535 | flags |= JIT_F_LEA_AGU; | ||
536 | } else if (vendor[2] == 0x444d4163) { /* AMD. */ | ||
537 | uint32_t fam = (features[0] & 0x0ff00f00); | ||
538 | if (fam == 0x00000f00) /* K8. */ | ||
539 | flags |= JIT_F_SPLIT_XMM; | ||
540 | if (fam >= 0x00000f00) /* K8, K10. */ | ||
541 | flags |= JIT_F_PREFER_IMUL; | ||
542 | } | ||
543 | #endif | ||
544 | } | ||
545 | #ifndef LUAJIT_CPU_NOCMOV | ||
546 | if (!(flags & JIT_F_CMOV)) | ||
547 | luaL_error(L, "Ancient CPU lacks CMOV support (recompile with -DLUAJIT_CPU_NOCMOV)"); | ||
548 | #endif | ||
549 | #if LJ_HASJIT | ||
550 | if (!(flags & JIT_F_SSE2)) | ||
551 | luaL_error(L, "Sorry, SSE2 CPU support required for this beta release"); | ||
552 | #endif | ||
553 | UNUSED(L); | ||
554 | #else | ||
555 | #error "Missing CPU detection for this architecture" | ||
556 | #endif | ||
557 | return flags; | ||
558 | } | ||
559 | |||
560 | /* Initialize JIT compiler. */ | ||
561 | static void jit_init(lua_State *L) | ||
562 | { | ||
563 | uint32_t flags = jit_cpudetect(L); | ||
564 | #if LJ_HASJIT | ||
565 | jit_State *J = L2J(L); | ||
566 | J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT; | ||
567 | memcpy(J->param, jit_param_default, sizeof(J->param)); | ||
568 | jit_init_hotcount(J); | ||
569 | lj_dispatch_update(G(L)); | ||
570 | #else | ||
571 | UNUSED(flags); | ||
572 | #endif | ||
573 | } | ||
574 | |||
575 | LUALIB_API int luaopen_jit(lua_State *L) | ||
576 | { | ||
577 | lua_pushliteral(L, LJ_ARCH_NAME); | ||
578 | lua_pushinteger(L, LUAJIT_VERSION_NUM); | ||
579 | lua_pushliteral(L, LUAJIT_VERSION); | ||
580 | LJ_LIB_REG(L, jit); | ||
581 | #ifndef LUAJIT_DISABLE_JITUTIL | ||
582 | LJ_LIB_REG_(L, "jit.util", jit_util); | ||
583 | #endif | ||
584 | LJ_LIB_REG_(L, "jit.opt", jit_opt); | ||
585 | L->top -= 2; | ||
586 | jit_init(L); | ||
587 | return 1; | ||
588 | } | ||
589 | |||