mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Implement match expression
RFC: https://wiki.php.net/rfc/match_expression_v2 Closes GH-5371.
This commit is contained in:
parent
c60d0dc2f4
commit
9fa1d13301
@ -571,6 +571,8 @@ PHP 8.0 UPGRADE NOTES
|
||||
. Added support for constructor property promotion (declaring properties in
|
||||
the constructor signature).
|
||||
RFC: https://wiki.php.net/rfc/constructor_promotion
|
||||
. Added support for `match` expression.
|
||||
RFC: https://wiki.php.net/rfc/match_expression_v2
|
||||
|
||||
- Date:
|
||||
. Added DateTime::createFromInterface() and
|
||||
|
36
Zend/tests/match/001.phpt
Normal file
36
Zend/tests/match/001.phpt
Normal file
@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
Basic match expression functionality test
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function wordify($x) {
|
||||
return match ($x) {
|
||||
0 => 'Zero',
|
||||
1 => 'One',
|
||||
2 => 'Two',
|
||||
3 => 'Three',
|
||||
4 => 'Four',
|
||||
5 => 'Five',
|
||||
6 => 'Six',
|
||||
7 => 'Seven',
|
||||
8 => 'Eight',
|
||||
9 => 'Nine',
|
||||
};
|
||||
}
|
||||
|
||||
for ($i = 0; $i <= 9; $i++) {
|
||||
print wordify($i) . "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Zero
|
||||
One
|
||||
Two
|
||||
Three
|
||||
Four
|
||||
Five
|
||||
Six
|
||||
Seven
|
||||
Eight
|
||||
Nine
|
19
Zend/tests/match/002.phpt
Normal file
19
Zend/tests/match/002.phpt
Normal file
@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Match expression omit trailing comma
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function print_bool($bool) {
|
||||
echo match ($bool) {
|
||||
true => "true\n",
|
||||
false => "false\n"
|
||||
};
|
||||
}
|
||||
|
||||
print_bool(true);
|
||||
print_bool(false);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
true
|
||||
false
|
24
Zend/tests/match/003.phpt
Normal file
24
Zend/tests/match/003.phpt
Normal file
@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
Match expression default case
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function get_value($i) {
|
||||
return match ($i) {
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
default => 'default',
|
||||
};
|
||||
}
|
||||
|
||||
echo get_value(0) . "\n";
|
||||
echo get_value(1) . "\n";
|
||||
echo get_value(2) . "\n";
|
||||
echo get_value(3) . "\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
default
|
||||
1
|
||||
2
|
||||
default
|
31
Zend/tests/match/004.phpt
Normal file
31
Zend/tests/match/004.phpt
Normal file
@ -0,0 +1,31 @@
|
||||
--TEST--
|
||||
Match expression with true as expression
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function get_range($i) {
|
||||
return match (true) {
|
||||
$i >= 50 => '50+',
|
||||
$i >= 40 => '40-50',
|
||||
$i >= 30 => '30-40',
|
||||
$i >= 20 => '20-30',
|
||||
$i >= 10 => '10-20',
|
||||
default => '0-10',
|
||||
};
|
||||
}
|
||||
|
||||
echo get_range(22) . "\n";
|
||||
echo get_range(0) . "\n";
|
||||
echo get_range(59) . "\n";
|
||||
echo get_range(13) . "\n";
|
||||
echo get_range(39) . "\n";
|
||||
echo get_range(40) . "\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
20-30
|
||||
0-10
|
||||
50+
|
||||
10-20
|
||||
30-40
|
||||
40-50
|
12
Zend/tests/match/005.phpt
Normal file
12
Zend/tests/match/005.phpt
Normal file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
Match expression discarding result
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
match (1) {
|
||||
1 => print "Executed\n",
|
||||
};
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Executed
|
13
Zend/tests/match/006.phpt
Normal file
13
Zend/tests/match/006.phpt
Normal file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
Match expression with no cases
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$x = match (true) {};
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type bool in %s
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
26
Zend/tests/match/007.phpt
Normal file
26
Zend/tests/match/007.phpt
Normal file
@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
Match expression exception on unhandled case
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function get_value($i) {
|
||||
return match ($i) {
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
};
|
||||
}
|
||||
|
||||
echo get_value(1) . "\n";
|
||||
echo get_value(2) . "\n";
|
||||
echo get_value(3) . "\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
1
|
||||
2
|
||||
|
||||
Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type int in %s
|
||||
Stack trace:
|
||||
#0 %s: get_value(3)
|
||||
#1 {main}
|
||||
thrown in %s on line %d
|
25
Zend/tests/match/008.phpt
Normal file
25
Zend/tests/match/008.phpt
Normal file
@ -0,0 +1,25 @@
|
||||
--TEST--
|
||||
Match expression multiple conditions per case
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function is_working_day($day) {
|
||||
return match ($day) {
|
||||
1, 7 => false,
|
||||
2, 3, 4, 5, 6 => true,
|
||||
};
|
||||
}
|
||||
|
||||
for ($i = 1; $i <= 7; $i++) {
|
||||
var_dump(is_working_day($i));
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
22
Zend/tests/match/009.phpt
Normal file
22
Zend/tests/match/009.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Pretty printing for match expression
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
assert((function () {
|
||||
match ('foo') {
|
||||
'foo', 'bar' => false,
|
||||
'baz' => 'a',
|
||||
default => 'b',
|
||||
};
|
||||
})());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: assert(): assert(function () {
|
||||
match ('foo') {
|
||||
'foo', 'bar' => false,
|
||||
'baz' => 'a',
|
||||
default => 'b',
|
||||
};
|
||||
}()) failed in %s on line %d
|
19
Zend/tests/match/011.phpt
Normal file
19
Zend/tests/match/011.phpt
Normal file
@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Implicit break in match expression
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function dump_and_return($string) {
|
||||
var_dump($string);
|
||||
return $string;
|
||||
}
|
||||
|
||||
var_dump(match ('foo') {
|
||||
'foo' => dump_and_return('foo'),
|
||||
'bar' => dump_and_return('bar'),
|
||||
});
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(3) "foo"
|
||||
string(3) "foo"
|
36
Zend/tests/match/012.phpt
Normal file
36
Zend/tests/match/012.phpt
Normal file
@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
Strict comparison in match expression
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function wrong() {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
var_dump(match (0) {
|
||||
null => wrong(),
|
||||
false => wrong(),
|
||||
0.0 => wrong(),
|
||||
[] => wrong(),
|
||||
'' => wrong(),
|
||||
0 => 'int',
|
||||
});
|
||||
|
||||
function get_value() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var_dump(match (get_value()) {
|
||||
null => wrong(),
|
||||
false => wrong(),
|
||||
0.0 => wrong(),
|
||||
[] => wrong(),
|
||||
'' => wrong(),
|
||||
0 => 'int',
|
||||
default => 'default',
|
||||
});
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(3) "int"
|
||||
string(3) "int"
|
92
Zend/tests/match/017.phpt
Normal file
92
Zend/tests/match/017.phpt
Normal file
@ -0,0 +1,92 @@
|
||||
--TEST--
|
||||
Test strict comparison with match expression jump table
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function wrong() {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
function test_int($char) {
|
||||
return match ($char) {
|
||||
0 => wrong(),
|
||||
1 => wrong(),
|
||||
2 => wrong(),
|
||||
3 => wrong(),
|
||||
4 => wrong(),
|
||||
5 => wrong(),
|
||||
6 => wrong(),
|
||||
7 => wrong(),
|
||||
8 => wrong(),
|
||||
9 => wrong(),
|
||||
default => 'Not matched',
|
||||
};
|
||||
}
|
||||
|
||||
foreach (range(0, 9) as $int) {
|
||||
var_dump((string) $int);
|
||||
var_dump(test_int((string) $int));
|
||||
}
|
||||
|
||||
function test_string($int) {
|
||||
return match ($int) {
|
||||
'0' => wrong(),
|
||||
'1' => wrong(),
|
||||
'2' => wrong(),
|
||||
'3' => wrong(),
|
||||
'4' => wrong(),
|
||||
'5' => wrong(),
|
||||
'6' => wrong(),
|
||||
'7' => wrong(),
|
||||
'8' => wrong(),
|
||||
'9' => wrong(),
|
||||
default => 'Not matched',
|
||||
};
|
||||
}
|
||||
|
||||
foreach (range(0, 9) as $int) {
|
||||
var_dump($int);
|
||||
var_dump(test_string($int));
|
||||
}
|
||||
|
||||
--EXPECT--
|
||||
string(1) "0"
|
||||
string(11) "Not matched"
|
||||
string(1) "1"
|
||||
string(11) "Not matched"
|
||||
string(1) "2"
|
||||
string(11) "Not matched"
|
||||
string(1) "3"
|
||||
string(11) "Not matched"
|
||||
string(1) "4"
|
||||
string(11) "Not matched"
|
||||
string(1) "5"
|
||||
string(11) "Not matched"
|
||||
string(1) "6"
|
||||
string(11) "Not matched"
|
||||
string(1) "7"
|
||||
string(11) "Not matched"
|
||||
string(1) "8"
|
||||
string(11) "Not matched"
|
||||
string(1) "9"
|
||||
string(11) "Not matched"
|
||||
int(0)
|
||||
string(11) "Not matched"
|
||||
int(1)
|
||||
string(11) "Not matched"
|
||||
int(2)
|
||||
string(11) "Not matched"
|
||||
int(3)
|
||||
string(11) "Not matched"
|
||||
int(4)
|
||||
string(11) "Not matched"
|
||||
int(5)
|
||||
string(11) "Not matched"
|
||||
int(6)
|
||||
string(11) "Not matched"
|
||||
int(7)
|
||||
string(11) "Not matched"
|
||||
int(8)
|
||||
string(11) "Not matched"
|
||||
int(9)
|
||||
string(11) "Not matched"
|
20
Zend/tests/match/023.phpt
Normal file
20
Zend/tests/match/023.phpt
Normal file
@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
Test match strict comparison with true expression
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function wrong() {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
echo match (true) {
|
||||
'truthy' => wrong(),
|
||||
['truthy'] => wrong(),
|
||||
new stdClass() => wrong(),
|
||||
1 => wrong(),
|
||||
1.0 => wrong(),
|
||||
true => "true\n",
|
||||
};
|
||||
|
||||
--EXPECT--
|
||||
true
|
19
Zend/tests/match/024.phpt
Normal file
19
Zend/tests/match/024.phpt
Normal file
@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Test match strict comparison with false expression
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function wrong() {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
echo match (false) {
|
||||
'' => wrong(),
|
||||
[] => wrong(),
|
||||
0 => wrong(),
|
||||
0.0 => wrong(),
|
||||
false => "false\n",
|
||||
};
|
||||
|
||||
--EXPECT--
|
||||
false
|
36
Zend/tests/match/027.phpt
Normal file
36
Zend/tests/match/027.phpt
Normal file
@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
Test result of match cannot be modified by reference
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
// opcache can't be certain Test::usesRef is actually this method
|
||||
if (!class_exists('Test')) {
|
||||
class Test {
|
||||
public static function usesRef(&$x) {
|
||||
$x = 'modified';
|
||||
}
|
||||
public static function usesValue($x) {
|
||||
echo "usesValue $x\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
$i = 0;
|
||||
Test::usesValue(match(true) { true => $i });
|
||||
echo "i is $i\n";
|
||||
$j = 1;
|
||||
Test::usesRef(match(true) { true => $j });
|
||||
echo "j is $j\n";
|
||||
}
|
||||
main();
|
||||
|
||||
--EXPECTF--
|
||||
usesValue 0
|
||||
i is 0
|
||||
|
||||
Fatal error: Uncaught Error: Cannot pass parameter 1 by reference in %s027.php:20
|
||||
Stack trace:
|
||||
#0 %s027.php(23): main()
|
||||
#1 {main}
|
||||
thrown in %s027.php on line 20
|
36
Zend/tests/match/028.phpt
Normal file
36
Zend/tests/match/028.phpt
Normal file
@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
Test result of match cannot be modified by reference
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
// opcache can't be certain Test::usesRef is actually this method
|
||||
if (!class_exists('Test')) {
|
||||
class Test {
|
||||
public static function usesRef(&$x) {
|
||||
$x = 'modified';
|
||||
}
|
||||
public static function usesValue($x) {
|
||||
echo "usesValue $x\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main(int $i): int {
|
||||
Test::usesValue(match(true) { true => $i });
|
||||
Test::usesValue(match($i) { 42 => $i });
|
||||
var_dump($i);
|
||||
Test::usesRef(match(true) { true => $i });
|
||||
var_dump($i);
|
||||
}
|
||||
|
||||
try {
|
||||
main(42);
|
||||
} catch (Error $e) {
|
||||
printf("Caught %s\n", $e->getMessage());
|
||||
}
|
||||
|
||||
--EXPECT--
|
||||
usesValue 42
|
||||
usesValue 42
|
||||
int(42)
|
||||
Caught Cannot pass parameter 1 by reference
|
22
Zend/tests/match/029.phpt
Normal file
22
Zend/tests/match/029.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Test long match with undefined variable
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
set_error_handler(function ($errno, $message) {
|
||||
throw new Exception("Custom error handler: $message");
|
||||
});
|
||||
|
||||
echo match ($undefVar) {
|
||||
default => "This should not get printed with or without opcache\n",
|
||||
1, 2, 3, 4, 5 => "Also should not be printed\n",
|
||||
};
|
||||
|
||||
echo "unreachable\n";
|
||||
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught Exception: Custom error handler: Undefined variable $undefVar in %s029.php:4
|
||||
Stack trace:
|
||||
#0 %s029.php(7): {closure}(%d, 'Undefined varia...', '%s', %d)
|
||||
#1 {main}
|
||||
thrown in %s029.php on line 4
|
22
Zend/tests/match/030.phpt
Normal file
22
Zend/tests/match/030.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Test string match with undefined variable
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
set_error_handler(function ($errno, $message) {
|
||||
throw new Exception("Custom error handler: $message");
|
||||
});
|
||||
|
||||
echo match ($undefVar) {
|
||||
default => "This should not get printed with or without opcache\n",
|
||||
'1', '2', '3', '4', '5' => "Also should not be printed\n",
|
||||
};
|
||||
|
||||
echo "unreachable\n";
|
||||
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught Exception: Custom error handler: Undefined variable $undefVar in %s030.php:4
|
||||
Stack trace:
|
||||
#0 %s030.php(7): {closure}(%d, 'Undefined varia...', '%s', %d)
|
||||
#1 {main}
|
||||
thrown in %s030.php on line 4
|
68
Zend/tests/match/037.phpt
Normal file
68
Zend/tests/match/037.phpt
Normal file
@ -0,0 +1,68 @@
|
||||
--TEST--
|
||||
Test match jumptable with only one arm
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
var_dump(match(true) {
|
||||
1, 2, 3, 4, 5 => 'foo',
|
||||
});
|
||||
} catch (Error $e) {
|
||||
var_dump((string) $e);
|
||||
}
|
||||
|
||||
try {
|
||||
var_dump(match(6) {
|
||||
1, 2, 3, 4, 5 => 'foo',
|
||||
});
|
||||
} catch (Error $e) {
|
||||
var_dump((string) $e);
|
||||
}
|
||||
|
||||
try {
|
||||
var_dump(match('3') {
|
||||
1, 2, 3, 4, 5 => 'foo',
|
||||
});
|
||||
} catch (Error $e) {
|
||||
var_dump((string) $e);
|
||||
}
|
||||
|
||||
var_dump(match(3) {
|
||||
1, 2, 3, 4, 5 => 'foo',
|
||||
});
|
||||
|
||||
var_dump(match(true) {
|
||||
1, 2, 3, 4, 5 => 'foo',
|
||||
default => 'bar',
|
||||
});
|
||||
|
||||
var_dump(match(6) {
|
||||
1, 2, 3, 4, 5 => 'foo',
|
||||
default => 'bar',
|
||||
});
|
||||
|
||||
var_dump(match('3') {
|
||||
1, 2, 3, 4, 5 => 'foo',
|
||||
default => 'bar',
|
||||
});
|
||||
|
||||
var_dump(match(3) {
|
||||
1, 2, 3, 4, 5 => 'foo',
|
||||
default => 'bar',
|
||||
});
|
||||
|
||||
--EXPECTF--
|
||||
string(%d) "UnhandledMatchError: Unhandled match value of type bool in %s037.php:5
|
||||
Stack trace:
|
||||
#0 {main}"
|
||||
string(%d) "UnhandledMatchError: Unhandled match value of type int in %s037.php:13
|
||||
Stack trace:
|
||||
#0 {main}"
|
||||
string(%d) "UnhandledMatchError: Unhandled match value of type string in %s037.php:21
|
||||
Stack trace:
|
||||
#0 {main}"
|
||||
string(3) "foo"
|
||||
string(3) "bar"
|
||||
string(3) "bar"
|
||||
string(3) "bar"
|
||||
string(3) "foo"
|
15
Zend/tests/match/038.phpt
Normal file
15
Zend/tests/match/038.phpt
Normal file
@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
Test multiple default arms in match in different arms
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
match (1) {
|
||||
default => 'foo',
|
||||
1 => 'bar',
|
||||
2 => 'baz',
|
||||
default => 'qux',
|
||||
};
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Match expressions may only contain one default arm in %s on line 7
|
61
Zend/tests/match/039.phpt
Normal file
61
Zend/tests/match/039.phpt
Normal file
@ -0,0 +1,61 @@
|
||||
--TEST--
|
||||
Test match with duplicate conditions
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$value = 1;
|
||||
|
||||
echo match ($value) {
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
5 => 5,
|
||||
1 => 6,
|
||||
};
|
||||
echo "\n";
|
||||
|
||||
echo match ($value) {
|
||||
2, 1 => '2, 1',
|
||||
1 => 1,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
5 => 5,
|
||||
};
|
||||
echo "\n";
|
||||
|
||||
echo match ($value) {
|
||||
1, 1 => '1, 1',
|
||||
2, 2 => '2, 2',
|
||||
3, 3 => '3, 3',
|
||||
4, 4 => '4, 4',
|
||||
5, 5 => '5, 5',
|
||||
};
|
||||
echo "\n";
|
||||
|
||||
echo match ($value) {
|
||||
1 => 1,
|
||||
1 => 2,
|
||||
};
|
||||
echo "\n";
|
||||
|
||||
echo match ($value) {
|
||||
2, 1 => '2, 1',
|
||||
1 => 1,
|
||||
};
|
||||
echo "\n";
|
||||
|
||||
echo match ($value) {
|
||||
1, 1 => '1, 1',
|
||||
1 => 1,
|
||||
};
|
||||
echo "\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
1
|
||||
2, 1
|
||||
1, 1
|
||||
1
|
||||
2, 1
|
||||
1, 1
|
44
Zend/tests/match/040.phpt
Normal file
44
Zend/tests/match/040.phpt
Normal file
@ -0,0 +1,44 @@
|
||||
--TEST--
|
||||
Test match with mixed int/string jumptable
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test($value) {
|
||||
echo match ($value) {
|
||||
1 => '1 int',
|
||||
'1' => '1 string',
|
||||
2 => '2 int',
|
||||
'2' => '2 string',
|
||||
3 => '3 int',
|
||||
'3' => '3 string',
|
||||
4 => '4 int',
|
||||
'4' => '4 string',
|
||||
5 => '5 int',
|
||||
'5' => '5 string',
|
||||
};
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
test(1);
|
||||
test('1');
|
||||
test(2);
|
||||
test('2');
|
||||
test(3);
|
||||
test('3');
|
||||
test(4);
|
||||
test('4');
|
||||
test(5);
|
||||
test('5');
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
1 int
|
||||
1 string
|
||||
2 int
|
||||
2 string
|
||||
3 int
|
||||
3 string
|
||||
4 int
|
||||
4 string
|
||||
5 int
|
||||
5 string
|
33
Zend/tests/match/041.phpt
Normal file
33
Zend/tests/match/041.phpt
Normal file
@ -0,0 +1,33 @@
|
||||
--TEST--
|
||||
Match expression with trailing comma in condition list
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function print_bool($bool) {
|
||||
echo match ($bool) {
|
||||
false,
|
||||
0,
|
||||
=> "false\n",
|
||||
true,
|
||||
1,
|
||||
=> "true\n",
|
||||
default,
|
||||
=> "not bool\n",
|
||||
};
|
||||
}
|
||||
|
||||
print_bool(false);
|
||||
print_bool(0);
|
||||
print_bool(true);
|
||||
print_bool(1);
|
||||
print_bool(2);
|
||||
print_bool('foo');
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
false
|
||||
false
|
||||
true
|
||||
true
|
||||
not bool
|
||||
not bool
|
22
Zend/tests/match/042.phpt
Normal file
22
Zend/tests/match/042.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Match expression with undefined variable as expression
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(match ($undefinedVariable) {
|
||||
null => 'null',
|
||||
default => 'default',
|
||||
});
|
||||
|
||||
var_dump(match ($undefinedVariable) {
|
||||
1, 2, 3, 4, 5 => 'foo',
|
||||
default => 'bar',
|
||||
});
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: Undefined variable $undefinedVariable in %s.php on line 3
|
||||
string(4) "null"
|
||||
|
||||
Warning: Undefined variable $undefinedVariable in %s.php on line 8
|
||||
string(3) "bar"
|
@ -1590,6 +1590,7 @@ simple_list:
|
||||
break;
|
||||
case ZEND_AST_SWITCH_LIST:
|
||||
case ZEND_AST_CATCH_LIST:
|
||||
case ZEND_AST_MATCH_ARM_LIST:
|
||||
zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent);
|
||||
break;
|
||||
case ZEND_AST_CLOSURE_USES:
|
||||
@ -1967,6 +1968,25 @@ simple_list:
|
||||
}
|
||||
zend_ast_export_stmt(str, ast->child[1], indent + 1);
|
||||
break;
|
||||
case ZEND_AST_MATCH:
|
||||
smart_str_appends(str, "match (");
|
||||
zend_ast_export_ex(str, ast->child[0], 0, indent);
|
||||
smart_str_appends(str, ") {\n");
|
||||
zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
|
||||
zend_ast_export_indent(str, indent);
|
||||
smart_str_appendc(str, '}');
|
||||
break;
|
||||
case ZEND_AST_MATCH_ARM:
|
||||
zend_ast_export_indent(str, indent);
|
||||
if (ast->child[0]) {
|
||||
zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
|
||||
smart_str_appends(str, " => ");
|
||||
} else {
|
||||
smart_str_appends(str, "default => ");
|
||||
}
|
||||
zend_ast_export_ex(str, ast->child[1], 0, 0);
|
||||
smart_str_appends(str, ",\n");
|
||||
break;
|
||||
case ZEND_AST_DECLARE:
|
||||
smart_str_appends(str, "declare(");
|
||||
ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
|
||||
|
@ -63,6 +63,7 @@ enum _zend_ast_kind {
|
||||
ZEND_AST_USE,
|
||||
ZEND_AST_TYPE_UNION,
|
||||
ZEND_AST_ATTRIBUTE_LIST,
|
||||
ZEND_AST_MATCH_ARM_LIST,
|
||||
|
||||
/* 0 child nodes */
|
||||
ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT,
|
||||
@ -141,6 +142,8 @@ enum _zend_ast_kind {
|
||||
ZEND_AST_GROUP_USE,
|
||||
ZEND_AST_CLASS_CONST_GROUP,
|
||||
ZEND_AST_ATTRIBUTE,
|
||||
ZEND_AST_MATCH,
|
||||
ZEND_AST_MATCH_ARM,
|
||||
|
||||
/* 3 child nodes */
|
||||
ZEND_AST_METHOD_CALL = 3 << ZEND_AST_NUM_CHILDREN_SHIFT,
|
||||
|
@ -2113,6 +2113,7 @@ ZEND_API int zend_is_smart_branch(const zend_op *opline) /* {{{ */
|
||||
case ZEND_IS_SMALLER:
|
||||
case ZEND_IS_SMALLER_OR_EQUAL:
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT:
|
||||
case ZEND_ISSET_ISEMPTY_CV:
|
||||
case ZEND_ISSET_ISEMPTY_VAR:
|
||||
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
|
||||
@ -5166,6 +5167,227 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static uint32_t count_match_conds(zend_ast_list *arms)
|
||||
{
|
||||
uint32_t num_conds = 0;
|
||||
|
||||
for (uint32_t i = 0; i < arms->children; i++) {
|
||||
zend_ast *arm_ast = arms->child[i];
|
||||
if (arm_ast->child[0] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
|
||||
num_conds += conds->children;
|
||||
}
|
||||
|
||||
return num_conds;
|
||||
}
|
||||
|
||||
static zend_bool can_match_use_jumptable(zend_ast_list *arms) {
|
||||
for (uint32_t i = 0; i < arms->children; i++) {
|
||||
zend_ast *arm_ast = arms->child[i];
|
||||
if (!arm_ast->child[0]) {
|
||||
/* Skip default arm */
|
||||
continue;
|
||||
}
|
||||
|
||||
zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
|
||||
for (uint32_t j = 0; j < conds->children; j++) {
|
||||
zend_ast **cond_ast = &conds->child[j];
|
||||
|
||||
zend_eval_const_expr(cond_ast);
|
||||
if ((*cond_ast)->kind != ZEND_AST_ZVAL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
zval *cond_zv = zend_ast_get_zval(*cond_ast);
|
||||
if (Z_TYPE_P(cond_zv) != IS_LONG && Z_TYPE_P(cond_zv) != IS_STRING) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void zend_compile_match(znode *result, zend_ast *ast)
|
||||
{
|
||||
zend_ast *expr_ast = ast->child[0];
|
||||
zend_ast_list *arms = zend_ast_get_list(ast->child[1]);
|
||||
zend_bool has_default_arm = 0;
|
||||
uint32_t opnum_match = (uint32_t)-1;
|
||||
|
||||
znode expr_node;
|
||||
zend_compile_expr(&expr_node, expr_ast);
|
||||
|
||||
znode case_node;
|
||||
case_node.op_type = IS_TMP_VAR;
|
||||
case_node.u.op.var = get_temporary_variable();
|
||||
|
||||
uint32_t num_conds = count_match_conds(arms);
|
||||
zend_uchar can_use_jumptable = can_match_use_jumptable(arms);
|
||||
zend_bool uses_jumptable = can_use_jumptable && num_conds >= 2;
|
||||
HashTable *jumptable = NULL;
|
||||
uint32_t *jmpnz_opnums = NULL;
|
||||
|
||||
for (uint32_t i = 0; i < arms->children; ++i) {
|
||||
zend_ast *arm_ast = arms->child[i];
|
||||
|
||||
if (!arm_ast->child[0]) {
|
||||
if (has_default_arm) {
|
||||
CG(zend_lineno) = arm_ast->lineno;
|
||||
zend_error_noreturn(E_COMPILE_ERROR,
|
||||
"Match expressions may only contain one default arm");
|
||||
}
|
||||
has_default_arm = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uses_jumptable) {
|
||||
znode jumptable_op;
|
||||
|
||||
ALLOC_HASHTABLE(jumptable);
|
||||
zend_hash_init(jumptable, num_conds, NULL, NULL, 0);
|
||||
jumptable_op.op_type = IS_CONST;
|
||||
ZVAL_ARR(&jumptable_op.u.constant, jumptable);
|
||||
|
||||
zend_op *opline = zend_emit_op(NULL, ZEND_MATCH, &expr_node, &jumptable_op);
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
|
||||
}
|
||||
opnum_match = opline - CG(active_op_array)->opcodes;
|
||||
} else {
|
||||
jmpnz_opnums = safe_emalloc(sizeof(uint32_t), num_conds, 0);
|
||||
uint32_t cond_count = 0;
|
||||
for (uint32_t i = 0; i < arms->children; ++i) {
|
||||
zend_ast *arm_ast = arms->child[i];
|
||||
|
||||
if (!arm_ast->child[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
|
||||
for (uint32_t j = 0; j < conds->children; j++) {
|
||||
zend_ast *cond_ast = conds->child[j];
|
||||
|
||||
znode cond_node;
|
||||
zend_compile_expr(&cond_node, cond_ast);
|
||||
|
||||
uint32_t opcode = (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) ? ZEND_CASE_STRICT : ZEND_IS_IDENTICAL;
|
||||
zend_op *opline = zend_emit_op(NULL, opcode, &expr_node, &cond_node);
|
||||
SET_NODE(opline->result, &case_node);
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
|
||||
}
|
||||
|
||||
jmpnz_opnums[cond_count] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
|
||||
|
||||
cond_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t opnum_default_jmp = 0;
|
||||
if (!uses_jumptable) {
|
||||
opnum_default_jmp = zend_emit_jump(0);
|
||||
}
|
||||
|
||||
zend_bool is_first_case = 1;
|
||||
uint32_t cond_count = 0;
|
||||
uint32_t *jmp_end_opnums = safe_emalloc(sizeof(uint32_t), arms->children, 0);
|
||||
|
||||
for (uint32_t i = 0; i < arms->children; ++i) {
|
||||
zend_ast *arm_ast = arms->child[i];
|
||||
zend_ast *body_ast = arm_ast->child[1];
|
||||
|
||||
if (arm_ast->child[0] != NULL) {
|
||||
zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);
|
||||
|
||||
for (uint32_t j = 0; j < conds->children; j++) {
|
||||
zend_ast *cond_ast = conds->child[j];
|
||||
|
||||
if (jmpnz_opnums != NULL) {
|
||||
zend_update_jump_target_to_next(jmpnz_opnums[cond_count]);
|
||||
}
|
||||
|
||||
if (jumptable) {
|
||||
zval *cond_zv = zend_ast_get_zval(cond_ast);
|
||||
zval jmp_target;
|
||||
ZVAL_LONG(&jmp_target, get_next_op_number());
|
||||
|
||||
if (Z_TYPE_P(cond_zv) == IS_LONG) {
|
||||
zend_hash_index_add(jumptable, Z_LVAL_P(cond_zv), &jmp_target);
|
||||
} else {
|
||||
ZEND_ASSERT(Z_TYPE_P(cond_zv) == IS_STRING);
|
||||
zend_hash_add(jumptable, Z_STR_P(cond_zv), &jmp_target);
|
||||
}
|
||||
}
|
||||
|
||||
cond_count++;
|
||||
}
|
||||
} else {
|
||||
if (!uses_jumptable) {
|
||||
zend_update_jump_target_to_next(opnum_default_jmp);
|
||||
}
|
||||
|
||||
if (jumptable) {
|
||||
ZEND_ASSERT(opnum_match != (uint32_t)-1);
|
||||
zend_op *opline = &CG(active_op_array)->opcodes[opnum_match];
|
||||
opline->extended_value = get_next_op_number();
|
||||
}
|
||||
}
|
||||
|
||||
znode body_node;
|
||||
zend_compile_expr(&body_node, body_ast);
|
||||
|
||||
if (is_first_case) {
|
||||
zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &body_node, NULL);
|
||||
is_first_case = 0;
|
||||
} else {
|
||||
zend_op *opline_qm_assign = zend_emit_op(NULL, ZEND_QM_ASSIGN, &body_node, NULL);
|
||||
SET_NODE(opline_qm_assign->result, result);
|
||||
}
|
||||
|
||||
jmp_end_opnums[i] = zend_emit_jump(0);
|
||||
}
|
||||
|
||||
// Initialize result in case there is no arm
|
||||
if (arms->children == 0) {
|
||||
result->op_type = IS_CONST;
|
||||
ZVAL_NULL(&result->u.constant);
|
||||
}
|
||||
|
||||
if (!has_default_arm) {
|
||||
if (!uses_jumptable) {
|
||||
zend_update_jump_target_to_next(opnum_default_jmp);
|
||||
}
|
||||
|
||||
if (jumptable) {
|
||||
zend_op *opline = &CG(active_op_array)->opcodes[opnum_match];
|
||||
opline->extended_value = get_next_op_number();
|
||||
}
|
||||
|
||||
zend_emit_op(NULL, ZEND_MATCH_ERROR, &expr_node, NULL);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < arms->children; ++i) {
|
||||
zend_update_jump_target_to_next(jmp_end_opnums[i]);
|
||||
}
|
||||
|
||||
if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) {
|
||||
zend_op *opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
|
||||
opline->extended_value = ZEND_FREE_SWITCH;
|
||||
} else if (expr_node.op_type == IS_CONST) {
|
||||
zval_ptr_dtor_nogc(&expr_node.u.constant);
|
||||
}
|
||||
|
||||
if (jmpnz_opnums != NULL) {
|
||||
efree(jmpnz_opnums);
|
||||
}
|
||||
efree(jmp_end_opnums);
|
||||
}
|
||||
|
||||
void zend_compile_try(zend_ast *ast) /* {{{ */
|
||||
{
|
||||
zend_ast *try_ast = ast->child[0];
|
||||
@ -9176,6 +9398,9 @@ void zend_compile_expr(znode *result, zend_ast *ast) /* {{{ */
|
||||
case ZEND_AST_THROW:
|
||||
zend_compile_throw(result, ast);
|
||||
return;
|
||||
case ZEND_AST_MATCH:
|
||||
zend_compile_match(result, ast);
|
||||
return;
|
||||
default:
|
||||
ZEND_ASSERT(0 /* not supported */);
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ ZEND_API zend_class_entry *zend_ce_argument_count_error;
|
||||
ZEND_API zend_class_entry *zend_ce_value_error;
|
||||
ZEND_API zend_class_entry *zend_ce_arithmetic_error;
|
||||
ZEND_API zend_class_entry *zend_ce_division_by_zero_error;
|
||||
ZEND_API zend_class_entry *zend_ce_unhandled_match_error;
|
||||
|
||||
/* Internal pseudo-exception that is not exposed to userland. */
|
||||
static zend_class_entry zend_ce_unwind_exit;
|
||||
@ -800,6 +801,10 @@ void zend_register_default_exception(void) /* {{{ */
|
||||
zend_ce_division_by_zero_error->create_object = zend_default_exception_new;
|
||||
|
||||
INIT_CLASS_ENTRY(zend_ce_unwind_exit, "UnwindExit", NULL);
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "UnhandledMatchError", NULL);
|
||||
zend_ce_unhandled_match_error = zend_register_internal_class_ex(&ce, zend_ce_error);
|
||||
zend_ce_unhandled_match_error->create_object = zend_default_exception_new;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -35,6 +35,7 @@ extern ZEND_API zend_class_entry *zend_ce_argument_count_error;
|
||||
extern ZEND_API zend_class_entry *zend_ce_value_error;
|
||||
extern ZEND_API zend_class_entry *zend_ce_arithmetic_error;
|
||||
extern ZEND_API zend_class_entry *zend_ce_division_by_zero_error;
|
||||
extern ZEND_API zend_class_entry *zend_ce_unhandled_match_error;
|
||||
|
||||
ZEND_API void zend_exception_set_previous(zend_object *exception, zend_object *add_previous);
|
||||
ZEND_API void zend_exception_save(void);
|
||||
|
@ -130,6 +130,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
|
||||
%token <ident> T_ENDSWITCH "endswitch (T_ENDSWITCH)"
|
||||
%token <ident> T_CASE "case (T_CASE)"
|
||||
%token <ident> T_DEFAULT "default (T_DEFAULT)"
|
||||
%token <ident> T_MATCH "match (T_MATCH)"
|
||||
%token <ident> T_BREAK "break (T_BREAK)"
|
||||
%token <ident> T_CONTINUE "continue (T_CONTINUE)"
|
||||
%token <ident> T_GOTO "goto (T_GOTO)"
|
||||
@ -261,6 +262,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
|
||||
%type <ast> inline_function union_type
|
||||
%type <ast> attributed_statement attributed_class_statement attributed_parameter
|
||||
%type <ast> attribute_decl attribute attributes
|
||||
%type <ast> match match_arm_list non_empty_match_arm_list match_arm match_arm_cond_list
|
||||
|
||||
%type <num> returns_ref function fn is_reference is_variadic variable_modifiers
|
||||
%type <num> method_modifiers non_empty_member_modifiers member_modifier optional_visibility_modifier
|
||||
@ -284,7 +286,7 @@ reserved_non_modifiers:
|
||||
| T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
|
||||
| T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK
|
||||
| T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
|
||||
| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_FN
|
||||
| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_FN | T_MATCH
|
||||
;
|
||||
|
||||
semi_reserved:
|
||||
@ -624,6 +626,34 @@ case_separator:
|
||||
;
|
||||
|
||||
|
||||
match:
|
||||
T_MATCH '(' expr ')' '{' match_arm_list '}'
|
||||
{ $$ = zend_ast_create(ZEND_AST_MATCH, $3, $6); };
|
||||
;
|
||||
|
||||
match_arm_list:
|
||||
%empty { $$ = zend_ast_create_list(0, ZEND_AST_MATCH_ARM_LIST); }
|
||||
| non_empty_match_arm_list possible_comma { $$ = $1; }
|
||||
;
|
||||
|
||||
non_empty_match_arm_list:
|
||||
match_arm { $$ = zend_ast_create_list(1, ZEND_AST_MATCH_ARM_LIST, $1); }
|
||||
| non_empty_match_arm_list ',' match_arm { $$ = zend_ast_list_add($1, $3); }
|
||||
;
|
||||
|
||||
match_arm:
|
||||
match_arm_cond_list possible_comma T_DOUBLE_ARROW expr
|
||||
{ $$ = zend_ast_create(ZEND_AST_MATCH_ARM, $1, $4); }
|
||||
| T_DEFAULT possible_comma T_DOUBLE_ARROW expr
|
||||
{ $$ = zend_ast_create(ZEND_AST_MATCH_ARM, NULL, $4); }
|
||||
;
|
||||
|
||||
match_arm_cond_list:
|
||||
expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); }
|
||||
| match_arm_cond_list ',' expr { $$ = zend_ast_list_add($1, $3); }
|
||||
;
|
||||
|
||||
|
||||
while_statement:
|
||||
statement { $$ = $1; }
|
||||
| ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; }
|
||||
@ -1079,6 +1109,7 @@ expr:
|
||||
| T_STATIC inline_function { $$ = $2; ((zend_ast_decl *) $$)->flags |= ZEND_ACC_STATIC; }
|
||||
| attributes T_STATIC inline_function
|
||||
{ $$ = zend_ast_with_attributes($3, $1); ((zend_ast_decl *) $$)->flags |= ZEND_ACC_STATIC; }
|
||||
| match { $$ = $1; }
|
||||
;
|
||||
|
||||
|
||||
|
@ -1512,6 +1512,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
RETURN_TOKEN_WITH_IDENT(T_SWITCH);
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"match" {
|
||||
RETURN_TOKEN_WITH_IDENT(T_MATCH);
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"endswitch" {
|
||||
RETURN_TOKEN_WITH_IDENT(T_ENDSWITCH);
|
||||
}
|
||||
|
@ -763,7 +763,9 @@ static zend_bool keeps_op1_alive(zend_op *opline) {
|
||||
/* These opcodes don't consume their OP1 operand,
|
||||
* it is later freed by something else. */
|
||||
if (opline->opcode == ZEND_CASE
|
||||
|| opline->opcode == ZEND_CASE_STRICT
|
||||
|| opline->opcode == ZEND_SWITCH_LONG
|
||||
|| opline->opcode == ZEND_MATCH
|
||||
|| opline->opcode == ZEND_FETCH_LIST_R
|
||||
|| opline->opcode == ZEND_COPY_TMP) {
|
||||
return 1;
|
||||
@ -1039,6 +1041,7 @@ ZEND_API int pass_two(zend_op_array *op_array)
|
||||
break;
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
{
|
||||
/* absolute indexes to relative offsets */
|
||||
HashTable *jumptable = Z_ARRVAL_P(CT_CONSTANT(opline->op2));
|
||||
@ -1108,6 +1111,7 @@ ZEND_API binary_op_type get_binary_op(int opcode)
|
||||
case ZEND_CONCAT:
|
||||
return (binary_op_type) concat_function;
|
||||
case ZEND_IS_IDENTICAL:
|
||||
case ZEND_CASE_STRICT:
|
||||
return (binary_op_type) is_identical_function;
|
||||
case ZEND_IS_NOT_IDENTICAL:
|
||||
return (binary_op_type) is_not_identical_function;
|
||||
|
@ -457,6 +457,20 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(196, ZEND_CASE_STRICT, TMP|VAR, CONST|TMP|VAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
zend_bool result;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
|
||||
op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
|
||||
result = fast_is_identical_function(op1, op2);
|
||||
FREE_OP2();
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE))
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -8394,6 +8408,58 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(188, ZEND_SWITCH_STRING, CONST|TMPVARCV, CONST,
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_COLD_CONSTCONST_HANDLER(195, ZEND_MATCH, CONST|TMPVARCV, CONST, JMP_ADDR)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op, *jump_zv;
|
||||
HashTable *jumptable;
|
||||
|
||||
op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
|
||||
jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
|
||||
|
||||
ZEND_VM_C_LABEL(match_try_again):
|
||||
if (Z_TYPE_P(op) == IS_LONG) {
|
||||
jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op));
|
||||
} else if (Z_TYPE_P(op) == IS_STRING) {
|
||||
jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), OP1_TYPE == IS_CONST);
|
||||
} else if (Z_TYPE_P(op) == IS_REFERENCE) {
|
||||
op = Z_REFVAL_P(op);
|
||||
ZEND_VM_C_GOTO(match_try_again);
|
||||
} else {
|
||||
if (UNEXPECTED((OP1_TYPE & IS_CV) && Z_TYPE_P(op) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
op = ZVAL_UNDEFINED_OP1();
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
ZEND_VM_C_GOTO(match_try_again);
|
||||
}
|
||||
|
||||
ZEND_VM_C_GOTO(default_branch);
|
||||
}
|
||||
|
||||
if (jump_zv != NULL) {
|
||||
ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
|
||||
ZEND_VM_CONTINUE();
|
||||
} else {
|
||||
ZEND_VM_C_LABEL(default_branch):
|
||||
/* default */
|
||||
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
|
||||
ZEND_VM_CONTINUE();
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_COLD_CONST_HANDLER(197, ZEND_MATCH_ERROR, CONST|TMPVARCV, UNUSED)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
|
||||
zend_throw_exception_ex(zend_ce_unhandled_match_error, 0, "Unhandled match value of type %s", zend_zval_type_name(op));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
@ -6496,6 +6496,47 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPE
|
||||
}
|
||||
}
|
||||
|
||||
static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op, *jump_zv;
|
||||
HashTable *jumptable;
|
||||
|
||||
op = RT_CONSTANT(opline, opline->op1);
|
||||
jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
|
||||
|
||||
match_try_again:
|
||||
if (Z_TYPE_P(op) == IS_LONG) {
|
||||
jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op));
|
||||
} else if (Z_TYPE_P(op) == IS_STRING) {
|
||||
jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), IS_CONST == IS_CONST);
|
||||
} else if (Z_TYPE_P(op) == IS_REFERENCE) {
|
||||
op = Z_REFVAL_P(op);
|
||||
goto match_try_again;
|
||||
} else {
|
||||
if (UNEXPECTED((IS_CONST & IS_CV) && Z_TYPE_P(op) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
op = ZVAL_UNDEFINED_OP1();
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
goto match_try_again;
|
||||
}
|
||||
|
||||
goto default_branch;
|
||||
}
|
||||
|
||||
if (jump_zv != NULL) {
|
||||
ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
|
||||
ZEND_VM_CONTINUE();
|
||||
} else {
|
||||
default_branch:
|
||||
/* default */
|
||||
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
|
||||
ZEND_VM_CONTINUE();
|
||||
}
|
||||
}
|
||||
|
||||
static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -9237,6 +9278,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE
|
||||
ZEND_VM_RETURN();
|
||||
}
|
||||
|
||||
static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op = RT_CONSTANT(opline, opline->op1);
|
||||
zend_throw_exception_ex(zend_ce_unhandled_match_error, 0, "Unhandled match value of type %s", zend_zval_type_name(op));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -11350,6 +11402,47 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_TMPVARCV_CO
|
||||
}
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op, *jump_zv;
|
||||
HashTable *jumptable;
|
||||
|
||||
op = EX_VAR(opline->op1.var);
|
||||
jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
|
||||
|
||||
match_try_again:
|
||||
if (Z_TYPE_P(op) == IS_LONG) {
|
||||
jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op));
|
||||
} else if (Z_TYPE_P(op) == IS_STRING) {
|
||||
jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST);
|
||||
} else if (Z_TYPE_P(op) == IS_REFERENCE) {
|
||||
op = Z_REFVAL_P(op);
|
||||
goto match_try_again;
|
||||
} else {
|
||||
if (UNEXPECTED(((IS_TMP_VAR|IS_VAR|IS_CV) & IS_CV) && Z_TYPE_P(op) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
op = ZVAL_UNDEFINED_OP1();
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
goto match_try_again;
|
||||
}
|
||||
|
||||
goto default_branch;
|
||||
}
|
||||
|
||||
if (jump_zv != NULL) {
|
||||
ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
|
||||
ZEND_VM_CONTINUE();
|
||||
} else {
|
||||
default_branch:
|
||||
/* default */
|
||||
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
|
||||
ZEND_VM_CONTINUE();
|
||||
}
|
||||
}
|
||||
|
||||
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -12666,6 +12759,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMP
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op = EX_VAR(opline->op1.var);
|
||||
zend_throw_exception_ex(zend_ce_unhandled_match_error, 0, "Unhandled match value of type %s", zend_zval_type_name(op));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -17922,6 +18026,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
zend_bool result;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC);
|
||||
op2 = RT_CONSTANT(opline, opline->op2);
|
||||
result = fast_is_identical_function(op1, op2);
|
||||
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -18723,6 +18841,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
zend_bool result;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC);
|
||||
op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC);
|
||||
result = fast_is_identical_function(op1, op2);
|
||||
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -18738,6 +18870,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
zend_bool result;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC);
|
||||
op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC);
|
||||
result = fast_is_identical_function(op1, op2);
|
||||
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
#if 0
|
||||
@ -19073,6 +19219,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDL
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
zend_bool result;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC);
|
||||
op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);
|
||||
result = fast_is_identical_function(op1, op2);
|
||||
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
#if 0
|
||||
@ -20943,6 +21103,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
zend_bool result;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC);
|
||||
op2 = RT_CONSTANT(opline, opline->op2);
|
||||
result = fast_is_identical_function(op1, op2);
|
||||
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -25349,6 +25523,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
zend_bool result;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC);
|
||||
op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC);
|
||||
result = fast_is_identical_function(op1, op2);
|
||||
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -25419,6 +25607,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
zend_bool result;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC);
|
||||
op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC);
|
||||
result = fast_is_identical_function(op1, op2);
|
||||
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -26657,6 +26859,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDL
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
zend_bool result;
|
||||
|
||||
SAVE_OPLINE();
|
||||
op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC);
|
||||
op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);
|
||||
result = fast_is_identical_function(op1, op2);
|
||||
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -50838,6 +51054,41 @@ ZEND_API void execute_ex(zend_execute_data *ex)
|
||||
(void*)&&ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_LABEL,
|
||||
(void*)&&ZEND_MATCH_SPEC_CONST_CONST_LABEL,
|
||||
(void*)&&ZEND_MATCH_SPEC_TMPVARCV_CONST_LABEL,
|
||||
(void*)&&ZEND_MATCH_SPEC_TMPVARCV_CONST_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_MATCH_SPEC_TMPVARCV_CONST_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_CASE_STRICT_SPEC_TMP_CONST_LABEL,
|
||||
(void*)&&ZEND_CASE_STRICT_SPEC_TMP_TMP_LABEL,
|
||||
(void*)&&ZEND_CASE_STRICT_SPEC_TMP_VAR_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_CASE_STRICT_SPEC_TMP_CV_LABEL,
|
||||
(void*)&&ZEND_CASE_STRICT_SPEC_VAR_CONST_LABEL,
|
||||
(void*)&&ZEND_CASE_STRICT_SPEC_VAR_TMP_LABEL,
|
||||
(void*)&&ZEND_CASE_STRICT_SPEC_VAR_VAR_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_CASE_STRICT_SPEC_VAR_CV_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_LABEL,
|
||||
(void*)&&ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_LABEL,
|
||||
(void*)&&ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_LABEL,
|
||||
(void*)&&ZEND_RECV_NOTYPE_SPEC_LABEL,
|
||||
(void*)&&ZEND_JMP_FORWARD_SPEC_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
@ -52490,6 +52741,10 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_SWITCH_STRING_SPEC_CONST_CONST)
|
||||
ZEND_SWITCH_STRING_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_MATCH_SPEC_CONST_CONST):
|
||||
VM_TRACE(ZEND_MATCH_SPEC_CONST_CONST)
|
||||
ZEND_MATCH_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_IN_ARRAY_SPEC_CONST_CONST):
|
||||
VM_TRACE(ZEND_IN_ARRAY_SPEC_CONST_CONST)
|
||||
ZEND_IN_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -52750,6 +53005,10 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_YIELD_SPEC_CONST_UNUSED)
|
||||
ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_MATCH_ERROR_SPEC_CONST_UNUSED):
|
||||
VM_TRACE(ZEND_MATCH_ERROR_SPEC_CONST_UNUSED)
|
||||
ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_COUNT_SPEC_CONST_UNUSED):
|
||||
VM_TRACE(ZEND_COUNT_SPEC_CONST_UNUSED)
|
||||
ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -52938,6 +53197,10 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST)
|
||||
ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_MATCH_SPEC_TMPVARCV_CONST):
|
||||
VM_TRACE(ZEND_MATCH_SPEC_TMPVARCV_CONST)
|
||||
ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST):
|
||||
VM_TRACE(ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST)
|
||||
ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -53266,6 +53529,10 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR)
|
||||
ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED):
|
||||
VM_TRACE(ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED)
|
||||
ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV):
|
||||
VM_TRACE(ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV)
|
||||
ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -53755,6 +54022,10 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_IS_IDENTICAL_SPEC_TMP_CONST)
|
||||
ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_CONST):
|
||||
VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_CONST)
|
||||
ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST):
|
||||
VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST)
|
||||
ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -53823,10 +54094,18 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_IS_IDENTICAL_SPEC_TMP_TMP)
|
||||
ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_TMP):
|
||||
VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_TMP)
|
||||
ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP):
|
||||
VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP)
|
||||
ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_VAR):
|
||||
VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_VAR)
|
||||
ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED):
|
||||
VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED)
|
||||
ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -53851,6 +54130,10 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_GET_TYPE_SPEC_TMP_UNUSED)
|
||||
ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_CV):
|
||||
VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_CV)
|
||||
ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV):
|
||||
VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV)
|
||||
ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -54068,6 +54351,10 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_IS_IDENTICAL_SPEC_VAR_CONST)
|
||||
ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CASE_STRICT_SPEC_VAR_CONST):
|
||||
VM_TRACE(ZEND_CASE_STRICT_SPEC_VAR_CONST)
|
||||
ZEND_CASE_STRICT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST):
|
||||
VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST)
|
||||
ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -54332,6 +54619,10 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_IS_IDENTICAL_SPEC_VAR_TMP)
|
||||
ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CASE_STRICT_SPEC_VAR_TMP):
|
||||
VM_TRACE(ZEND_CASE_STRICT_SPEC_VAR_TMP)
|
||||
ZEND_CASE_STRICT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP):
|
||||
VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP)
|
||||
ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -54348,6 +54639,10 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_IS_IDENTICAL_SPEC_VAR_VAR)
|
||||
ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CASE_STRICT_SPEC_VAR_VAR):
|
||||
VM_TRACE(ZEND_CASE_STRICT_SPEC_VAR_VAR)
|
||||
ZEND_CASE_STRICT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR):
|
||||
VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR)
|
||||
ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -54432,6 +54727,10 @@ zend_leave_helper_SPEC_LABEL:
|
||||
VM_TRACE(ZEND_GET_TYPE_SPEC_VAR_UNUSED)
|
||||
ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CASE_STRICT_SPEC_VAR_CV):
|
||||
VM_TRACE(ZEND_CASE_STRICT_SPEC_VAR_CV)
|
||||
ZEND_CASE_STRICT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV):
|
||||
VM_TRACE(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV)
|
||||
ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@ -58382,6 +58681,41 @@ void zend_vm_init(void)
|
||||
ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_HANDLER,
|
||||
ZEND_MATCH_SPEC_CONST_CONST_HANDLER,
|
||||
ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER,
|
||||
ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER,
|
||||
ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDLER,
|
||||
ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER,
|
||||
ZEND_CASE_STRICT_SPEC_VAR_CONST_HANDLER,
|
||||
ZEND_CASE_STRICT_SPEC_VAR_TMP_HANDLER,
|
||||
ZEND_CASE_STRICT_SPEC_VAR_VAR_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_CASE_STRICT_SPEC_VAR_CV_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_HANDLER,
|
||||
ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER,
|
||||
ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER,
|
||||
ZEND_RECV_NOTYPE_SPEC_HANDLER,
|
||||
ZEND_JMP_FORWARD_SPEC_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
@ -59483,7 +59817,10 @@ void zend_vm_init(void)
|
||||
2284,
|
||||
2285 | SPEC_RULE_OP1,
|
||||
2290 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
|
||||
3218
|
||||
2315 | SPEC_RULE_OP1,
|
||||
2320 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
|
||||
2345 | SPEC_RULE_OP1,
|
||||
3253
|
||||
};
|
||||
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
|
||||
zend_opcode_handler_funcs = labels;
|
||||
@ -59648,7 +59985,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2317 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2352 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
if (op->op1_type < op->op2_type) {
|
||||
zend_swap_operands(op);
|
||||
}
|
||||
@ -59656,7 +59993,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2342 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2377 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
if (op->op1_type < op->op2_type) {
|
||||
zend_swap_operands(op);
|
||||
}
|
||||
@ -59664,7 +60001,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2367 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2402 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
if (op->op1_type < op->op2_type) {
|
||||
zend_swap_operands(op);
|
||||
}
|
||||
@ -59675,17 +60012,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2392 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
spec = 2427 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
} else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2417 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
spec = 2452 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2442 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
spec = 2477 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
}
|
||||
break;
|
||||
case ZEND_MUL:
|
||||
@ -59696,17 +60033,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2467 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2502 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
} else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2492 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2527 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2517 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2552 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_IDENTICAL:
|
||||
@ -59717,14 +60054,14 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2542 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2577 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2617 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2652 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
} else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) {
|
||||
spec = 2842 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2877 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_NOT_IDENTICAL:
|
||||
@ -59735,14 +60072,14 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2692 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2727 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2767 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2802 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
} else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) {
|
||||
spec = 2847 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2882 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_EQUAL:
|
||||
@ -59753,12 +60090,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2542 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2577 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2617 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2652 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_NOT_EQUAL:
|
||||
@ -59769,12 +60106,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2692 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2727 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2767 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2802 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_SMALLER:
|
||||
@ -59782,12 +60119,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2852 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
spec = 2887 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 2927 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
spec = 2962 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_SMALLER_OR_EQUAL:
|
||||
@ -59795,74 +60132,74 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 3002 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
spec = 3037 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 3077 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
spec = 3112 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
}
|
||||
break;
|
||||
case ZEND_QM_ASSIGN:
|
||||
if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3164 | SPEC_RULE_OP1;
|
||||
spec = 3199 | SPEC_RULE_OP1;
|
||||
} else if (op1_info == MAY_BE_DOUBLE) {
|
||||
spec = 3169 | SPEC_RULE_OP1;
|
||||
spec = 3204 | SPEC_RULE_OP1;
|
||||
} else if ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) {
|
||||
spec = 3174 | SPEC_RULE_OP1;
|
||||
spec = 3209 | SPEC_RULE_OP1;
|
||||
}
|
||||
break;
|
||||
case ZEND_PRE_INC:
|
||||
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
|
||||
spec = 3152 | SPEC_RULE_RETVAL;
|
||||
spec = 3187 | SPEC_RULE_RETVAL;
|
||||
} else if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3154 | SPEC_RULE_RETVAL;
|
||||
spec = 3189 | SPEC_RULE_RETVAL;
|
||||
}
|
||||
break;
|
||||
case ZEND_PRE_DEC:
|
||||
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
|
||||
spec = 3156 | SPEC_RULE_RETVAL;
|
||||
spec = 3191 | SPEC_RULE_RETVAL;
|
||||
} else if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3158 | SPEC_RULE_RETVAL;
|
||||
spec = 3193 | SPEC_RULE_RETVAL;
|
||||
}
|
||||
break;
|
||||
case ZEND_POST_INC:
|
||||
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
|
||||
spec = 3160;
|
||||
spec = 3195;
|
||||
} else if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3161;
|
||||
spec = 3196;
|
||||
}
|
||||
break;
|
||||
case ZEND_POST_DEC:
|
||||
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
|
||||
spec = 3162;
|
||||
spec = 3197;
|
||||
} else if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3163;
|
||||
spec = 3198;
|
||||
}
|
||||
break;
|
||||
case ZEND_JMP:
|
||||
if (OP_JMP_ADDR(op, op->op1) > op) {
|
||||
spec = 2316;
|
||||
spec = 2351;
|
||||
}
|
||||
break;
|
||||
case ZEND_RECV:
|
||||
if (op->op2.num == MAY_BE_ANY) {
|
||||
spec = 2315;
|
||||
spec = 2350;
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAL:
|
||||
if (op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) {
|
||||
spec = 3214;
|
||||
spec = 3249;
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAR_EX:
|
||||
if (op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
|
||||
spec = 3209 | SPEC_RULE_OP1;
|
||||
spec = 3244 | SPEC_RULE_OP1;
|
||||
}
|
||||
break;
|
||||
case ZEND_FE_FETCH_R:
|
||||
if (op->op2_type == IS_CV && (op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) {
|
||||
spec = 3216 | SPEC_RULE_RETVAL;
|
||||
spec = 3251 | SPEC_RULE_RETVAL;
|
||||
}
|
||||
break;
|
||||
case ZEND_FETCH_DIM_R:
|
||||
@ -59870,17 +60207,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
|
||||
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
spec = 3179 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
spec = 3214 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAL_EX:
|
||||
if (op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) {
|
||||
spec = 3215;
|
||||
spec = 3250;
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAR:
|
||||
if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
|
||||
spec = 3204 | SPEC_RULE_OP1;
|
||||
spec = 3239 | SPEC_RULE_OP1;
|
||||
}
|
||||
break;
|
||||
case ZEND_BW_OR:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@
|
||||
#include <zend.h>
|
||||
#include <zend_vm_opcodes.h>
|
||||
|
||||
static const char *zend_vm_opcodes_names[195] = {
|
||||
static const char *zend_vm_opcodes_names[198] = {
|
||||
"ZEND_NOP",
|
||||
"ZEND_ADD",
|
||||
"ZEND_SUB",
|
||||
@ -218,9 +218,12 @@ static const char *zend_vm_opcodes_names[195] = {
|
||||
"ZEND_GET_CALLED_CLASS",
|
||||
"ZEND_GET_TYPE",
|
||||
"ZEND_ARRAY_KEY_EXISTS",
|
||||
"ZEND_MATCH",
|
||||
"ZEND_CASE_STRICT",
|
||||
"ZEND_MATCH_ERROR",
|
||||
};
|
||||
|
||||
static uint32_t zend_vm_opcodes_flags[195] = {
|
||||
static uint32_t zend_vm_opcodes_flags[198] = {
|
||||
0x00000000,
|
||||
0x00000b0b,
|
||||
0x00000b0b,
|
||||
@ -416,6 +419,9 @@ static uint32_t zend_vm_opcodes_flags[195] = {
|
||||
0x00000101,
|
||||
0x00000103,
|
||||
0x00000707,
|
||||
0x0300030b,
|
||||
0x00000301,
|
||||
0x0000010b,
|
||||
};
|
||||
|
||||
ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(zend_uchar opcode) {
|
||||
|
@ -271,7 +271,10 @@ END_EXTERN_C()
|
||||
#define ZEND_GET_CALLED_CLASS 192
|
||||
#define ZEND_GET_TYPE 193
|
||||
#define ZEND_ARRAY_KEY_EXISTS 194
|
||||
#define ZEND_MATCH 195
|
||||
#define ZEND_CASE_STRICT 196
|
||||
#define ZEND_MATCH_ERROR 197
|
||||
|
||||
#define ZEND_VM_LAST_OPCODE 194
|
||||
#define ZEND_VM_LAST_OPCODE 197
|
||||
|
||||
#endif
|
||||
|
@ -115,6 +115,10 @@ static int get_const_switch_target(zend_cfg *cfg, zend_op_array *op_array, zend_
|
||||
/* fallback to next block */
|
||||
return block->successors[block->successors_count - 1];
|
||||
}
|
||||
if (opline->opcode == ZEND_MATCH && Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_STRING) {
|
||||
/* always jump to the default arm */
|
||||
return block->successors[block->successors_count - 1];
|
||||
}
|
||||
if (Z_TYPE_P(val) == IS_LONG) {
|
||||
zv = zend_hash_index_find(jumptable, Z_LVAL_P(val));
|
||||
} else {
|
||||
@ -123,7 +127,7 @@ static int get_const_switch_target(zend_cfg *cfg, zend_op_array *op_array, zend_
|
||||
}
|
||||
if (!zv) {
|
||||
/* default */
|
||||
return block->successors[block->successors_count - 2];
|
||||
return block->successors[block->successors_count - (opline->opcode == ZEND_MATCH ? 1 : 2)];
|
||||
}
|
||||
return cfg->map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv))];
|
||||
}
|
||||
@ -369,6 +373,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
|
||||
/* SWITCH variable will be deleted later by FREE, so we can't optimize it */
|
||||
Tsource[VAR_NUM(opline->op1.var)] = NULL;
|
||||
@ -387,6 +392,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
break;
|
||||
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT:
|
||||
case ZEND_COPY_TMP:
|
||||
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
|
||||
/* Variable will be deleted later by FREE, so we can't optimize it */
|
||||
@ -1046,11 +1052,12 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op
|
||||
break;
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
{
|
||||
HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
|
||||
zval *zv;
|
||||
uint32_t s = 0;
|
||||
ZEND_ASSERT(b->successors_count == 2 + zend_hash_num_elements(jumptable));
|
||||
ZEND_ASSERT(b->successors_count == (opline->opcode == ZEND_MATCH ? 1 : 2) + zend_hash_num_elements(jumptable));
|
||||
|
||||
ZEND_HASH_FOREACH_VAL(jumptable, zv) {
|
||||
Z_LVAL_P(zv) = ZEND_OPLINE_TO_OFFSET(opline, new_opcodes + blocks[b->successors[s++]].start);
|
||||
|
@ -106,6 +106,7 @@ static inline zend_bool may_have_side_effects(
|
||||
case ZEND_IS_SMALLER:
|
||||
case ZEND_IS_SMALLER_OR_EQUAL:
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT:
|
||||
case ZEND_CAST:
|
||||
case ZEND_ROPE_INIT:
|
||||
case ZEND_ROPE_ADD:
|
||||
@ -146,6 +147,7 @@ static inline zend_bool may_have_side_effects(
|
||||
case ZEND_ECHO:
|
||||
case ZEND_INCLUDE_OR_EVAL:
|
||||
case ZEND_THROW:
|
||||
case ZEND_MATCH_ERROR:
|
||||
case ZEND_EXT_STMT:
|
||||
case ZEND_EXT_FCALL_BEGIN:
|
||||
case ZEND_EXT_FCALL_END:
|
||||
@ -391,7 +393,8 @@ static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
|
||||
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR))&& !is_var_dead(ctx, ssa_op->op1_use)) {
|
||||
if (!try_remove_var_def(ctx, ssa_op->op1_use, ssa_op->op1_use_chain, opline)) {
|
||||
if (ssa->var_info[ssa_op->op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)
|
||||
&& opline->opcode != ZEND_CASE) {
|
||||
&& opline->opcode != ZEND_CASE
|
||||
&& opline->opcode != ZEND_CASE_STRICT) {
|
||||
free_var = ssa_op->op1_use;
|
||||
free_var_type = opline->op1_type;
|
||||
}
|
||||
|
@ -641,6 +641,7 @@ static void zend_ssa_replace_control_link(zend_op_array *op_array, zend_ssa *ssa
|
||||
break;
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
{
|
||||
HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
|
||||
zval *zv;
|
||||
@ -895,48 +896,29 @@ optimize_jmpnz:
|
||||
break;
|
||||
}
|
||||
case ZEND_SWITCH_LONG:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
|
||||
if (Z_TYPE_P(zv) != IS_LONG) {
|
||||
removed_ops++;
|
||||
MAKE_NOP(opline);
|
||||
opline->extended_value = 0;
|
||||
take_successor_ex(ssa, block_num, block, block->successors[0]);
|
||||
goto optimize_nop;
|
||||
} else {
|
||||
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
|
||||
zval *jmp_zv = zend_hash_index_find(jmptable, Z_LVAL_P(zv));
|
||||
uint32_t target;
|
||||
|
||||
if (jmp_zv) {
|
||||
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv));
|
||||
} else {
|
||||
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
|
||||
}
|
||||
opline->opcode = ZEND_JMP;
|
||||
opline->extended_value = 0;
|
||||
SET_UNUSED(opline->op1);
|
||||
ZEND_SET_OP_JMP_ADDR(opline, opline->op1, op_array->opcodes + target);
|
||||
SET_UNUSED(opline->op2);
|
||||
take_successor_ex(ssa, block_num, block, ssa->cfg.map[target]);
|
||||
goto optimize_jmp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
|
||||
if (Z_TYPE_P(zv) != IS_STRING) {
|
||||
zend_uchar type = Z_TYPE_P(zv);
|
||||
zend_bool correct_type =
|
||||
(opline->opcode == ZEND_SWITCH_LONG && type == IS_LONG)
|
||||
|| (opline->opcode == ZEND_SWITCH_STRING && type == IS_STRING)
|
||||
|| (opline->opcode == ZEND_MATCH && (type == IS_LONG || type == IS_STRING));
|
||||
|
||||
if (!correct_type) {
|
||||
removed_ops++;
|
||||
MAKE_NOP(opline);
|
||||
opline->extended_value = 0;
|
||||
take_successor_ex(ssa, block_num, block, block->successors[0]);
|
||||
take_successor_ex(ssa, block_num, block, block->successors[block->successors_count - 1]);
|
||||
goto optimize_nop;
|
||||
} else {
|
||||
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
|
||||
zval *jmp_zv = zend_hash_find(jmptable, Z_STR_P(zv));
|
||||
uint32_t target;
|
||||
zval *jmp_zv = type == IS_LONG
|
||||
? zend_hash_index_find(jmptable, Z_LVAL_P(zv))
|
||||
: zend_hash_find(jmptable, Z_STR_P(zv));
|
||||
|
||||
uint32_t target;
|
||||
if (jmp_zv) {
|
||||
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv));
|
||||
} else {
|
||||
|
@ -82,6 +82,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
case ZEND_BOOL_XOR:
|
||||
case ZEND_SPACESHIP:
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT:
|
||||
if (opline->op1_type == IS_CONST &&
|
||||
opline->op2_type == IS_CONST) {
|
||||
/* binary operation with constant operands */
|
||||
@ -663,6 +664,7 @@ constant_binary_op:
|
||||
case ZEND_GENERATOR_RETURN:
|
||||
case ZEND_EXIT:
|
||||
case ZEND_THROW:
|
||||
case ZEND_MATCH_ERROR:
|
||||
case ZEND_CATCH:
|
||||
case ZEND_FAST_CALL:
|
||||
case ZEND_FAST_RET:
|
||||
|
@ -300,10 +300,15 @@ static zend_bool try_replace_op1(
|
||||
switch (opline->opcode) {
|
||||
case ZEND_CASE:
|
||||
opline->opcode = ZEND_IS_EQUAL;
|
||||
/* break missing intentionally */
|
||||
goto replace_op1_simple;
|
||||
case ZEND_CASE_STRICT:
|
||||
opline->opcode = ZEND_IS_IDENTICAL;
|
||||
goto replace_op1_simple;
|
||||
case ZEND_FETCH_LIST_R:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_MATCH:
|
||||
replace_op1_simple:
|
||||
if (Z_TYPE(zv) == IS_STRING) {
|
||||
zend_string_hash_val(Z_STR(zv));
|
||||
}
|
||||
@ -1460,6 +1465,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
|
||||
case ZEND_BW_XOR:
|
||||
case ZEND_BOOL_XOR:
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT:
|
||||
SKIP_IF_TOP(op1);
|
||||
SKIP_IF_TOP(op2);
|
||||
|
||||
@ -1986,29 +1992,23 @@ static void sccp_mark_feasible_successors(
|
||||
s = zend_hash_num_elements(Z_ARR_P(op1)) != 0;
|
||||
break;
|
||||
case ZEND_SWITCH_LONG:
|
||||
if (Z_TYPE_P(op1) == IS_LONG) {
|
||||
zend_op_array *op_array = scdf->op_array;
|
||||
zend_ssa *ssa = scdf->ssa;
|
||||
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
|
||||
zval *jmp_zv = zend_hash_index_find(jmptable, Z_LVAL_P(op1));
|
||||
int target;
|
||||
|
||||
if (jmp_zv) {
|
||||
target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv))];
|
||||
} else {
|
||||
target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
|
||||
}
|
||||
scdf_mark_edge_feasible(scdf, block_num, target);
|
||||
return;
|
||||
}
|
||||
s = 0;
|
||||
break;
|
||||
case ZEND_SWITCH_STRING:
|
||||
if (Z_TYPE_P(op1) == IS_STRING) {
|
||||
case ZEND_MATCH:
|
||||
{
|
||||
zend_bool strict_comparison = opline->opcode == ZEND_MATCH;
|
||||
zend_uchar type = Z_TYPE_P(op1);
|
||||
zend_bool correct_type =
|
||||
(opline->opcode == ZEND_SWITCH_LONG && type == IS_LONG)
|
||||
|| (opline->opcode == ZEND_SWITCH_STRING && type == IS_STRING)
|
||||
|| (opline->opcode == ZEND_MATCH && (type == IS_LONG || type == IS_STRING));
|
||||
|
||||
if (correct_type) {
|
||||
zend_op_array *op_array = scdf->op_array;
|
||||
zend_ssa *ssa = scdf->ssa;
|
||||
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
|
||||
zval *jmp_zv = zend_hash_find(jmptable, Z_STR_P(op1));
|
||||
zval *jmp_zv = type == IS_LONG
|
||||
? zend_hash_index_find(jmptable, Z_LVAL_P(op1))
|
||||
: zend_hash_find(jmptable, Z_STR_P(op1));
|
||||
int target;
|
||||
|
||||
if (jmp_zv) {
|
||||
@ -2018,9 +2018,16 @@ static void sccp_mark_feasible_successors(
|
||||
}
|
||||
scdf_mark_edge_feasible(scdf, block_num, target);
|
||||
return;
|
||||
} else if (strict_comparison) {
|
||||
zend_op_array *op_array = scdf->op_array;
|
||||
zend_ssa *ssa = scdf->ssa;
|
||||
int target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
|
||||
scdf_mark_edge_feasible(scdf, block_num, target);
|
||||
return;
|
||||
}
|
||||
s = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
for (s = 0; s < block->successors_count; s++) {
|
||||
scdf_mark_edge_feasible(scdf, block_num, block->successors[s]);
|
||||
|
@ -73,7 +73,11 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc
|
||||
succ->flags |= ZEND_BB_FOLLOW;
|
||||
}
|
||||
} else {
|
||||
ZEND_ASSERT(opcode == ZEND_SWITCH_LONG || opcode == ZEND_SWITCH_STRING);
|
||||
ZEND_ASSERT(
|
||||
opcode == ZEND_SWITCH_LONG
|
||||
|| opcode == ZEND_SWITCH_STRING
|
||||
|| opcode == ZEND_MATCH
|
||||
);
|
||||
if (i == b->successors_count - 1) {
|
||||
succ->flags |= ZEND_BB_FOLLOW | ZEND_BB_TARGET;
|
||||
} else {
|
||||
@ -296,6 +300,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
|
||||
case ZEND_RETURN_BY_REF:
|
||||
case ZEND_GENERATOR_RETURN:
|
||||
case ZEND_EXIT:
|
||||
case ZEND_MATCH_ERROR:
|
||||
if (i + 1 < op_array->last) {
|
||||
BB_START(i + 1);
|
||||
}
|
||||
@ -391,6 +396,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
|
||||
break;
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
{
|
||||
HashTable *jumptable = Z_ARRVAL_P(CRT_CONSTANT(opline->op2));
|
||||
zval *zv;
|
||||
@ -507,6 +513,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
|
||||
case ZEND_GENERATOR_RETURN:
|
||||
case ZEND_EXIT:
|
||||
case ZEND_THROW:
|
||||
case ZEND_MATCH_ERROR:
|
||||
break;
|
||||
case ZEND_JMP:
|
||||
block->successors_count = 1;
|
||||
@ -557,12 +564,13 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
|
||||
break;
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
{
|
||||
HashTable *jumptable = Z_ARRVAL_P(CRT_CONSTANT(opline->op2));
|
||||
zval *zv;
|
||||
uint32_t s = 0;
|
||||
|
||||
block->successors_count = 2 + zend_hash_num_elements(jumptable);
|
||||
block->successors_count = (opline->opcode == ZEND_MATCH ? 1 : 2) + zend_hash_num_elements(jumptable);
|
||||
block->successors = zend_arena_calloc(arena, block->successors_count, sizeof(int));
|
||||
|
||||
ZEND_HASH_FOREACH_VAL(jumptable, zv) {
|
||||
@ -570,7 +578,9 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
block->successors[s++] = block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
|
||||
block->successors[s++] = j + 1;
|
||||
if (opline->opcode != ZEND_MATCH) {
|
||||
block->successors[s++] = j + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -615,7 +615,11 @@ void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *b, cons
|
||||
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
zval *op = CRT_CONSTANT(opline->op2);
|
||||
if (opline->opcode == ZEND_SWITCH_LONG || opline->opcode == ZEND_SWITCH_STRING) {
|
||||
if (
|
||||
opline->opcode == ZEND_SWITCH_LONG
|
||||
|| opline->opcode == ZEND_SWITCH_STRING
|
||||
|| opline->opcode == ZEND_MATCH
|
||||
) {
|
||||
HashTable *jumptable = Z_ARRVAL_P(op);
|
||||
zend_string *key;
|
||||
zend_ulong num_key;
|
||||
|
@ -2413,6 +2413,7 @@ static zend_always_inline int _zend_update_type_info(
|
||||
case ZEND_JMPZ_EX:
|
||||
case ZEND_JMPNZ_EX:
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT:
|
||||
case ZEND_BOOL:
|
||||
case ZEND_ISSET_ISEMPTY_CV:
|
||||
case ZEND_ISSET_ISEMPTY_VAR:
|
||||
@ -4312,6 +4313,7 @@ int zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op, const ze
|
||||
if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY)) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT:
|
||||
case ZEND_FE_FETCH_R:
|
||||
case ZEND_FE_FETCH_RW:
|
||||
case ZEND_FETCH_LIST_R:
|
||||
@ -4380,12 +4382,14 @@ int zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op, const ze
|
||||
case ZEND_COALESCE:
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
case ZEND_ISSET_ISEMPTY_VAR:
|
||||
case ZEND_ISSET_ISEMPTY_CV:
|
||||
case ZEND_FUNC_NUM_ARGS:
|
||||
case ZEND_FUNC_GET_ARGS:
|
||||
case ZEND_COPY_TMP:
|
||||
case ZEND_CHECK_FUNC_ARG:
|
||||
case ZEND_CASE_STRICT:
|
||||
return 0;
|
||||
case ZEND_INIT_FCALL:
|
||||
/* can't throw, because call is resolved at compile time */
|
||||
|
@ -293,6 +293,7 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
|
||||
* zend_optimizer_replace_by_const() supports this. */
|
||||
return 0;
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT:
|
||||
case ZEND_FETCH_LIST_R:
|
||||
case ZEND_COPY_TMP:
|
||||
case ZEND_FETCH_CLASS_NAME:
|
||||
@ -558,7 +559,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
|
||||
break;
|
||||
/* In most cases IS_TMP_VAR operand may be used only once.
|
||||
* The operands are usually destroyed by the opcode handler.
|
||||
* ZEND_CASE and ZEND_FETCH_LIST_R are exceptions, they keeps operand
|
||||
* ZEND_CASE[_STRICT] and ZEND_FETCH_LIST_R are exceptions, they keeps operand
|
||||
* unchanged, and allows its reuse. these instructions
|
||||
* usually terminated by ZEND_FREE that finally kills the value.
|
||||
*/
|
||||
@ -587,17 +588,25 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
|
||||
}
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_CASE: {
|
||||
case ZEND_MATCH:
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT: {
|
||||
zend_op *end = op_array->opcodes + op_array->last;
|
||||
while (opline < end) {
|
||||
if (opline->op1_type == type && opline->op1.var == var) {
|
||||
if (opline->opcode == ZEND_CASE
|
||||
|| opline->opcode == ZEND_SWITCH_LONG
|
||||
|| opline->opcode == ZEND_SWITCH_STRING) {
|
||||
if (
|
||||
opline->opcode == ZEND_CASE
|
||||
|| opline->opcode == ZEND_CASE_STRICT
|
||||
|| opline->opcode == ZEND_SWITCH_LONG
|
||||
|| opline->opcode == ZEND_SWITCH_STRING
|
||||
|| opline->opcode == ZEND_MATCH
|
||||
) {
|
||||
zval v;
|
||||
|
||||
if (opline->opcode == ZEND_CASE) {
|
||||
opline->opcode = ZEND_IS_EQUAL;
|
||||
} else if (opline->opcode == ZEND_CASE_STRICT) {
|
||||
opline->opcode = ZEND_IS_IDENTICAL;
|
||||
}
|
||||
ZVAL_COPY(&v, val);
|
||||
if (Z_TYPE(v) == IS_STRING) {
|
||||
@ -687,6 +696,7 @@ void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, z
|
||||
break;
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
{
|
||||
HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
|
||||
zval *zv;
|
||||
@ -731,6 +741,7 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_
|
||||
break;
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
{
|
||||
HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
|
||||
zval *zv;
|
||||
@ -1105,6 +1116,7 @@ static void zend_redo_pass_two(zend_op_array *op_array)
|
||||
case ZEND_FE_FETCH_RW:
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
/* relative extended_value don't have to be changed */
|
||||
break;
|
||||
#endif
|
||||
@ -1115,6 +1127,7 @@ static void zend_redo_pass_two(zend_op_array *op_array)
|
||||
case ZEND_IS_SMALLER:
|
||||
case ZEND_IS_SMALLER_OR_EQUAL:
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT:
|
||||
case ZEND_ISSET_ISEMPTY_CV:
|
||||
case ZEND_ISSET_ISEMPTY_VAR:
|
||||
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
|
||||
@ -1225,6 +1238,7 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa)
|
||||
case ZEND_FE_FETCH_RW:
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
/* relative extended_value don't have to be changed */
|
||||
break;
|
||||
#endif
|
||||
@ -1235,6 +1249,7 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa)
|
||||
case ZEND_IS_SMALLER:
|
||||
case ZEND_IS_SMALLER_OR_EQUAL:
|
||||
case ZEND_CASE:
|
||||
case ZEND_CASE_STRICT:
|
||||
case ZEND_ISSET_ISEMPTY_CV:
|
||||
case ZEND_ISSET_ISEMPTY_VAR:
|
||||
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
|
||||
|
@ -2120,7 +2120,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
|
||||
&& ssa->cfg.blocks[b].start != 0
|
||||
&& (op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_NOP
|
||||
|| op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_SWITCH_LONG
|
||||
|| op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_SWITCH_STRING)) {
|
||||
|| op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_SWITCH_STRING
|
||||
|| op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_MATCH)) {
|
||||
if (!zend_jit_reset_opline(&dasm_state, op_array->opcodes + ssa->cfg.blocks[b].start)
|
||||
|| !zend_jit_set_valid_ip(&dasm_state, op_array->opcodes + ssa->cfg.blocks[b].start)) {
|
||||
goto jit_failure;
|
||||
@ -2851,6 +2852,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
|
||||
goto done;
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
if (!zend_jit_switch(&dasm_state, opline, op_array, ssa)) {
|
||||
goto jit_failure;
|
||||
}
|
||||
@ -2898,6 +2900,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
|
||||
case ZEND_OP_DATA:
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
break;
|
||||
case ZEND_JMP:
|
||||
if (JIT_G(opt_level) < ZEND_JIT_LEVEL_INLINE) {
|
||||
@ -2920,6 +2923,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
|
||||
case ZEND_RETURN_BY_REF:
|
||||
case ZEND_RETURN:
|
||||
case ZEND_EXIT:
|
||||
case ZEND_MATCH_ERROR:
|
||||
/* switch through trampoline */
|
||||
case ZEND_YIELD:
|
||||
case ZEND_YIELD_FROM:
|
||||
|
@ -279,6 +279,7 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
|
||||
case ZEND_FE_FETCH_RW:
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
/* branch opcodes */
|
||||
return 1;
|
||||
case ZEND_NEW:
|
||||
@ -296,6 +297,7 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
|
||||
case ZEND_YIELD:
|
||||
case ZEND_YIELD_FROM:
|
||||
case ZEND_INCLUDE_OR_EVAL:
|
||||
case ZEND_MATCH_ERROR:
|
||||
/* unsupported */
|
||||
return 1;
|
||||
case ZEND_DO_FCALL:
|
||||
@ -3943,6 +3945,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
|
||||
#if 0
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
if (!zend_jit_switch(&dasm_state, opline, op_array, op_array_ssa)) {
|
||||
goto jit_failure;
|
||||
}
|
||||
|
@ -11377,6 +11377,13 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o
|
||||
{
|
||||
HashTable *jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
|
||||
|
||||
// TODO: Implement for match instructions
|
||||
if (opline->opcode == ZEND_MATCH) {
|
||||
// Since the match expression doesn't have a IS_IDENTICAL/JMPNZ chain
|
||||
// we can't skip the jumptable and thus can't JIT the function
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zval *zv = RT_CONSTANT(opline, opline->op1);
|
||||
zval *jump_zv;
|
||||
|
71
ext/opcache/tests/match/001.phpt
Normal file
71
ext/opcache/tests/match/001.phpt
Normal file
@ -0,0 +1,71 @@
|
||||
--TEST--
|
||||
Match expression string jump table
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.opt_debug_level=0x20000
|
||||
--SKIPIF--
|
||||
<?php require_once(__DIR__ . '/../skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test($char) {
|
||||
return match ($char) {
|
||||
'a' => 'a',
|
||||
'b', 'c' => 'b, c',
|
||||
'd' => 'd',
|
||||
'e', 'f' => 'e, f',
|
||||
'g' => 'g',
|
||||
'h', 'i' => 'h, i',
|
||||
};
|
||||
}
|
||||
|
||||
foreach (range('a', 'i') as $char) {
|
||||
var_dump(test($char));
|
||||
}
|
||||
|
||||
--EXPECTF--
|
||||
$_main:
|
||||
; (lines=15, args=0, vars=1, tmps=2)
|
||||
; (after optimizer)
|
||||
; %s
|
||||
0000 INIT_FCALL 2 %d string("range")
|
||||
0001 SEND_VAL string("a") 1
|
||||
0002 SEND_VAL string("i") 2
|
||||
0003 V2 = DO_ICALL
|
||||
0004 V1 = FE_RESET_R V2 0013
|
||||
0005 FE_FETCH_R V1 CV0($char) 0013
|
||||
0006 INIT_FCALL 1 %d string("var_dump")
|
||||
0007 INIT_FCALL 1 %d string("test")
|
||||
0008 SEND_VAR CV0($char) 1
|
||||
0009 V2 = DO_UCALL
|
||||
0010 SEND_VAR V2 1
|
||||
0011 DO_ICALL
|
||||
0012 JMP 0005
|
||||
0013 FE_FREE V1
|
||||
0014 RETURN int(1)
|
||||
LIVE RANGES:
|
||||
1: 0005 - 0013 (loop)
|
||||
|
||||
test:
|
||||
; (lines=9, args=1, vars=1, tmps=0)
|
||||
; (after optimizer)
|
||||
; %s
|
||||
0000 CV0($char) = RECV 1
|
||||
0001 MATCH CV0($char) "a": 0002, "b": 0003, "c": 0003, "d": 0004, "e": 0005, "f": 0005, "g": 0006, "h": 0007, "i": 0007, default: 0008
|
||||
0002 RETURN string("a")
|
||||
0003 RETURN string("b, c")
|
||||
0004 RETURN string("d")
|
||||
0005 RETURN string("e, f")
|
||||
0006 RETURN string("g")
|
||||
0007 RETURN string("h, i")
|
||||
0008 MATCH_ERROR CV0($char)
|
||||
string(1) "a"
|
||||
string(4) "b, c"
|
||||
string(4) "b, c"
|
||||
string(1) "d"
|
||||
string(4) "e, f"
|
||||
string(4) "e, f"
|
||||
string(1) "g"
|
||||
string(4) "h, i"
|
||||
string(4) "h, i"
|
57
ext/opcache/tests/match/002.phpt
Normal file
57
ext/opcache/tests/match/002.phpt
Normal file
@ -0,0 +1,57 @@
|
||||
--TEST--
|
||||
Test match jump table optimizer
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.opt_debug_level=0x20000
|
||||
--SKIPIF--
|
||||
<?php require_once(__DIR__ . '/../skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test() {
|
||||
$x = '2';
|
||||
echo match($x) {
|
||||
1, 2, 3, 4, 5 => throw new RuntimeException(),
|
||||
default => "No match\n",
|
||||
};
|
||||
}
|
||||
test();
|
||||
|
||||
function test2() {
|
||||
$x = 2;
|
||||
echo match($x) {
|
||||
'1', '2', '3', '4', '5' => throw new RuntimeException(),
|
||||
default => "No match\n",
|
||||
};
|
||||
}
|
||||
test2();
|
||||
|
||||
--EXPECTF--
|
||||
$_main:
|
||||
; (lines=5, args=0, vars=0, tmps=0)
|
||||
; (after optimizer)
|
||||
; %s
|
||||
0000 INIT_FCALL 0 %d string("test")
|
||||
0001 DO_UCALL
|
||||
0002 INIT_FCALL 0 %d string("test2")
|
||||
0003 DO_UCALL
|
||||
0004 RETURN int(1)
|
||||
|
||||
test:
|
||||
; (lines=2, args=0, vars=0, tmps=0)
|
||||
; (after optimizer)
|
||||
; %s
|
||||
0000 ECHO string("No match
|
||||
")
|
||||
0001 RETURN null
|
||||
|
||||
test2:
|
||||
; (lines=2, args=0, vars=0, tmps=0)
|
||||
; (after optimizer)
|
||||
; %s
|
||||
0000 ECHO string("No match
|
||||
")
|
||||
0001 RETURN null
|
||||
No match
|
||||
No match
|
74
ext/opcache/tests/match/003.phpt
Normal file
74
ext/opcache/tests/match/003.phpt
Normal file
@ -0,0 +1,74 @@
|
||||
--TEST--
|
||||
Match expression long jump table
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.opt_debug_level=0x20000
|
||||
--SKIPIF--
|
||||
<?php require_once(__DIR__ . '/../skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test($char) {
|
||||
return match ($char) {
|
||||
1 => '1',
|
||||
2, 3 => '2, 3',
|
||||
4 => '4',
|
||||
5, 6 => '5, 6',
|
||||
7 => '7',
|
||||
8, 9 => '8, 9',
|
||||
default => 'default'
|
||||
};
|
||||
}
|
||||
|
||||
foreach (range(0, 10) as $char) {
|
||||
var_dump(test($char));
|
||||
}
|
||||
|
||||
--EXPECTF--
|
||||
$_main:
|
||||
; (lines=15, args=0, vars=1, tmps=2)
|
||||
; (after optimizer)
|
||||
; %s
|
||||
0000 INIT_FCALL 2 %d string("range")
|
||||
0001 SEND_VAL int(0) 1
|
||||
0002 SEND_VAL int(10) 2
|
||||
0003 V2 = DO_ICALL
|
||||
0004 V1 = FE_RESET_R V2 0013
|
||||
0005 FE_FETCH_R V1 CV0($char) 0013
|
||||
0006 INIT_FCALL 1 %d string("var_dump")
|
||||
0007 INIT_FCALL 1 %d string("test")
|
||||
0008 SEND_VAR CV0($char) 1
|
||||
0009 V2 = DO_UCALL
|
||||
0010 SEND_VAR V2 1
|
||||
0011 DO_ICALL
|
||||
0012 JMP 0005
|
||||
0013 FE_FREE V1
|
||||
0014 RETURN int(1)
|
||||
LIVE RANGES:
|
||||
1: 0005 - 0013 (loop)
|
||||
|
||||
test:
|
||||
; (lines=9, args=1, vars=1, tmps=0)
|
||||
; (after optimizer)
|
||||
; %s
|
||||
0000 CV0($char) = RECV 1
|
||||
0001 MATCH CV0($char) 1: 0002, 2: 0003, 3: 0003, 4: 0004, 5: 0005, 6: 0005, 7: 0006, 8: 0007, 9: 0007, default: 0008
|
||||
0002 RETURN string("1")
|
||||
0003 RETURN string("2, 3")
|
||||
0004 RETURN string("4")
|
||||
0005 RETURN string("5, 6")
|
||||
0006 RETURN string("7")
|
||||
0007 RETURN string("8, 9")
|
||||
0008 RETURN string("default")
|
||||
string(7) "default"
|
||||
string(1) "1"
|
||||
string(4) "2, 3"
|
||||
string(4) "2, 3"
|
||||
string(1) "4"
|
||||
string(4) "5, 6"
|
||||
string(4) "5, 6"
|
||||
string(1) "7"
|
||||
string(4) "8, 9"
|
||||
string(4) "8, 9"
|
||||
string(7) "default"
|
93
ext/opcache/tests/match/004.phpt
Normal file
93
ext/opcache/tests/match/004.phpt
Normal file
@ -0,0 +1,93 @@
|
||||
--TEST--
|
||||
Match expression mixed jump table
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.opt_debug_level=0x20000
|
||||
--SKIPIF--
|
||||
<?php require_once(__DIR__ . '/../skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test($value) {
|
||||
return match ($value) {
|
||||
1 => '1 int',
|
||||
'1' => '1 string',
|
||||
2 => '2 int',
|
||||
'2' => '2 string',
|
||||
3 => '3 int',
|
||||
'3' => '3 string',
|
||||
4 => '4 int',
|
||||
'4' => '4 string',
|
||||
5 => '5 int',
|
||||
'5' => '5 string',
|
||||
default => 'default',
|
||||
};
|
||||
}
|
||||
|
||||
foreach (range(0, 6) as $number) {
|
||||
var_dump(test($number));
|
||||
var_dump(test((string) $number));
|
||||
}
|
||||
|
||||
--EXPECTF--
|
||||
$_main:
|
||||
; (lines=22, args=0, vars=1, tmps=2)
|
||||
; (after optimizer)
|
||||
; %s.php:1-24
|
||||
0000 INIT_FCALL 2 %d string("range")
|
||||
0001 SEND_VAL int(0) 1
|
||||
0002 SEND_VAL int(6) 2
|
||||
0003 V2 = DO_ICALL
|
||||
0004 V1 = FE_RESET_R V2 0020
|
||||
0005 FE_FETCH_R V1 CV0($number) 0020
|
||||
0006 INIT_FCALL 1 %d string("var_dump")
|
||||
0007 INIT_FCALL 1 %d string("test")
|
||||
0008 SEND_VAR CV0($number) 1
|
||||
0009 V2 = DO_UCALL
|
||||
0010 SEND_VAR V2 1
|
||||
0011 DO_ICALL
|
||||
0012 INIT_FCALL 1 %d string("var_dump")
|
||||
0013 INIT_FCALL 1 %d string("test")
|
||||
0014 T2 = CAST (string) CV0($number)
|
||||
0015 SEND_VAL T2 1
|
||||
0016 V2 = DO_UCALL
|
||||
0017 SEND_VAR V2 1
|
||||
0018 DO_ICALL
|
||||
0019 JMP 0005
|
||||
0020 FE_FREE V1
|
||||
0021 RETURN int(1)
|
||||
LIVE RANGES:
|
||||
1: 0005 - 0020 (loop)
|
||||
|
||||
test:
|
||||
; (lines=13, args=1, vars=1, tmps=0)
|
||||
; (after optimizer)
|
||||
; %s.php:3-17
|
||||
0000 CV0($value) = RECV 1
|
||||
0001 MATCH CV0($value) 1: 0002, "1": 0003, 2: 0004, "2": 0005, 3: 0006, "3": 0007, 4: 0008, "4": 0009, 5: 0010, "5": 0011, default: 0012
|
||||
0002 RETURN string("1 int")
|
||||
0003 RETURN string("1 string")
|
||||
0004 RETURN string("2 int")
|
||||
0005 RETURN string("2 string")
|
||||
0006 RETURN string("3 int")
|
||||
0007 RETURN string("3 string")
|
||||
0008 RETURN string("4 int")
|
||||
0009 RETURN string("4 string")
|
||||
0010 RETURN string("5 int")
|
||||
0011 RETURN string("5 string")
|
||||
0012 RETURN string("default")
|
||||
string(7) "default"
|
||||
string(7) "default"
|
||||
string(5) "1 int"
|
||||
string(8) "1 string"
|
||||
string(5) "2 int"
|
||||
string(8) "2 string"
|
||||
string(5) "3 int"
|
||||
string(8) "3 string"
|
||||
string(5) "4 int"
|
||||
string(8) "4 string"
|
||||
string(5) "5 int"
|
||||
string(8) "5 string"
|
||||
string(7) "default"
|
||||
string(7) "default"
|
@ -547,6 +547,7 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
|
||||
case ZEND_FE_FETCH_RW:
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
/* relative extended_value don't have to be changed */
|
||||
break;
|
||||
}
|
||||
|
@ -549,6 +549,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
|
||||
case ZEND_FE_FETCH_RW:
|
||||
case ZEND_SWITCH_LONG:
|
||||
case ZEND_SWITCH_STRING:
|
||||
case ZEND_MATCH:
|
||||
/* relative extended_value don't have to be changed */
|
||||
break;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ unlink($file_name);
|
||||
echo "\n*** Testing fnmatch() with other types other than files ***";
|
||||
|
||||
/* defining a common function */
|
||||
function match( $pattern, $string ) {
|
||||
function match_( $pattern, $string ) {
|
||||
for( $i = 0; $i<count($pattern); $i++ ) {
|
||||
echo "-- Iteration $i --\n";
|
||||
for( $j = 0; $j<count($string); $j++ ) {
|
||||
@ -96,7 +96,7 @@ $int_arr = array(
|
||||
0xF,
|
||||
0xF0000
|
||||
);
|
||||
match($int_arr, $int_arr);
|
||||
match_($int_arr, $int_arr);
|
||||
|
||||
echo "\n--- With Strings ---\n";
|
||||
$str_arr = array(
|
||||
@ -109,7 +109,7 @@ $str_arr = array(
|
||||
/* binary input */
|
||||
b"string"
|
||||
);
|
||||
match($str_arr, $str_arr);
|
||||
match_($str_arr, $str_arr);
|
||||
|
||||
echo "\n--- With booleans ---\n";
|
||||
$bool_arr = array(
|
||||
@ -123,7 +123,7 @@ $bool_arr = array(
|
||||
"",
|
||||
"string"
|
||||
);
|
||||
match($bool_arr, $bool_arr);
|
||||
match_($bool_arr, $bool_arr);
|
||||
|
||||
echo "\n--- With NULL ---\n";
|
||||
$null_arr = array(
|
||||
@ -134,7 +134,7 @@ $null_arr = array(
|
||||
"string",
|
||||
0
|
||||
);
|
||||
match($null_arr, $null_arr);
|
||||
match_($null_arr, $null_arr);
|
||||
|
||||
echo "\n*** Done ***\n";
|
||||
?>
|
||||
|
@ -84,8 +84,6 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
|
||||
REGISTER_LONG_CONSTANT("T_STRING_VARNAME", T_STRING_VARNAME, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_NUM_STRING", T_NUM_STRING, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_EVAL", T_EVAL, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_INC", T_INC, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_DEC", T_DEC, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_NEW", T_NEW, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_EXIT", T_EXIT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_IF", T_IF, CONST_CS | CONST_PERSISTENT);
|
||||
@ -105,6 +103,7 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
|
||||
REGISTER_LONG_CONSTANT("T_ENDSWITCH", T_ENDSWITCH, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_CASE", T_CASE, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_DEFAULT", T_DEFAULT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_MATCH", T_MATCH, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_BREAK", T_BREAK, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_CONTINUE", T_CONTINUE, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_GOTO", T_GOTO, CONST_CS | CONST_PERSISTENT);
|
||||
@ -134,7 +133,7 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
|
||||
REGISTER_LONG_CONSTANT("T_INTERFACE", T_INTERFACE, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_EXTENDS", T_EXTENDS, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_IMPLEMENTS", T_IMPLEMENTS, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_OBJECT_OPERATOR", T_OBJECT_OPERATOR, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_NAMESPACE", T_NAMESPACE, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_LIST", T_LIST, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_ARRAY", T_ARRAY, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_CALLABLE", T_CALLABLE, CONST_CS | CONST_PERSISTENT);
|
||||
@ -145,6 +144,10 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
|
||||
REGISTER_LONG_CONSTANT("T_TRAIT_C", T_TRAIT_C, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_METHOD_C", T_METHOD_C, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_FUNC_C", T_FUNC_C, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_NS_C", T_NS_C, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_INC", T_INC, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_DEC", T_DEC, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_OBJECT_OPERATOR", T_OBJECT_OPERATOR, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_COMMENT", T_COMMENT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_DOC_COMMENT", T_DOC_COMMENT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_OPEN_TAG", T_OPEN_TAG, CONST_CS | CONST_PERSISTENT);
|
||||
@ -156,8 +159,6 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
|
||||
REGISTER_LONG_CONSTANT("T_DOLLAR_OPEN_CURLY_BRACES", T_DOLLAR_OPEN_CURLY_BRACES, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_CURLY_OPEN", T_CURLY_OPEN, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_PAAMAYIM_NEKUDOTAYIM", T_PAAMAYIM_NEKUDOTAYIM, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_NAMESPACE", T_NAMESPACE, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_NS_C", T_NS_C, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_NS_SEPARATOR", T_NS_SEPARATOR, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_ELLIPSIS", T_ELLIPSIS, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_BAD_CHARACTER", T_BAD_CHARACTER, CONST_CS | CONST_PERSISTENT);
|
||||
@ -227,8 +228,6 @@ char *get_token_type_name(int token_type)
|
||||
case T_STRING_VARNAME: return "T_STRING_VARNAME";
|
||||
case T_NUM_STRING: return "T_NUM_STRING";
|
||||
case T_EVAL: return "T_EVAL";
|
||||
case T_INC: return "T_INC";
|
||||
case T_DEC: return "T_DEC";
|
||||
case T_NEW: return "T_NEW";
|
||||
case T_EXIT: return "T_EXIT";
|
||||
case T_IF: return "T_IF";
|
||||
@ -248,6 +247,7 @@ char *get_token_type_name(int token_type)
|
||||
case T_ENDSWITCH: return "T_ENDSWITCH";
|
||||
case T_CASE: return "T_CASE";
|
||||
case T_DEFAULT: return "T_DEFAULT";
|
||||
case T_MATCH: return "T_MATCH";
|
||||
case T_BREAK: return "T_BREAK";
|
||||
case T_CONTINUE: return "T_CONTINUE";
|
||||
case T_GOTO: return "T_GOTO";
|
||||
@ -277,7 +277,7 @@ char *get_token_type_name(int token_type)
|
||||
case T_INTERFACE: return "T_INTERFACE";
|
||||
case T_EXTENDS: return "T_EXTENDS";
|
||||
case T_IMPLEMENTS: return "T_IMPLEMENTS";
|
||||
case T_OBJECT_OPERATOR: return "T_OBJECT_OPERATOR";
|
||||
case T_NAMESPACE: return "T_NAMESPACE";
|
||||
case T_LIST: return "T_LIST";
|
||||
case T_ARRAY: return "T_ARRAY";
|
||||
case T_CALLABLE: return "T_CALLABLE";
|
||||
@ -288,6 +288,10 @@ char *get_token_type_name(int token_type)
|
||||
case T_TRAIT_C: return "T_TRAIT_C";
|
||||
case T_METHOD_C: return "T_METHOD_C";
|
||||
case T_FUNC_C: return "T_FUNC_C";
|
||||
case T_NS_C: return "T_NS_C";
|
||||
case T_INC: return "T_INC";
|
||||
case T_DEC: return "T_DEC";
|
||||
case T_OBJECT_OPERATOR: return "T_OBJECT_OPERATOR";
|
||||
case T_COMMENT: return "T_COMMENT";
|
||||
case T_DOC_COMMENT: return "T_DOC_COMMENT";
|
||||
case T_OPEN_TAG: return "T_OPEN_TAG";
|
||||
@ -299,8 +303,6 @@ char *get_token_type_name(int token_type)
|
||||
case T_DOLLAR_OPEN_CURLY_BRACES: return "T_DOLLAR_OPEN_CURLY_BRACES";
|
||||
case T_CURLY_OPEN: return "T_CURLY_OPEN";
|
||||
case T_PAAMAYIM_NEKUDOTAYIM: return "T_DOUBLE_COLON";
|
||||
case T_NAMESPACE: return "T_NAMESPACE";
|
||||
case T_NS_C: return "T_NS_C";
|
||||
case T_NS_SEPARATOR: return "T_NS_SEPARATOR";
|
||||
case T_ELLIPSIS: return "T_ELLIPSIS";
|
||||
case T_BAD_CHARACTER: return "T_BAD_CHARACTER";
|
||||
|
Loading…
Reference in New Issue
Block a user