Skip to content

Commit 89fc0f0

Browse files
committed
Refactor Perl_av_fetch: remove goto, reduce the number of branches
1 parent c0b8ab1 commit 89fc0f0

File tree

1 file changed

+14
-18
lines changed

1 file changed

+14
-18
lines changed

av.c

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,6 @@ S_adjust_index(pTHX_ AV *av, const MAGIC *mg, SSize_t *keyp)
266266
SV**
267267
Perl_av_fetch(pTHX_ AV *av, SSize_t key, I32 lval)
268268
{
269-
SSize_t neg;
270-
SSize_t size;
271-
272269
PERL_ARGS_ASSERT_AV_FETCH;
273270

274271
if (UNLIKELY(SvRMAGICAL(av))) {
@@ -291,24 +288,23 @@ Perl_av_fetch(pTHX_ AV *av, SSize_t key, I32 lval)
291288
}
292289
}
293290

294-
neg = (key < 0);
295-
size = AvFILLp(av) + 1;
296-
key += neg * size; /* handle negative index without using branch */
291+
/* recalculating key early helps branch prediction */
292+
SSize_t neg = key < 0;
293+
SSize_t size = AvFILLp(av) + 1;
294+
key += neg * size;
297295

298296
/* the cast from SSize_t to Size_t allows both (key < 0) and (key >= size)
299297
* to be tested as a single condition */
300-
if ((Size_t)key >= (Size_t)size) {
301-
if (UNLIKELY(neg))
302-
return NULL;
303-
goto emptiness;
304-
}
305-
306-
if (!AvARRAY(av)[key]) {
307-
emptiness:
308-
return lval ? av_store(av,key,newSV_type(SVt_NULL)) : NULL;
309-
}
310-
311-
return &AvARRAY(av)[key];
298+
if ((Size_t)key >= (Size_t)size)
299+
/* Only non-negative out of bounds keys are eligible for lvalue
300+
* treatment, so adjust lval by setting value to 0 if the key was
301+
* negative */
302+
lval *= !neg;
303+
else if (AvARRAY(av)[key])
304+
return &AvARRAY(av)[key];
305+
306+
/* value does not exist in the array */
307+
return lval ? av_store(av, key, newSV_type(SVt_NULL)) : NULL;
312308
}
313309

314310
/*

0 commit comments

Comments
 (0)