aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2022-01-15 17:52:21 +0100
committerMike Pall <mike>2022-01-15 17:52:21 +0100
commitd5a237eae03d2ad346f82390836371a952e9a286 (patch)
tree339cbf74ab7d3a6e49d90b34a88df7427cb23a41
parentbc1bdbf620f58f0978385828bc51272903601e17 (diff)
downloadluajit-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.c63
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. */
76static 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. */
90int 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. */
76static AliasRet aa_ahref(jit_State *J, IRIns *refa, IRIns *refb) 104static 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. */
284docse: 313docse:
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. */
317static 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. */
331int 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. */
345TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J) 346TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J)
346{ 347{