forked from php/php-src
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Optimize array_key_exists/in_array for empty array
Make opcache replace the result with false if the array argument is known to be empty. This may be useful when a codebase has placeholders, e.g. `if (!in_array($method, self::ALLOWED_METHODS)) { return; }` In zend_inference.c: In php 8, array_key_exists will throw a TypeError instead of returning null. I didn't see any discussion of this optimization (for/against) after a quick search on github, e.g. phpGH-3360 Potential future optimizations: - convert `in_array($needle, ['only one element'], true)` to `===`? (or `==` for strict=false) - When the number of elements is less than 4, switch to looping instead of hash lookup. (exact threshold for better performance to be determined) Also support looping for `in_array($value, [false, 'str', 2.5], true/false)`
- Loading branch information
1 parent
f826bbd
commit 9f410c2
Showing
5 changed files
with
136 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
--TEST-- | ||
array_key_exists() on known empty array | ||
--SKIPIF-- | ||
<?php require_once('skipif.inc'); ?> | ||
--FILE-- | ||
<?php | ||
error_reporting(E_ALL); | ||
function helper(&$var) { | ||
var_dump($var); | ||
} | ||
class ExampleArrayKeyExists { | ||
const EMPTY_ARRAY = []; | ||
public static function test(int $x, array $arr) { | ||
$y = array_key_exists($x, self::EMPTY_ARRAY); | ||
$v2 = array_key_exists($undef, self::EMPTY_ARRAY); | ||
$z = array_key_exists($x, []); | ||
$z1 = array_key_exists($x, [1 => true]); | ||
$z2 = array_key_exists($x, [2 => true]); | ||
$w = array_key_exists('literal', self::EMPTY_ARRAY); | ||
echo helper($y); | ||
echo helper($z); | ||
echo helper($w); | ||
echo helper($z1); | ||
echo helper($z2); | ||
$unusedVar = array_key_exists('unused', $arr); | ||
if (array_key_exists(printf("Should get called\n"), self::EMPTY_ARRAY)) { | ||
echo "Impossible\n"; | ||
} | ||
$v = array_key_exists($arr, self::EMPTY_ARRAY); | ||
} | ||
} | ||
try { | ||
ExampleArrayKeyExists::test(1,[2]); | ||
} catch (TypeError $e) { | ||
printf("%s at line %d\n", $e->getMessage(), $e->getLine()); | ||
} | ||
?> | ||
--EXPECTF-- | ||
Warning: Undefined variable: undef in %s on line 10 | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(true) | ||
bool(false) | ||
Should get called | ||
Illegal offset type at line 24 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
--TEST-- | ||
in_array() on known empty array | ||
--SKIPIF-- | ||
<?php require_once('skipif.inc'); ?> | ||
--FILE-- | ||
<?php | ||
error_reporting(E_ALL); | ||
function helper(&$var) { | ||
var_dump($var); | ||
} | ||
class ExampleInArray { | ||
const EMPTY_ARRAY = []; | ||
public static function test(int $x, array $arr) { | ||
$y = in_array($x, self::EMPTY_ARRAY); | ||
$y2 = in_array($x, self::EMPTY_ARRAY, true); | ||
$v2 = in_array($undef, self::EMPTY_ARRAY); | ||
$z = in_array($x, []); | ||
$w = in_array('literal', self::EMPTY_ARRAY); | ||
$z1 = in_array($x, [1]); | ||
$z2 = in_array($x, [2]); | ||
$z3 = in_array($x, [1], true); | ||
$z4 = in_array($x, [2], true); | ||
echo helper($y); | ||
echo helper($y2); | ||
echo helper($z); | ||
echo helper($w); | ||
echo "Results for non-empty arrays\n"; | ||
echo helper($z1); | ||
echo helper($z2); | ||
echo helper($z3); | ||
echo helper($z4); | ||
$unusedVar = in_array('unused', $arr); | ||
if (in_array(printf("Should get called\n"), self::EMPTY_ARRAY)) { | ||
echo "Impossible\n"; | ||
} | ||
} | ||
} | ||
ExampleInArray::test(1,[2]); | ||
?> | ||
--EXPECTF-- | ||
Warning: Undefined variable: undef in %s on line 11 | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
Results for non-empty arrays | ||
bool(true) | ||
bool(false) | ||
bool(true) | ||
bool(false) | ||
Should get called |