]> granicus.if.org Git - php/commitdiff
Added ZEND_GET_CLASS, ZEMD_GET_CALLED_CLASS, ZEND_GET_TYPE instructions, to implement...
authorDmitry Stogov <dmitry@zend.com>
Thu, 25 May 2017 15:41:28 +0000 (18:41 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 25 May 2017 15:41:28 +0000 (18:41 +0300)
12 files changed:
NEWS
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_compile.c
Zend/zend_string.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_opcodes.c
Zend/zend_vm_opcodes.h
ext/opcache/Optimizer/zend_func_info.c
ext/opcache/Optimizer/zend_inference.c
ext/standard/type.c

diff --git a/NEWS b/NEWS
index 1e3803a6e6fa710d68e781cf398a144ec5d058d2..9b2544beb5458266b825cba06b6f30f18eb10581 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,8 @@ PHP                                                                        NEWS
 ?? ??? ????, PHP 7.2
 
 - Core:
-  . Added ZEND_COUNT instruction, to implement corresponding builtin. (Dmitry)
+  . Added ZEND_COUNT, ZEND_GET_CLASS, ZEMD_GET_CALLED_CLASS, ZEND_GET_TYPE
+    instructions, to implement corresponding builtin functions. (Dmitry)
   . "Countable" interface is moved from SPL to Core. (Dmitry)
   . Added ZEND_IN_ARRAY instruction, implementing optimized in_array() builtin
     function, through hash lookup in flipped array. (Dmitry)
index 0274a288b693191f40a738da699d1f062d6e4d1d..c95d462872237a8c93f7c7bc5c846ccf0f6989f9 100644 (file)
@@ -202,6 +202,36 @@ ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
 }
 /* }}} */
 
+ZEND_API zend_string *zend_zval_get_type(const zval *arg) /* {{{ */
+{
+       switch (Z_TYPE_P(arg)) {
+               case IS_NULL:
+                       return ZSTR_KNOWN(ZEND_STR_NULL);
+               case IS_FALSE:
+               case IS_TRUE:
+                       return ZSTR_KNOWN(ZEND_STR_BOOLEAN);
+               case IS_LONG:
+                       return ZSTR_KNOWN(ZEND_STR_INTEGER);
+               case IS_DOUBLE:
+                       return ZSTR_KNOWN(ZEND_STR_DOUBLE);
+               case IS_STRING:
+                       return ZSTR_KNOWN(ZEND_STR_STRING);
+               case IS_ARRAY:
+                       return ZSTR_KNOWN(ZEND_STR_ARRAY);
+               case IS_OBJECT:
+                       return ZSTR_KNOWN(ZEND_STR_OBJECT);
+               case IS_RESOURCE:
+                       if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {
+                               return ZSTR_KNOWN(ZEND_STR_RESOURCE);
+                       } else {
+                               return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);
+                       }
+               default:
+                       return NULL;
+       }
+}
+/* }}} */
+
 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(zend_bool throw_, int num_args, int min_num_args, int max_num_args) /* {{{ */
 {
        zend_function *active_function = EG(current_execute_data)->func;
index b8a6ecfcb77d80eab01d6ab5d98feee78fd1e25e..4a1a0d46176f381bc2e72901d45a145892b7fe20 100644 (file)
@@ -277,6 +277,7 @@ ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...);
 ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...);
 ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ...);
 ZEND_API char *zend_zval_type_name(const zval *arg);
+ZEND_API zend_string *zend_zval_get_type(const zval *arg);
 
 ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const char *type_spec, ...);
 ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this_ptr, const char *type_spec, ...);
index 2858e6a9065ddbf45cacc95ec572a1a091930402..372fddc5f52508bd24c2c05ff2d1f942a77a4b27 100644 (file)
@@ -3737,6 +3737,51 @@ int zend_compile_func_count(znode *result, zend_ast_list *args) /* {{{ */
 }
 /* }}} */
 
+int zend_compile_func_get_class(znode *result, zend_ast_list *args) /* {{{ */
+{
+       if (args->children == 0) {
+               zend_emit_op_tmp(result, ZEND_GET_CLASS, NULL, NULL);
+       } else {
+               znode arg_node;
+
+               if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
+                       return FAILURE;
+               }
+
+               zend_compile_expr(&arg_node, args->child[0]);
+               zend_emit_op_tmp(result, ZEND_GET_CLASS, &arg_node, NULL);
+       }
+       return SUCCESS;
+}
+/* }}} */
+
+int zend_compile_func_get_called_class(znode *result, zend_ast_list *args) /* {{{ */
+{
+       znode arg_node;
+
+       if (args->children != 0) {
+               return FAILURE;
+       }
+
+       zend_emit_op_tmp(result, ZEND_GET_CALLED_CLASS, &arg_node, NULL);
+       return SUCCESS;
+}
+/* }}} */
+
+int zend_compile_func_gettype(znode *result, zend_ast_list *args) /* {{{ */
+{
+       znode arg_node;
+
+       if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
+               return FAILURE;
+       }
+
+       zend_compile_expr(&arg_node, args->child[0]);
+       zend_emit_op_tmp(result, ZEND_GET_TYPE, &arg_node, NULL);
+       return SUCCESS;
+}
+/* }}} */
+
 int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */
 {
        if (fbc->internal_function.handler == ZEND_FN(display_disabled_function)) {
@@ -3799,6 +3844,12 @@ int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_l
                return zend_compile_func_in_array(result, args);
        } else if (zend_string_equals_literal(lcname, "count")) {
                return zend_compile_func_count(result, args);
+       } else if (zend_string_equals_literal(lcname, "get_class")) {
+               return zend_compile_func_get_class(result, args);
+       } else if (zend_string_equals_literal(lcname, "get_called_class")) {
+               return zend_compile_func_get_called_class(result, args);
+       } else if (zend_string_equals_literal(lcname, "gettype")) {
+               return zend_compile_func_gettype(result, args);
        } else {
                return FAILURE;
        }
index 81db801783de070e4a1ba6c8b4c25d9960d53d4d..7277101efde2c7a63be2d23f63bdbe5304fc03e4 100644 (file)
@@ -416,6 +416,13 @@ EMPTY_SWITCH_DEFAULT_CASE()
        _(ZEND_STR_PATH,                   "path") \
        _(ZEND_STR_QUERY,                  "query") \
        _(ZEND_STR_FRAGMENT,               "fragment") \
+       _(ZEND_STR_NULL,                   "NULL") \
+       _(ZEND_STR_BOOLEAN,                "boolean") \
+       _(ZEND_STR_INTEGER,                "integer") \
+       _(ZEND_STR_DOUBLE,                 "double") \
+       _(ZEND_STR_ARRAY,                  "array") \
+       _(ZEND_STR_RESOURCE,               "resource") \
+       _(ZEND_STR_CLOSED_RESOURCE,        "resource (closed)") \
 
 
 typedef enum _zend_known_string_id {
index 621e5a75d0b92d2023b5eb2220c7ca9c2bc4da3c..9b8d0670bb8bf9089cc389a60e42e88473767e4d 100644 (file)
@@ -8188,6 +8188,75 @@ ZEND_VM_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED)
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
+ZEND_VM_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMP|VAR|CV, UNUSED)
+{
+       USE_OPLINE
+
+       if (OP1_TYPE == IS_UNUSED) {
+               if (UNEXPECTED(!EX(func)->common.scope)) {
+                       SAVE_OPLINE();
+                       zend_error(E_WARNING, "get_class() called without object from outside a class");
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+                       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               } else {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name);
+                       ZEND_VM_NEXT_OPCODE();
+               }
+       } else {
+               zend_free_op free_op1;
+               zval *op1;
+
+               SAVE_OPLINE();
+               op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
+               if (Z_TYPE_P(op1) == IS_OBJECT) {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
+               } else {
+                       zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1)));
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+               }
+               FREE_OP1();
+               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       }
+}
+
+ZEND_VM_HANDLER(192, ZEND_GET_CALLED_CLASS, UNUSED, UNUSED)
+{
+       USE_OPLINE
+
+       if (Z_TYPE(EX(This)) == IS_OBJECT) {
+               ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE(EX(This))->name);
+       } else if (Z_CE(EX(This))) {
+               ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_CE(EX(This))->name);
+       } else {
+               ZVAL_FALSE(EX_VAR(opline->result.var));
+               if (UNEXPECTED(!EX(func)->common.scope)) {
+                       SAVE_OPLINE();
+                       zend_error(E_WARNING, "get_called_class() called from outside a class");
+                       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               }
+       }
+       ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(193, ZEND_GET_TYPE, CONST|TMP|VAR|CV, UNUSED)
+{
+       USE_OPLINE
+       zend_free_op free_op1;
+       zval *op1;
+       zend_string *type;
+
+       SAVE_OPLINE();
+       op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
+       type = zend_zval_get_type(op1);
+       if (EXPECTED(type)) {
+               ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type);
+       } else {
+               ZVAL_STRING(EX_VAR(opline->result.var), "unknown type");
+       }
+       FREE_OP1();
+       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_ADD, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
 {
        USE_OPLINE
index b2c701c47bfb5f03305d32243b4d0e6cf1ce3d65..aa2175e4c9ad84cc4521951aa725e41fc254d8d0 100644 (file)
@@ -8115,6 +8115,56 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_UNUSED_HANDLE
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       if (IS_CONST == IS_UNUSED) {
+               if (UNEXPECTED(!EX(func)->common.scope)) {
+                       SAVE_OPLINE();
+                       zend_error(E_WARNING, "get_class() called without object from outside a class");
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+                       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               } else {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name);
+                       ZEND_VM_NEXT_OPCODE();
+               }
+       } else {
+
+               zval *op1;
+
+               SAVE_OPLINE();
+               op1 = EX_CONSTANT(opline->op1);
+               if (Z_TYPE_P(op1) == IS_OBJECT) {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
+               } else {
+                       zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1)));
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+               }
+
+               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       }
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       zval *op1;
+       zend_string *type;
+
+       SAVE_OPLINE();
+       op1 = EX_CONSTANT(opline->op1);
+       type = zend_zval_get_type(op1);
+       if (EXPECTED(type)) {
+               ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type);
+       } else {
+               ZVAL_STRING(EX_VAR(opline->result.var), "unknown type");
+       }
+
+       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -14629,6 +14679,56 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMP_UNUSED_HANDLER(
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       if (IS_TMP_VAR == IS_UNUSED) {
+               if (UNEXPECTED(!EX(func)->common.scope)) {
+                       SAVE_OPLINE();
+                       zend_error(E_WARNING, "get_class() called without object from outside a class");
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+                       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               } else {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name);
+                       ZEND_VM_NEXT_OPCODE();
+               }
+       } else {
+               zend_free_op free_op1;
+               zval *op1;
+
+               SAVE_OPLINE();
+               op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+               if (Z_TYPE_P(op1) == IS_OBJECT) {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
+               } else {
+                       zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1)));
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+               }
+               zval_ptr_dtor_nogc(free_op1);
+               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       }
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zend_free_op free_op1;
+       zval *op1;
+       zend_string *type;
+
+       SAVE_OPLINE();
+       op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+       type = zend_zval_get_type(op1);
+       if (EXPECTED(type)) {
+               ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type);
+       } else {
+               ZVAL_STRING(EX_VAR(opline->result.var), "unknown type");
+       }
+       zval_ptr_dtor_nogc(free_op1);
+       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -21751,6 +21851,56 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_VAR_UNUSED_HANDLER(
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       if (IS_VAR == IS_UNUSED) {
+               if (UNEXPECTED(!EX(func)->common.scope)) {
+                       SAVE_OPLINE();
+                       zend_error(E_WARNING, "get_class() called without object from outside a class");
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+                       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               } else {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name);
+                       ZEND_VM_NEXT_OPCODE();
+               }
+       } else {
+               zend_free_op free_op1;
+               zval *op1;
+
+               SAVE_OPLINE();
+               op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+               if (Z_TYPE_P(op1) == IS_OBJECT) {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
+               } else {
+                       zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1)));
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+               }
+               zval_ptr_dtor_nogc(free_op1);
+               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       }
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zend_free_op free_op1;
+       zval *op1;
+       zend_string *type;
+
+       SAVE_OPLINE();
+       op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+       type = zend_zval_get_type(op1);
+       if (EXPECTED(type)) {
+               ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type);
+       } else {
+               ZVAL_STRING(EX_VAR(opline->result.var), "unknown type");
+       }
+       zval_ptr_dtor_nogc(free_op1);
+       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -29263,6 +29413,56 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED
        ZEND_VM_NEXT_OPCODE();
 }
 
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       if (IS_UNUSED == IS_UNUSED) {
+               if (UNEXPECTED(!EX(func)->common.scope)) {
+                       SAVE_OPLINE();
+                       zend_error(E_WARNING, "get_class() called without object from outside a class");
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+                       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               } else {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name);
+                       ZEND_VM_NEXT_OPCODE();
+               }
+       } else {
+
+               zval *op1;
+
+               SAVE_OPLINE();
+               op1 = NULL;
+               if (Z_TYPE_P(op1) == IS_OBJECT) {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
+               } else {
+                       zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1)));
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+               }
+
+               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       }
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       if (Z_TYPE(EX(This)) == IS_OBJECT) {
+               ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE(EX(This))->name);
+       } else if (Z_CE(EX(This))) {
+               ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_CE(EX(This))->name);
+       } else {
+               ZVAL_FALSE(EX_VAR(opline->result.var));
+               if (UNEXPECTED(!EX(func)->common.scope)) {
+                       SAVE_OPLINE();
+                       zend_error(E_WARNING, "get_called_class() called from outside a class");
+                       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               }
+       }
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(binary_op_type binary_op ZEND_OPCODE_HANDLER_ARGS_DC)
 {
        USE_OPLINE
@@ -40853,6 +41053,56 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       if (IS_CV == IS_UNUSED) {
+               if (UNEXPECTED(!EX(func)->common.scope)) {
+                       SAVE_OPLINE();
+                       zend_error(E_WARNING, "get_class() called without object from outside a class");
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+                       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               } else {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name);
+                       ZEND_VM_NEXT_OPCODE();
+               }
+       } else {
+
+               zval *op1;
+
+               SAVE_OPLINE();
+               op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+               if (Z_TYPE_P(op1) == IS_OBJECT) {
+                       ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
+               } else {
+                       zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1)));
+                       ZVAL_FALSE(EX_VAR(opline->result.var));
+               }
+
+               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       }
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       zval *op1;
+       zend_string *type;
+
+       SAVE_OPLINE();
+       op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+       type = zend_zval_get_type(op1);
+       if (EXPECTED(type)) {
+               ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type);
+       } else {
+               ZVAL_STRING(EX_VAR(opline->result.var), "unknown type");
+       }
+
+       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -58165,6 +58415,81 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        (void*)&&ZEND_COUNT_SPEC_CV_UNUSED_LABEL,
                        (void*)&&ZEND_NULL_LABEL,
                        (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_GET_CLASS_SPEC_CONST_UNUSED_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_GET_CLASS_SPEC_TMP_UNUSED_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_GET_CLASS_SPEC_VAR_UNUSED_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_GET_CLASS_SPEC_CV_UNUSED_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_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_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED_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_GET_TYPE_SPEC_CONST_UNUSED_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_GET_TYPE_SPEC_TMP_UNUSED_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_GET_TYPE_SPEC_VAR_UNUSED_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_GET_TYPE_SPEC_CV_UNUSED_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
                        (void*)&&ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_LABEL,
                        (void*)&&ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_LABEL,
                        (void*)&&ZEND_NULL_LABEL,
@@ -59673,6 +59998,12 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        HYBRID_CASE(ZEND_COUNT_SPEC_CONST_UNUSED):
                                ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_GET_CLASS_SPEC_CONST_UNUSED):
+                               ZEND_GET_CLASS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_GET_TYPE_SPEC_CONST_UNUSED):
+                               ZEND_GET_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
                        HYBRID_CASE(ZEND_ADD_SPEC_CONST_CV):
                                ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
@@ -60111,6 +60442,12 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        HYBRID_CASE(ZEND_COUNT_SPEC_TMP_UNUSED):
                                ZEND_COUNT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_GET_CLASS_SPEC_TMP_UNUSED):
+                               ZEND_GET_CLASS_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_GET_TYPE_SPEC_TMP_UNUSED):
+                               ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
                        HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_TMP_CV):
                                ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
@@ -60582,6 +60919,12 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        HYBRID_CASE(ZEND_COUNT_SPEC_VAR_UNUSED):
                                ZEND_COUNT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_GET_CLASS_SPEC_VAR_UNUSED):
+                               ZEND_GET_CLASS_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_GET_TYPE_SPEC_VAR_UNUSED):
+                               ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
                        HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_VAR_CV):
                                ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
@@ -61104,6 +61447,12 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        HYBRID_CASE(ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED):
                                ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_GET_CLASS_SPEC_UNUSED_UNUSED):
+                               ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED):
+                               ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
                        HYBRID_CASE(ZEND_ASSIGN_ADD_SPEC_UNUSED_CV_OBJ):
                                ZEND_ASSIGN_ADD_SPEC_UNUSED_CV_OBJ_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
@@ -61923,6 +62272,12 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        HYBRID_CASE(ZEND_COUNT_SPEC_CV_UNUSED):
                                ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_GET_CLASS_SPEC_CV_UNUSED):
+                               ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_GET_TYPE_SPEC_CV_UNUSED):
+                               ZEND_GET_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
                        HYBRID_CASE(ZEND_ADD_SPEC_CV_CV):
                                ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
@@ -66879,6 +67234,81 @@ void zend_init_opcodes_handlers(void)
                ZEND_COUNT_SPEC_CV_UNUSED_HANDLER,
                ZEND_NULL_HANDLER,
                ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_GET_CLASS_SPEC_CONST_UNUSED_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_GET_CLASS_SPEC_TMP_UNUSED_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_GET_CLASS_SPEC_VAR_UNUSED_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_GET_CLASS_SPEC_CV_UNUSED_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_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_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED_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_GET_TYPE_SPEC_CONST_UNUSED_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_GET_TYPE_SPEC_VAR_UNUSED_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_GET_TYPE_SPEC_CV_UNUSED_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
                ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_HANDLER,
                ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_HANDLER,
                ZEND_NULL_HANDLER,
@@ -67946,7 +68376,7 @@ void zend_init_opcodes_handlers(void)
                2257 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                2282 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                2307 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               4696,
+               4771,
                2332,
                2333,
                2334,
@@ -68031,13 +68461,16 @@ void zend_init_opcodes_handlers(void)
                3531 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                3556 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                3581 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               4696,
+               4771,
                3606 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                3631 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                3656 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                3681 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                3706 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               4696
+               3731 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               3756 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               3781 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               4771
        };
 #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
        zend_opcode_handler_funcs = labels;
@@ -68232,7 +68665,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3731 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3806 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68240,7 +68673,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3756 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3831 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68248,7 +68681,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3781 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3856 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68259,17 +68692,17 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3806 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3881 | 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 = 3831 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3906 | 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 = 3856 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3931 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                        }
                        break;
                case ZEND_MUL:
@@ -68277,7 +68710,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3881 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3956 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68285,7 +68718,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3906 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3981 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68293,7 +68726,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3931 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 4006 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68304,7 +68737,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3956 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4031 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68312,7 +68745,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 4031 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4106 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68323,7 +68756,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 4106 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4181 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68331,7 +68764,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 4181 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4256 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68342,12 +68775,12 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 4256 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4331 | 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 = 4331 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4406 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                        }
                        break;
                case ZEND_IS_SMALLER_OR_EQUAL:
@@ -68355,70 +68788,70 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 4406 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4481 | 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 = 4481 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4556 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                        }
                        break;
                case ZEND_QM_ASSIGN:
                        if (op1_info == MAY_BE_DOUBLE) {
-                               spec = 4646 | SPEC_RULE_OP1;
+                               spec = 4721 | SPEC_RULE_OP1;
                        } else if (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)))) {
-                               spec = 4651 | SPEC_RULE_OP1;
+                               spec = 4726 | SPEC_RULE_OP1;
                        }
                        break;
                case ZEND_PRE_INC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 4556 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4631 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 4566 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4641 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 4576 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4651 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        }
                        break;
                case ZEND_PRE_DEC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 4586 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4661 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 4596 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4671 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 4606 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4681 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        }
                        break;
                case ZEND_POST_INC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 4616 | SPEC_RULE_OP1;
+                               spec = 4691 | SPEC_RULE_OP1;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 4621 | SPEC_RULE_OP1;
+                               spec = 4696 | SPEC_RULE_OP1;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 4626 | SPEC_RULE_OP1;
+                               spec = 4701 | SPEC_RULE_OP1;
                        }
                        break;
                case ZEND_POST_DEC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 4631 | SPEC_RULE_OP1;
+                               spec = 4706 | SPEC_RULE_OP1;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 4636 | SPEC_RULE_OP1;
+                               spec = 4711 | SPEC_RULE_OP1;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 4641 | SPEC_RULE_OP1;
+                               spec = 4716 | SPEC_RULE_OP1;
                        }
                        break;
                case ZEND_SEND_VAR_EX:
                        if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
-                               spec = 4686 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG;
+                               spec = 4761 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG;
                        }
                        break;
                case ZEND_FETCH_DIM_R:
                        if (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) {
-                               spec = 4656 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 4731 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                        }
                        break;
                case ZEND_SEND_VAR:
                        if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
-                               spec = 4681 | SPEC_RULE_OP1;
+                               spec = 4756 | SPEC_RULE_OP1;
                        }
                        break;
                default:
index 22349193f9970ad484c2bc1f0bb422d0475905f6..0d0fc51455cbd7724322d73611c3c8a8901c69d7 100644 (file)
@@ -21,7 +21,7 @@
 #include <stdio.h>
 #include <zend.h>
 
-static const char *zend_vm_opcodes_names[191] = {
+static const char *zend_vm_opcodes_names[194] = {
        "ZEND_NOP",
        "ZEND_ADD",
        "ZEND_SUB",
@@ -213,9 +213,12 @@ static const char *zend_vm_opcodes_names[191] = {
        "ZEND_SWITCH_STRING",
        "ZEND_IN_ARRAY",
        "ZEND_COUNT",
+       "ZEND_GET_CLASS",
+       "ZEND_GET_CALLED_CLASS",
+       "ZEND_GET_TYPE",
 };
 
-static uint32_t zend_vm_opcodes_flags[191] = {
+static uint32_t zend_vm_opcodes_flags[194] = {
        0x00000000,
        0x00000707,
        0x00000707,
@@ -407,6 +410,9 @@ static uint32_t zend_vm_opcodes_flags[191] = {
        0x03000307,
        0x01000303,
        0x00000103,
+       0x00000103,
+       0x00000101,
+       0x00000103,
 };
 
 ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {
index 60a1a26168f702c994945bee79207d49e5d08342..ed4bb73b27c6e90607697b41ed1438955b80c4d7 100644 (file)
@@ -262,7 +262,10 @@ END_EXTERN_C()
 #define ZEND_SWITCH_STRING                   188
 #define ZEND_IN_ARRAY                        189
 #define ZEND_COUNT                           190
+#define ZEND_GET_CLASS                       191
+#define ZEND_GET_CALLED_CLASS                192
+#define ZEND_GET_TYPE                        193
 
-#define ZEND_VM_LAST_OPCODE                  190
+#define ZEND_VM_LAST_OPCODE                  193
 
 #endif
index d9fc42bf806a482a6ad895d5affa6a7f0891eae9..f9992d539a9577230ee38aed7036a79e8e48edb7 100644 (file)
@@ -589,7 +589,7 @@ static const func_info_t func_infos[] = {
        F0("doubleval",                    MAY_BE_NULL | MAY_BE_DOUBLE),
        FN("strval",                       MAY_BE_NULL | MAY_BE_STRING),
        F0("boolval",                      MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE),
-       F1("gettype",                      MAY_BE_NULL | MAY_BE_STRING),
+       FN("gettype",                      MAY_BE_NULL | MAY_BE_STRING),
        F0("settype",                      MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE),
        FC("is_null",                      zend_is_type_info),
        F0("is_resource",                  MAY_BE_FALSE | MAY_BE_TRUE), // TODO: inline with support for closed resources
index 01d40bf15d8eac1a2a09a3a92453defaba57c650..ee242c4253215f04c92cd23135637e0d559ab2f6 100644 (file)
@@ -3163,6 +3163,13 @@ static void zend_update_type_info(const zend_op_array *op_array,
                case ZEND_COUNT:
                        UPDATE_SSA_TYPE(MAY_BE_LONG, ssa_ops[i].result_def);
                        break;
+               case ZEND_GET_CLASS:
+               case ZEND_GET_CALLED_CLASS:
+                       UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_STRING, ssa_ops[i].result_def);
+                       break;
+               case ZEND_GET_TYPE:
+                       UPDATE_SSA_TYPE(MAY_BE_STRING, ssa_ops[i].result_def);
+                       break;
                case ZEND_TYPE_CHECK:
                case ZEND_DEFINED:
                        UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_TRUE, ssa_ops[i].result_def);
index a8000504628f28eabfaf5c9d9cb41e7829a913e8..1df5a63eccd552cebaf4011e573ebcf961cc7d2a 100644 (file)
 PHP_FUNCTION(gettype)
 {
        zval *arg;
+       zend_string *type;
 
        ZEND_PARSE_PARAMETERS_START(1, 1)
                Z_PARAM_ZVAL_DEREF(arg)
        ZEND_PARSE_PARAMETERS_END();
 
-       switch (Z_TYPE_P(arg)) {
-               case IS_NULL:
-                       RETVAL_STRING("NULL");
-                       break;
-
-               case IS_FALSE:
-               case IS_TRUE:
-                       RETVAL_STRING("boolean");
-                       break;
-
-               case IS_LONG:
-                       RETVAL_STRING("integer");
-                       break;
-
-               case IS_DOUBLE:
-                       RETVAL_STRING("double");
-                       break;
-
-               case IS_STRING:
-                       RETVAL_STRING("string");
-                       break;
-
-               case IS_ARRAY:
-                       RETVAL_STRING("array");
-                       break;
-
-               case IS_OBJECT:
-                       RETVAL_STRING("object");
-                       break;
-
-               case IS_RESOURCE:
-                       {
-                               const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
-
-                               if (type_name) {
-                                       RETVAL_STRING("resource");
-                               } else {
-                                       RETVAL_STRING("resource (closed)");
-                               }
-                               break;
-                       }
-
-               default:
-                       RETVAL_STRING("unknown type");
+       type = zend_zval_get_type(arg);
+       if (EXPECTED(type)) {
+               RETURN_INTERNED_STR(type);
+       } else {
+               RETURN_STRING("unknown type");
        }
 }
 /* }}} */