mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Add support for $obj::class
This allows $obj::class, which gives the same result as get_class($obj). Anything other than an object results in TypeError. RFC: https://wiki.php.net/rfc/class_name_literal_on_object Closes GH-5065.
This commit is contained in:
parent
69819baee3
commit
d933591674
11 changed files with 943 additions and 704 deletions
|
@ -367,6 +367,9 @@ PHP 8.0 UPGRADE NOTES
|
|||
class B extends A {
|
||||
public function method(...$everything) {}
|
||||
}
|
||||
. It is now possible to fetch the class name of an object using
|
||||
`$object::class`. The result is the same as `get_class($object)`.
|
||||
RFC: https://wiki.php.net/rfc/class_name_literal_on_object
|
||||
|
||||
|
||||
- Date:
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
--TEST--
|
||||
$var::class is not supported
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$obj = new stdClass;
|
||||
var_dump($obj::class);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use ::class with dynamic class name in %s on line %d
|
10
Zend/tests/class_on_constant_evaluated_expression.phpt
Normal file
10
Zend/tests/class_on_constant_evaluated_expression.phpt
Normal file
|
@ -0,0 +1,10 @@
|
|||
--TEST--
|
||||
An error should be generated when using ::class on a constant evaluated expression
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
(1+1)::class;
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use ::class on value of type int in %s on line %d
|
10
Zend/tests/class_on_expression_in_constant_expression.phpt
Normal file
10
Zend/tests/class_on_expression_in_constant_expression.phpt
Normal file
|
@ -0,0 +1,10 @@
|
|||
--TEST--
|
||||
::class on an expression cannot be used inside constant expressions
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
const A = [0]::class;
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: (expression)::class cannot be used in constant expressions in %s on line %d
|
28
Zend/tests/class_on_object.phpt
Normal file
28
Zend/tests/class_on_object.phpt
Normal file
|
@ -0,0 +1,28 @@
|
|||
--TEST--
|
||||
Using ::class on an object
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$obj = new stdClass;
|
||||
var_dump($obj::class);
|
||||
$ref =& $obj;
|
||||
var_dump($ref::class);
|
||||
var_dump((new stdClass)::class);
|
||||
|
||||
// Placed in a function to check that opcache doesn't perform incorrect constprop.
|
||||
function test() {
|
||||
$other = null;
|
||||
var_dump($other::class);
|
||||
}
|
||||
try {
|
||||
test();
|
||||
} catch (TypeError $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(8) "stdClass"
|
||||
string(8) "stdClass"
|
||||
string(8) "stdClass"
|
||||
Cannot use ::class on value of type null
|
|
@ -1551,7 +1551,7 @@ static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_a
|
|||
zval *class_name;
|
||||
|
||||
if (class_ast->kind != ZEND_AST_ZVAL) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use ::class with dynamic class name");
|
||||
return 0;
|
||||
}
|
||||
|
||||
class_name = zend_ast_get_zval(class_ast);
|
||||
|
@ -8246,15 +8246,27 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
|
|||
void zend_compile_class_name(znode *result, zend_ast *ast) /* {{{ */
|
||||
{
|
||||
zend_ast *class_ast = ast->child[0];
|
||||
zend_op *opline;
|
||||
|
||||
if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast)) {
|
||||
result->op_type = IS_CONST;
|
||||
return;
|
||||
}
|
||||
|
||||
opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
|
||||
opline->op1.num = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
|
||||
if (class_ast->kind == ZEND_AST_ZVAL) {
|
||||
zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
|
||||
opline->op1.num = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
|
||||
} else {
|
||||
znode expr_node;
|
||||
zend_compile_expr(&expr_node, class_ast);
|
||||
if (expr_node.op_type == IS_CONST) {
|
||||
/* Unlikely case that happen if class_ast is constant folded.
|
||||
* Handle it here, to avoid needing a CONST specialization in the VM. */
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use ::class on value of type %s",
|
||||
zend_get_type_by_const(Z_TYPE(expr_node.u.constant)));
|
||||
}
|
||||
|
||||
zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, &expr_node, NULL);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -8491,6 +8503,11 @@ void zend_compile_const_expr_class_name(zend_ast **ast_ptr) /* {{{ */
|
|||
{
|
||||
zend_ast *ast = *ast_ptr;
|
||||
zend_ast *class_ast = ast->child[0];
|
||||
if (class_ast->kind != ZEND_AST_ZVAL) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR,
|
||||
"(expression)::class cannot be used in constant expressions");
|
||||
}
|
||||
|
||||
zend_string *class_name = zend_ast_get_str(class_ast);
|
||||
uint32_t fetch_type = zend_get_class_fetch_type(class_name);
|
||||
|
||||
|
|
|
@ -7992,14 +7992,32 @@ ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, JMP_ADDR)
|
|||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, UNUSED|CLASS_FETCH, ANY)
|
||||
ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, CV|TMPVAR|UNUSED|CLASS_FETCH, ANY)
|
||||
{
|
||||
uint32_t fetch_type;
|
||||
zend_class_entry *called_scope, *scope;
|
||||
USE_OPLINE
|
||||
|
||||
fetch_type = opline->op1.num;
|
||||
if (OP1_TYPE != IS_UNUSED) {
|
||||
zval *op = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
||||
SAVE_OPLINE();
|
||||
if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) {
|
||||
ZVAL_DEREF(op);
|
||||
if (Z_TYPE_P(op) != IS_OBJECT) {
|
||||
zend_type_error("Cannot use ::class on value of type %s",
|
||||
zend_get_type_by_const(Z_TYPE_P(op)));
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name);
|
||||
FREE_OP1();
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
fetch_type = opline->op1.num;
|
||||
scope = EX(func)->op_array.scope;
|
||||
if (UNEXPECTED(scope == NULL)) {
|
||||
SAVE_OPLINE();
|
||||
|
|
|
@ -13350,6 +13350,69 @@ type_check_resource:
|
|||
}
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
uint32_t fetch_type;
|
||||
zend_class_entry *called_scope, *scope;
|
||||
USE_OPLINE
|
||||
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
|
||||
zval *op = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC);
|
||||
SAVE_OPLINE();
|
||||
if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) {
|
||||
ZVAL_DEREF(op);
|
||||
if (Z_TYPE_P(op) != IS_OBJECT) {
|
||||
zend_type_error("Cannot use ::class on value of type %s",
|
||||
zend_get_type_by_const(Z_TYPE_P(op)));
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name);
|
||||
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
fetch_type = opline->op1.num;
|
||||
scope = EX(func)->op_array.scope;
|
||||
if (UNEXPECTED(scope == NULL)) {
|
||||
SAVE_OPLINE();
|
||||
zend_throw_error(NULL, "Cannot use \"%s\" when no class scope is active",
|
||||
fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
|
||||
fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
switch (fetch_type) {
|
||||
case ZEND_FETCH_CLASS_SELF:
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name);
|
||||
break;
|
||||
case ZEND_FETCH_CLASS_PARENT:
|
||||
if (UNEXPECTED(scope->parent == NULL)) {
|
||||
SAVE_OPLINE();
|
||||
zend_throw_error(NULL,
|
||||
"Cannot use \"parent\" when current class scope has no parent");
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name);
|
||||
break;
|
||||
case ZEND_FETCH_CLASS_STATIC:
|
||||
if (Z_TYPE(EX(This)) == IS_OBJECT) {
|
||||
called_scope = Z_OBJCE(EX(This));
|
||||
} else {
|
||||
called_scope = Z_CE(EX(This));
|
||||
}
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), called_scope->name);
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
@ -29033,8 +29096,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_H
|
|||
zend_class_entry *called_scope, *scope;
|
||||
USE_OPLINE
|
||||
|
||||
fetch_type = opline->op1.num;
|
||||
if (IS_UNUSED != IS_UNUSED) {
|
||||
zval *op = NULL;
|
||||
SAVE_OPLINE();
|
||||
if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) {
|
||||
ZVAL_DEREF(op);
|
||||
if (Z_TYPE_P(op) != IS_OBJECT) {
|
||||
zend_type_error("Cannot use ::class on value of type %s",
|
||||
zend_get_type_by_const(Z_TYPE_P(op)));
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
fetch_type = opline->op1.num;
|
||||
scope = EX(func)->op_array.scope;
|
||||
if (UNEXPECTED(scope == NULL)) {
|
||||
SAVE_OPLINE();
|
||||
|
@ -36666,6 +36747,69 @@ type_check_resource:
|
|||
}
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
uint32_t fetch_type;
|
||||
zend_class_entry *called_scope, *scope;
|
||||
USE_OPLINE
|
||||
|
||||
if (IS_CV != IS_UNUSED) {
|
||||
zval *op = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC);
|
||||
SAVE_OPLINE();
|
||||
if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) {
|
||||
ZVAL_DEREF(op);
|
||||
if (Z_TYPE_P(op) != IS_OBJECT) {
|
||||
zend_type_error("Cannot use ::class on value of type %s",
|
||||
zend_get_type_by_const(Z_TYPE_P(op)));
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
fetch_type = opline->op1.num;
|
||||
scope = EX(func)->op_array.scope;
|
||||
if (UNEXPECTED(scope == NULL)) {
|
||||
SAVE_OPLINE();
|
||||
zend_throw_error(NULL, "Cannot use \"%s\" when no class scope is active",
|
||||
fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
|
||||
fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
switch (fetch_type) {
|
||||
case ZEND_FETCH_CLASS_SELF:
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name);
|
||||
break;
|
||||
case ZEND_FETCH_CLASS_PARENT:
|
||||
if (UNEXPECTED(scope->parent == NULL)) {
|
||||
SAVE_OPLINE();
|
||||
zend_throw_error(NULL,
|
||||
"Cannot use \"parent\" when current class scope has no parent");
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name);
|
||||
break;
|
||||
case ZEND_FETCH_CLASS_STATIC:
|
||||
if (Z_TYPE(EX(This)) == IS_OBJECT) {
|
||||
called_scope = Z_OBJCE(EX(This));
|
||||
} else {
|
||||
called_scope = Z_CE(EX(This));
|
||||
}
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), called_scope->name);
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
@ -50613,7 +50757,11 @@ ZEND_API void execute_ex(zend_execute_data *ex)
|
|||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_FETCH_LIST_W_SPEC_VAR_CV_LABEL,
|
||||
(void*)&&ZEND_SEPARATE_SPEC_VAR_UNUSED_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_LABEL,
|
||||
(void*)&&ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_LABEL,
|
||||
(void*)&&ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_LABEL,
|
||||
(void*)&&ZEND_FETCH_CLASS_NAME_SPEC_CV_LABEL,
|
||||
(void*)&&ZEND_CALL_TRAMPOLINE_SPEC_LABEL,
|
||||
(void*)&&ZEND_DISCARD_EXCEPTION_SPEC_LABEL,
|
||||
(void*)&&ZEND_YIELD_SPEC_CONST_CONST_LABEL,
|
||||
|
@ -53267,6 +53415,10 @@ zend_leave_helper_SPEC_LABEL:
|
|||
VM_TRACE(ZEND_TYPE_CHECK_SPEC_TMPVAR)
|
||||
ZEND_TYPE_CHECK_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR):
|
||||
VM_TRACE(ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR)
|
||||
ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_DIV_SPEC_TMPVAR_CONST):
|
||||
VM_TRACE(ZEND_DIV_SPEC_TMPVAR_CONST)
|
||||
ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
|
@ -55050,6 +55202,10 @@ zend_leave_helper_SPEC_LABEL:
|
|||
VM_TRACE(ZEND_TYPE_CHECK_SPEC_CV)
|
||||
ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_FETCH_CLASS_NAME_SPEC_CV):
|
||||
VM_TRACE(ZEND_FETCH_CLASS_NAME_SPEC_CV)
|
||||
ZEND_FETCH_CLASS_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED):
|
||||
VM_TRACE(ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED)
|
||||
ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
|
@ -58145,7 +58301,11 @@ void zend_vm_init(void)
|
|||
ZEND_NULL_HANDLER,
|
||||
ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER,
|
||||
ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_HANDLER,
|
||||
ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_HANDLER,
|
||||
ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_HANDLER,
|
||||
ZEND_FETCH_CLASS_NAME_SPEC_CV_HANDLER,
|
||||
ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
|
||||
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
||||
ZEND_YIELD_SPEC_CONST_CONST_HANDLER,
|
||||
|
@ -59362,45 +59522,45 @@ void zend_vm_init(void)
|
|||
2149 | SPEC_RULE_ISSET,
|
||||
2151 | SPEC_RULE_OP2,
|
||||
2156,
|
||||
2157,
|
||||
2158,
|
||||
2159,
|
||||
2160 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
|
||||
2185 | SPEC_RULE_OP1,
|
||||
2190,
|
||||
2191,
|
||||
2192,
|
||||
2193,
|
||||
2194 | SPEC_RULE_OP1,
|
||||
2199,
|
||||
2200,
|
||||
2201 | SPEC_RULE_OP1,
|
||||
2206 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
|
||||
2231,
|
||||
2232 | SPEC_RULE_OP1,
|
||||
2237,
|
||||
2238,
|
||||
2239,
|
||||
2240,
|
||||
2157 | SPEC_RULE_OP1,
|
||||
2162,
|
||||
2163,
|
||||
2164 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
|
||||
2189 | SPEC_RULE_OP1,
|
||||
2194,
|
||||
2195,
|
||||
2196,
|
||||
2197,
|
||||
2198 | SPEC_RULE_OP1,
|
||||
2203,
|
||||
2204,
|
||||
2205 | SPEC_RULE_OP1,
|
||||
2210 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
|
||||
2235,
|
||||
2236 | SPEC_RULE_OP1,
|
||||
2241,
|
||||
2242,
|
||||
2243,
|
||||
2244,
|
||||
2245 | SPEC_RULE_OP1,
|
||||
2250,
|
||||
2251,
|
||||
2252,
|
||||
2253,
|
||||
2245,
|
||||
2246,
|
||||
2247,
|
||||
2248,
|
||||
2249 | SPEC_RULE_OP1,
|
||||
2254,
|
||||
2255 | SPEC_RULE_OP1,
|
||||
2260 | SPEC_RULE_OP1,
|
||||
2265 | SPEC_RULE_OP1,
|
||||
2270 | SPEC_RULE_OP1,
|
||||
2275 | SPEC_RULE_OP1,
|
||||
2280,
|
||||
2281 | SPEC_RULE_OP1,
|
||||
2286 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
|
||||
3214
|
||||
2255,
|
||||
2256,
|
||||
2257,
|
||||
2258,
|
||||
2259 | SPEC_RULE_OP1,
|
||||
2264 | SPEC_RULE_OP1,
|
||||
2269 | SPEC_RULE_OP1,
|
||||
2274 | SPEC_RULE_OP1,
|
||||
2279 | SPEC_RULE_OP1,
|
||||
2284,
|
||||
2285 | SPEC_RULE_OP1,
|
||||
2290 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
|
||||
3218
|
||||
};
|
||||
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
|
||||
zend_opcode_handler_funcs = labels;
|
||||
|
@ -59560,7 +59720,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 = 2313 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2317 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
if (op->op1_type < op->op2_type) {
|
||||
zend_swap_operands(op);
|
||||
}
|
||||
|
@ -59568,7 +59728,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 = 2338 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2342 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
if (op->op1_type < op->op2_type) {
|
||||
zend_swap_operands(op);
|
||||
}
|
||||
|
@ -59576,7 +59736,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 = 2363 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2367 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
if (op->op1_type < op->op2_type) {
|
||||
zend_swap_operands(op);
|
||||
}
|
||||
|
@ -59587,17 +59747,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 = 2388 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
spec = 2392 | 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 = 2413 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
spec = 2417 | 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 = 2438 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
spec = 2442 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
}
|
||||
break;
|
||||
case ZEND_MUL:
|
||||
|
@ -59608,17 +59768,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 = 2463 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2467 | 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 = 2488 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2492 | 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 = 2513 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2517 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_IDENTICAL:
|
||||
|
@ -59629,14 +59789,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 = 2538 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2542 | 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 = 2613 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2617 | 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 = 2838 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2842 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_NOT_IDENTICAL:
|
||||
|
@ -59647,14 +59807,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 = 2688 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2692 | 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 = 2763 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2767 | 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 = 2843 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2847 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_EQUAL:
|
||||
|
@ -59665,12 +59825,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 = 2538 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2542 | 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 = 2613 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2617 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_NOT_EQUAL:
|
||||
|
@ -59681,12 +59841,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 = 2688 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2692 | 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 = 2763 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
spec = 2767 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_SMALLER:
|
||||
|
@ -59694,12 +59854,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 = 2848 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
spec = 2852 | 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 = 2923 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
spec = 2927 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
}
|
||||
break;
|
||||
case ZEND_IS_SMALLER_OR_EQUAL:
|
||||
|
@ -59707,74 +59867,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 = 2998 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
spec = 3002 | 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 = 3073 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
spec = 3077 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
|
||||
}
|
||||
break;
|
||||
case ZEND_QM_ASSIGN:
|
||||
if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3160 | SPEC_RULE_OP1;
|
||||
spec = 3164 | SPEC_RULE_OP1;
|
||||
} else if (op1_info == MAY_BE_DOUBLE) {
|
||||
spec = 3165 | SPEC_RULE_OP1;
|
||||
spec = 3169 | 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 = 3170 | SPEC_RULE_OP1;
|
||||
spec = 3174 | SPEC_RULE_OP1;
|
||||
}
|
||||
break;
|
||||
case ZEND_PRE_INC:
|
||||
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
|
||||
spec = 3148 | SPEC_RULE_RETVAL;
|
||||
} else if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3150 | SPEC_RULE_RETVAL;
|
||||
}
|
||||
break;
|
||||
case ZEND_PRE_DEC:
|
||||
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
|
||||
spec = 3152 | SPEC_RULE_RETVAL;
|
||||
} else if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3154 | SPEC_RULE_RETVAL;
|
||||
}
|
||||
break;
|
||||
case ZEND_PRE_DEC:
|
||||
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
|
||||
spec = 3156 | SPEC_RULE_RETVAL;
|
||||
} else if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3158 | SPEC_RULE_RETVAL;
|
||||
}
|
||||
break;
|
||||
case ZEND_POST_INC:
|
||||
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
|
||||
spec = 3156;
|
||||
spec = 3160;
|
||||
} else if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3157;
|
||||
spec = 3161;
|
||||
}
|
||||
break;
|
||||
case ZEND_POST_DEC:
|
||||
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
|
||||
spec = 3158;
|
||||
spec = 3162;
|
||||
} else if (op1_info == MAY_BE_LONG) {
|
||||
spec = 3159;
|
||||
spec = 3163;
|
||||
}
|
||||
break;
|
||||
case ZEND_JMP:
|
||||
if (OP_JMP_ADDR(op, op->op1) > op) {
|
||||
spec = 2312;
|
||||
spec = 2316;
|
||||
}
|
||||
break;
|
||||
case ZEND_RECV:
|
||||
if (op->op2.num == MAY_BE_ANY) {
|
||||
spec = 2311;
|
||||
spec = 2315;
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAL:
|
||||
if (op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) {
|
||||
spec = 3210;
|
||||
spec = 3214;
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAR_EX:
|
||||
if (op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
|
||||
spec = 3205 | SPEC_RULE_OP1;
|
||||
spec = 3209 | 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 = 3212 | SPEC_RULE_RETVAL;
|
||||
spec = 3216 | SPEC_RULE_RETVAL;
|
||||
}
|
||||
break;
|
||||
case ZEND_FETCH_DIM_R:
|
||||
|
@ -59782,17 +59942,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 = 3175 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
|
||||
spec = 3179 | 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 = 3211;
|
||||
spec = 3215;
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAR:
|
||||
if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
|
||||
spec = 3200 | SPEC_RULE_OP1;
|
||||
spec = 3204 | SPEC_RULE_OP1;
|
||||
}
|
||||
break;
|
||||
case ZEND_BW_OR:
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -378,7 +378,7 @@ static uint32_t zend_vm_opcodes_flags[195] = {
|
|||
0x00020101,
|
||||
0x00000701,
|
||||
0x00000101,
|
||||
0x00000071,
|
||||
0x00000075,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0b000703,
|
||||
|
|
|
@ -339,6 +339,7 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
|
|||
case ZEND_CASE:
|
||||
case ZEND_FETCH_LIST_R:
|
||||
case ZEND_COPY_TMP:
|
||||
case ZEND_FETCH_CLASS_NAME:
|
||||
return 0;
|
||||
case ZEND_ECHO:
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue