diff options
author | Mike Pall <mike> | 2022-01-15 17:52:21 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2022-01-15 17:52:21 +0100 |
commit | d5a237eae03d2ad346f82390836371a952e9a286 (patch) | |
tree | 339cbf74ab7d3a6e49d90b34a88df7427cb23a41 | |
parent | bc1bdbf620f58f0978385828bc51272903601e17 (diff) | |
download | luajit-d5a237eae03d2ad346f82390836371a952e9a286.tar.gz luajit-d5a237eae03d2ad346f82390836371a952e9a286.tar.bz2 luajit-d5a237eae03d2ad346f82390836371a952e9a286.zip |
Fix HREFK forwarding vs. table.clear().
Reported by XmiliaH.
-rw-r--r-- | src/lj_opt_mem.c | 63 |
1 files changed, 32 insertions, 31 deletions
diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c index d6a419e4..f8059cb1 100644 --- a/src/lj_opt_mem.c +++ b/src/lj_opt_mem.c | |||
@@ -72,6 +72,34 @@ static AliasRet aa_table(jit_State *J, IRRef ta, IRRef tb) | |||
72 | return aa_escape(J, taba, tabb); | 72 | return aa_escape(J, taba, tabb); |
73 | } | 73 | } |
74 | 74 | ||
75 | /* Check whether there's no aliasing table.clear. */ | ||
76 | static int fwd_aa_tab_clear(jit_State *J, IRRef lim, IRRef ta) | ||
77 | { | ||
78 | IRRef ref = J->chain[IR_CALLS]; | ||
79 | while (ref > lim) { | ||
80 | IRIns *calls = IR(ref); | ||
81 | if (calls->op2 == IRCALL_lj_tab_clear && | ||
82 | (ta == calls->op1 || aa_table(J, ta, calls->op1) != ALIAS_NO)) | ||
83 | return 0; /* Conflict. */ | ||
84 | ref = calls->prev; | ||
85 | } | ||
86 | return 1; /* No conflict. Can safely FOLD/CSE. */ | ||
87 | } | ||
88 | |||
89 | /* Check whether there's no aliasing NEWREF/table.clear for the left operand. */ | ||
90 | int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) | ||
91 | { | ||
92 | IRRef ta = fins->op1; | ||
93 | IRRef ref = J->chain[IR_NEWREF]; | ||
94 | while (ref > lim) { | ||
95 | IRIns *newref = IR(ref); | ||
96 | if (ta == newref->op1 || aa_table(J, ta, newref->op1) != ALIAS_NO) | ||
97 | return 0; /* Conflict. */ | ||
98 | ref = newref->prev; | ||
99 | } | ||
100 | return fwd_aa_tab_clear(J, lim, ta); | ||
101 | } | ||
102 | |||
75 | /* Alias analysis for array and hash access using key-based disambiguation. */ | 103 | /* Alias analysis for array and hash access using key-based disambiguation. */ |
76 | static AliasRet aa_ahref(jit_State *J, IRIns *refa, IRIns *refb) | 104 | static AliasRet aa_ahref(jit_State *J, IRIns *refa, IRIns *refb) |
77 | { | 105 | { |
@@ -154,7 +182,8 @@ static TRef fwd_ahload(jit_State *J, IRRef xref) | |||
154 | IRIns *ir = (xr->o == IR_HREFK || xr->o == IR_AREF) ? IR(xr->op1) : xr; | 182 | IRIns *ir = (xr->o == IR_HREFK || xr->o == IR_AREF) ? IR(xr->op1) : xr; |
155 | IRRef tab = ir->op1; | 183 | IRRef tab = ir->op1; |
156 | ir = IR(tab); | 184 | ir = IR(tab); |
157 | if (ir->o == IR_TNEW || (ir->o == IR_TDUP && irref_isk(xr->op2))) { | 185 | if ((ir->o == IR_TNEW || (ir->o == IR_TDUP && irref_isk(xr->op2))) && |
186 | fwd_aa_tab_clear(J, tab, tab)) { | ||
158 | /* A NEWREF with a number key may end up pointing to the array part. | 187 | /* A NEWREF with a number key may end up pointing to the array part. |
159 | ** But it's referenced from HSTORE and not found in the ASTORE chain. | 188 | ** But it's referenced from HSTORE and not found in the ASTORE chain. |
160 | ** For now simply consider this a conflict without forwarding anything. | 189 | ** For now simply consider this a conflict without forwarding anything. |
@@ -269,7 +298,7 @@ TRef LJ_FASTCALL lj_opt_fwd_hrefk(jit_State *J) | |||
269 | while (ref > tab) { | 298 | while (ref > tab) { |
270 | IRIns *newref = IR(ref); | 299 | IRIns *newref = IR(ref); |
271 | if (tab == newref->op1) { | 300 | if (tab == newref->op1) { |
272 | if (fright->op1 == newref->op2) | 301 | if (fright->op1 == newref->op2 && fwd_aa_tab_clear(J, ref, tab)) |
273 | return ref; /* Forward from NEWREF. */ | 302 | return ref; /* Forward from NEWREF. */ |
274 | else | 303 | else |
275 | goto docse; | 304 | goto docse; |
@@ -279,7 +308,7 @@ TRef LJ_FASTCALL lj_opt_fwd_hrefk(jit_State *J) | |||
279 | ref = newref->prev; | 308 | ref = newref->prev; |
280 | } | 309 | } |
281 | /* No conflicting NEWREF: key location unchanged for HREFK of TDUP. */ | 310 | /* No conflicting NEWREF: key location unchanged for HREFK of TDUP. */ |
282 | if (IR(tab)->o == IR_TDUP) | 311 | if (IR(tab)->o == IR_TDUP && fwd_aa_tab_clear(J, tab, tab)) |
283 | fins->t.irt &= ~IRT_GUARD; /* Drop HREFK guard. */ | 312 | fins->t.irt &= ~IRT_GUARD; /* Drop HREFK guard. */ |
284 | docse: | 313 | docse: |
285 | return CSEFOLD; | 314 | return CSEFOLD; |
@@ -313,34 +342,6 @@ int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J) | |||
313 | return 1; /* No conflict. Can fold to niltv. */ | 342 | return 1; /* No conflict. Can fold to niltv. */ |
314 | } | 343 | } |
315 | 344 | ||
316 | /* Check whether there's no aliasing table.clear. */ | ||
317 | static int fwd_aa_tab_clear(jit_State *J, IRRef lim, IRRef ta) | ||
318 | { | ||
319 | IRRef ref = J->chain[IR_CALLS]; | ||
320 | while (ref > lim) { | ||
321 | IRIns *calls = IR(ref); | ||
322 | if (calls->op2 == IRCALL_lj_tab_clear && | ||
323 | (ta == calls->op1 || aa_table(J, ta, calls->op1) != ALIAS_NO)) | ||
324 | return 0; /* Conflict. */ | ||
325 | ref = calls->prev; | ||
326 | } | ||
327 | return 1; /* No conflict. Can safely FOLD/CSE. */ | ||
328 | } | ||
329 | |||
330 | /* Check whether there's no aliasing NEWREF/table.clear for the left operand. */ | ||
331 | int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) | ||
332 | { | ||
333 | IRRef ta = fins->op1; | ||
334 | IRRef ref = J->chain[IR_NEWREF]; | ||
335 | while (ref > lim) { | ||
336 | IRIns *newref = IR(ref); | ||
337 | if (ta == newref->op1 || aa_table(J, ta, newref->op1) != ALIAS_NO) | ||
338 | return 0; /* Conflict. */ | ||
339 | ref = newref->prev; | ||
340 | } | ||
341 | return fwd_aa_tab_clear(J, lim, ta); | ||
342 | } | ||
343 | |||
344 | /* ASTORE/HSTORE elimination. */ | 345 | /* ASTORE/HSTORE elimination. */ |
345 | TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J) | 346 | TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J) |
346 | { | 347 | { |