Incorrect narrowing for huge numbers.
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 18/100
Piste de recherche
The bug is in the narrowing pass of the JIT, so start in src/lj_opt_narrow.c, at narrow_conv_emit, where the integer conversion is emitted. Reproduce with src/luajit -Ohotloop=1 using the s + 1 - 0LL - s loop from the issue, and compare against jit.off(). Done when the traced results match the interpreter for values at or beyond 2^53, and the trace dump shows the range guard.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Mantissa precision of IEEE-754 doubles can't store integral types precision for |x| >= 2^53.
That means that premature folding optimization may lead to invalid results in cases like the following:
x + 1 + 0LL - x => 1LL; x >= 2^53
x - 1 + 0LL - x => -1LL; x <= -2^53
since it changes the semantics of operations to (int)x + 1LL instead of (int)((double)x + 1.) + 0LL.
Lua examples of this misbehaviour:
src/luajit -Ohotloop=1 -e '
local s = 2^53
local v = {}
for i = 1, 4 do
v[i] = s + 1 - 0LL - s
end
jit.off()
for i = 1, 4 do
print(i,v[i])
end
'
1 0LL
2 0LL
3 0LL
4 1LL
or vice versa for substracture:
src/luajit -Ohotloop=1 -e '
local s = -2^53
local v = {}
for i = 1, 4 do
v[i] = s - 1 - 0LL - s
end
jit.off()
for i = 1, 4 do
print(i,v[i])
end
'
1 0LL
2 0LL
3 0LL
4 -1LL
The start of the trace looks like the following with enabled narrowing:
---- TRACE 1 start (command line):4
---- TRACE 1 IR
0001 int SLOAD #4 CI
0002 > num SLOAD #2 T
0007 > cdt CNEWI +11 +1
And like the following with disabled:
0001 num SLOAD #4 I
0002 > num SLOAD #2 T
0003 num ADD 0002 +1
0004 i64 CONV 0003 i64.num none
0006 i64 CONV 0002 i64.num none
0007 i64 SUB 0004 0006
0008 > cdt CNEWI +11 0007
One of the ways to fix it is to add an assertion guard before corresponding conversions (it seems harmless for the SPEC benchmarks).
PoC workaround for the problem:
diff --git a/src/lj_opt_narrow.c b/src/lj_opt_narrow.c
index db0da10f..5dd3819c 100644
--- a/src/lj_opt_narrow.c
+++ b/src/lj_opt_narrow.c
@@ -370,6 +370,15 @@ static IRRef narrow_conv_emit(jit_State *J, NarrowConv *nc)
if (op == NARROW_REF) {
*sp++ = ref;
} else if (op == NARROW_CONV) {
+ if (fins->o == IR_CONV && (fins->op2 & IRCONV_SRCMASK) == IRT_NUM) {
+ IRIns *srcins = IR(fins->op1);
+ if (srcins->o == IR_SUB)
+ emitir(IRTG(IR_GT, IRT_NUM), srcins->op1,
+ lj_ir_knum(J, -(lua_Number)(1LL<<52)));
+ else if (srcins->o == IR_ADD)
+ emitir(IRTG(IR_LT, IRT_NUM), srcins->op1,
+ lj_ir_knum(J, (lua_Number)(1LL<<52)));
+ }
*sp++ = emitir_raw(convot, ref, convop2); /* Raw emit avoids a loop. */
} else if (op == NARROW_SEXT) {
lj_assertJ(sp >= nc->stack+1, "stack underflow");
The start of a trace after the patch looks like the following:
---- TRACE 1 IR
0001 int SLOAD #4 CI
0002 > num SLOAD #2 T
0004 > num LT 0002 +4.5035996273705e+15
0008 > cdt CNEWI +11 +1
- Langage dominant
- C
- Étoiles
- 5.8k
- Forks
- 1.2k
- Métriques de merge des PR
- Aucune PR mergée en 30 j
Préparer son environnement
Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de LuaJIT/LuaJIT
-
Difficulté 2/5 1-3 heures Accessibilité débutants 74/100
-
Difficulté 4/5 3-5 jours Accessibilité débutants 35/100
-
3.0 enhancement
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 12/100
-
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 18/100
-
Difficulté 4/5 3-5 jours Accessibilité débutants 30/100
Toutes les issues de LuaJIT/LuaJIT
Issues similaires
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
micropython/micropython#19906 ·
Les mainteneurs répondent en général sous 1 jour
-
QOI: QOI_OP_RUN does not update the previously seen pixels, corrupting qoi_test_images/edgecase.qoiPeut-être pris @manit2004 l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
python-pillow/Pillow#10452 · 4 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 1/5 Moins d'une heure Accessibilité débutants 75/100
Les mainteneurs répondent en général sous 10 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 77/100
JPHutchins/dynamic-call-tree-resolution#349 ·
Les mainteneurs répondent en général sous 1 jour
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
Les mainteneurs répondent en général sous 1 jour