diff options
Diffstat (limited to 'src/lj_parse.c')
-rw-r--r-- | src/lj_parse.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/src/lj_parse.c b/src/lj_parse.c index d93ed990..22241b24 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c | |||
@@ -17,6 +17,9 @@ | |||
17 | #include "lj_func.h" | 17 | #include "lj_func.h" |
18 | #include "lj_state.h" | 18 | #include "lj_state.h" |
19 | #include "lj_bc.h" | 19 | #include "lj_bc.h" |
20 | #if LJ_HASFFI | ||
21 | #include "lj_ctype.h" | ||
22 | #endif | ||
20 | #include "lj_lex.h" | 23 | #include "lj_lex.h" |
21 | #include "lj_parse.h" | 24 | #include "lj_parse.h" |
22 | #include "lj_vm.h" | 25 | #include "lj_vm.h" |
@@ -33,6 +36,7 @@ typedef enum { | |||
33 | VKSTR, /* sval = string value */ | 36 | VKSTR, /* sval = string value */ |
34 | VKNUM, /* nval = number value */ | 37 | VKNUM, /* nval = number value */ |
35 | VKLAST = VKNUM, | 38 | VKLAST = VKNUM, |
39 | VKCDATA, /* nval = cdata value, not treated as a constant expression */ | ||
36 | /* Non-constant expressions follow: */ | 40 | /* Non-constant expressions follow: */ |
37 | VLOCAL, /* info = local register */ | 41 | VLOCAL, /* info = local register */ |
38 | VUPVAL, /* info = upvalue index */ | 42 | VUPVAL, /* info = upvalue index */ |
@@ -61,7 +65,7 @@ typedef struct ExpDesc { | |||
61 | } ExpDesc; | 65 | } ExpDesc; |
62 | 66 | ||
63 | /* Macros for expressions. */ | 67 | /* Macros for expressions. */ |
64 | #define expr_hasjump(e) ((e)->t != (e)->f) | 68 | #define expr_hasjump(e) ((e)->t != (e)->f) |
65 | 69 | ||
66 | #define expr_isk(e) ((e)->k <= VKLAST) | 70 | #define expr_isk(e) ((e)->k <= VKLAST) |
67 | #define expr_isk_nojump(e) (expr_isk(e) && !expr_hasjump(e)) | 71 | #define expr_isk_nojump(e) (expr_isk(e) && !expr_hasjump(e)) |
@@ -216,6 +220,17 @@ GCstr *lj_parse_keepstr(LexState *ls, const char *str, size_t len) | |||
216 | return s; | 220 | return s; |
217 | } | 221 | } |
218 | 222 | ||
223 | #if LJ_HASFFI | ||
224 | /* Anchor cdata to avoid GC. */ | ||
225 | void lj_parse_keepcdata(LexState *ls, TValue *tv, GCcdata *cd) | ||
226 | { | ||
227 | /* NOBARRIER: the key is new or kept alive. */ | ||
228 | lua_State *L = ls->L; | ||
229 | setcdataV(L, tv, cd); | ||
230 | setboolV(lj_tab_set(L, ls->fs->kt, tv), 1); | ||
231 | } | ||
232 | #endif | ||
233 | |||
219 | /* -- Jump list handling -------------------------------------------------- */ | 234 | /* -- Jump list handling -------------------------------------------------- */ |
220 | 235 | ||
221 | /* Get next element in jump list. */ | 236 | /* Get next element in jump list. */ |
@@ -469,6 +484,11 @@ static void expr_toreg_nobranch(FuncState *fs, ExpDesc *e, BCReg reg) | |||
469 | ins = BCINS_AD(BC_KSHORT, reg, (BCReg)(uint16_t)k); | 484 | ins = BCINS_AD(BC_KSHORT, reg, (BCReg)(uint16_t)k); |
470 | else | 485 | else |
471 | ins = BCINS_AD(BC_KNUM, reg, const_num(fs, e)); | 486 | ins = BCINS_AD(BC_KNUM, reg, const_num(fs, e)); |
487 | #if LJ_HASFFI | ||
488 | } else if (e->k == VKCDATA) { | ||
489 | ins = BCINS_AD(BC_KCDATA, reg, | ||
490 | const_gc(fs, obj2gco(cdataV(&e->u.nval)), LJ_TCDATA)); | ||
491 | #endif | ||
472 | } else if (e->k == VRELOCABLE) { | 492 | } else if (e->k == VRELOCABLE) { |
473 | setbc_a(bcptr(fs, e), reg); | 493 | setbc_a(bcptr(fs, e), reg); |
474 | goto noins; | 494 | goto noins; |
@@ -856,7 +876,7 @@ static void bcemit_unop(FuncState *fs, BCOp op, ExpDesc *e) | |||
856 | if (e->k == VKNIL || e->k == VKFALSE) { | 876 | if (e->k == VKNIL || e->k == VKFALSE) { |
857 | e->k = VKTRUE; | 877 | e->k = VKTRUE; |
858 | return; | 878 | return; |
859 | } else if (expr_isk(e)) { | 879 | } else if (expr_isk(e) || (LJ_HASFFI && e->k == VKCDATA)) { |
860 | e->k = VKFALSE; | 880 | e->k = VKFALSE; |
861 | return; | 881 | return; |
862 | } else if (e->k == VJMP) { | 882 | } else if (e->k == VJMP) { |
@@ -872,10 +892,22 @@ static void bcemit_unop(FuncState *fs, BCOp op, ExpDesc *e) | |||
872 | } | 892 | } |
873 | } else { | 893 | } else { |
874 | lua_assert(op == BC_UNM || op == BC_LEN); | 894 | lua_assert(op == BC_UNM || op == BC_LEN); |
875 | /* Constant-fold negations. But avoid folding to -0. */ | 895 | if (op == BC_UNM && !expr_hasjump(e)) { /* Constant-fold negations. */ |
876 | if (op == BC_UNM && expr_isnumk_nojump(e) && expr_numV(e) != 0) { | 896 | #if LJ_HASFFI |
877 | setnumV(&e->u.nval, -expr_numV(e)); | 897 | if (e->k == VKCDATA) { /* Fold in-place since cdata is not interned. */ |
878 | return; | 898 | GCcdata *cd = cdataV(&e->u.nval); |
899 | int64_t *p = (int64_t *)cdataptr(cd); | ||
900 | if (cd->typeid == CTID_COMPLEX_DOUBLE) | ||
901 | p[1] ^= (int64_t)U64x(80000000,00000000); | ||
902 | else | ||
903 | *p = -*p; | ||
904 | return; | ||
905 | } else | ||
906 | #endif | ||
907 | if (expr_isnumk(e) && expr_numV(e) != 0) { /* Avoid folding to -0. */ | ||
908 | e->u.nval.u64 ^= U64x(80000000,00000000); | ||
909 | return; | ||
910 | } | ||
879 | } | 911 | } |
880 | expr_toanyreg(fs, e); | 912 | expr_toanyreg(fs, e); |
881 | } | 913 | } |
@@ -1554,8 +1586,8 @@ static void expr_simple(LexState *ls, ExpDesc *v) | |||
1554 | { | 1586 | { |
1555 | switch (ls->token) { | 1587 | switch (ls->token) { |
1556 | case TK_number: | 1588 | case TK_number: |
1557 | expr_init(v, VKNUM, 0); | 1589 | expr_init(v, (LJ_HASFFI && tviscdata(&ls->tokenval)) ? VKCDATA : VKNUM, 0); |
1558 | setnumV(&v->u.nval, numV(&ls->tokenval)); | 1590 | copyTV(ls->L, &v->u.nval, &ls->tokenval); |
1559 | break; | 1591 | break; |
1560 | case TK_string: | 1592 | case TK_string: |
1561 | expr_init(v, VKSTR, 0); | 1593 | expr_init(v, VKSTR, 0); |