Skip to content

Commit f00d1c7

Browse files
committed
Added ZEND_GET_CLASS, ZEMD_GET_CALLED_CLASS, ZEND_GET_TYPE instructions, to implement corresponding builtin functions.
1 parent 546dd2a commit f00d1c7

File tree

12 files changed

+656
-86
lines changed

12 files changed

+656
-86
lines changed

NEWS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ PHP NEWS
33
?? ??? ????, PHP 7.2
44

55
- Core:
6-
. Added ZEND_COUNT instruction, to implement corresponding builtin. (Dmitry)
6+
. Added ZEND_COUNT, ZEND_GET_CLASS, ZEMD_GET_CALLED_CLASS, ZEND_GET_TYPE
7+
instructions, to implement corresponding builtin functions. (Dmitry)
78
. "Countable" interface is moved from SPL to Core. (Dmitry)
89
. Added ZEND_IN_ARRAY instruction, implementing optimized in_array() builtin
910
function, through hash lookup in flipped array. (Dmitry)

Zend/zend_API.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,36 @@ ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
202202
}
203203
/* }}} */
204204

205+
ZEND_API zend_string *zend_zval_get_type(const zval *arg) /* {{{ */
206+
{
207+
switch (Z_TYPE_P(arg)) {
208+
case IS_NULL:
209+
return ZSTR_KNOWN(ZEND_STR_NULL);
210+
case IS_FALSE:
211+
case IS_TRUE:
212+
return ZSTR_KNOWN(ZEND_STR_BOOLEAN);
213+
case IS_LONG:
214+
return ZSTR_KNOWN(ZEND_STR_INTEGER);
215+
case IS_DOUBLE:
216+
return ZSTR_KNOWN(ZEND_STR_DOUBLE);
217+
case IS_STRING:
218+
return ZSTR_KNOWN(ZEND_STR_STRING);
219+
case IS_ARRAY:
220+
return ZSTR_KNOWN(ZEND_STR_ARRAY);
221+
case IS_OBJECT:
222+
return ZSTR_KNOWN(ZEND_STR_OBJECT);
223+
case IS_RESOURCE:
224+
if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {
225+
return ZSTR_KNOWN(ZEND_STR_RESOURCE);
226+
} else {
227+
return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);
228+
}
229+
default:
230+
return NULL;
231+
}
232+
}
233+
/* }}} */
234+
205235
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) /* {{{ */
206236
{
207237
zend_function *active_function = EG(current_execute_data)->func;

Zend/zend_API.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...);
277277
ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...);
278278
ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ...);
279279
ZEND_API char *zend_zval_type_name(const zval *arg);
280+
ZEND_API zend_string *zend_zval_get_type(const zval *arg);
280281

281282
ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const char *type_spec, ...);
282283
ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this_ptr, const char *type_spec, ...);

Zend/zend_compile.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3737,6 +3737,51 @@ int zend_compile_func_count(znode *result, zend_ast_list *args) /* {{{ */
37373737
}
37383738
/* }}} */
37393739

3740+
int zend_compile_func_get_class(znode *result, zend_ast_list *args) /* {{{ */
3741+
{
3742+
if (args->children == 0) {
3743+
zend_emit_op_tmp(result, ZEND_GET_CLASS, NULL, NULL);
3744+
} else {
3745+
znode arg_node;
3746+
3747+
if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
3748+
return FAILURE;
3749+
}
3750+
3751+
zend_compile_expr(&arg_node, args->child[0]);
3752+
zend_emit_op_tmp(result, ZEND_GET_CLASS, &arg_node, NULL);
3753+
}
3754+
return SUCCESS;
3755+
}
3756+
/* }}} */
3757+
3758+
int zend_compile_func_get_called_class(znode *result, zend_ast_list *args) /* {{{ */
3759+
{
3760+
znode arg_node;
3761+
3762+
if (args->children != 0) {
3763+
return FAILURE;
3764+
}
3765+
3766+
zend_emit_op_tmp(result, ZEND_GET_CALLED_CLASS, &arg_node, NULL);
3767+
return SUCCESS;
3768+
}
3769+
/* }}} */
3770+
3771+
int zend_compile_func_gettype(znode *result, zend_ast_list *args) /* {{{ */
3772+
{
3773+
znode arg_node;
3774+
3775+
if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
3776+
return FAILURE;
3777+
}
3778+
3779+
zend_compile_expr(&arg_node, args->child[0]);
3780+
zend_emit_op_tmp(result, ZEND_GET_TYPE, &arg_node, NULL);
3781+
return SUCCESS;
3782+
}
3783+
/* }}} */
3784+
37403785
int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */
37413786
{
37423787
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
37993844
return zend_compile_func_in_array(result, args);
38003845
} else if (zend_string_equals_literal(lcname, "count")) {
38013846
return zend_compile_func_count(result, args);
3847+
} else if (zend_string_equals_literal(lcname, "get_class")) {
3848+
return zend_compile_func_get_class(result, args);
3849+
} else if (zend_string_equals_literal(lcname, "get_called_class")) {
3850+
return zend_compile_func_get_called_class(result, args);
3851+
} else if (zend_string_equals_literal(lcname, "gettype")) {
3852+
return zend_compile_func_gettype(result, args);
38023853
} else {
38033854
return FAILURE;
38043855
}

Zend/zend_string.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,13 @@ EMPTY_SWITCH_DEFAULT_CASE()
416416
_(ZEND_STR_PATH, "path") \
417417
_(ZEND_STR_QUERY, "query") \
418418
_(ZEND_STR_FRAGMENT, "fragment") \
419+
_(ZEND_STR_NULL, "NULL") \
420+
_(ZEND_STR_BOOLEAN, "boolean") \
421+
_(ZEND_STR_INTEGER, "integer") \
422+
_(ZEND_STR_DOUBLE, "double") \
423+
_(ZEND_STR_ARRAY, "array") \
424+
_(ZEND_STR_RESOURCE, "resource") \
425+
_(ZEND_STR_CLOSED_RESOURCE, "resource (closed)") \
419426

420427

421428
typedef enum _zend_known_string_id {

Zend/zend_vm_def.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8188,6 +8188,75 @@ ZEND_VM_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED)
81888188
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
81898189
}
81908190

8191+
ZEND_VM_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMP|VAR|CV, UNUSED)
8192+
{
8193+
USE_OPLINE
8194+
8195+
if (OP1_TYPE == IS_UNUSED) {
8196+
if (UNEXPECTED(!EX(func)->common.scope)) {
8197+
SAVE_OPLINE();
8198+
zend_error(E_WARNING, "get_class() called without object from outside a class");
8199+
ZVAL_FALSE(EX_VAR(opline->result.var));
8200+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8201+
} else {
8202+
ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name);
8203+
ZEND_VM_NEXT_OPCODE();
8204+
}
8205+
} else {
8206+
zend_free_op free_op1;
8207+
zval *op1;
8208+
8209+
SAVE_OPLINE();
8210+
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
8211+
if (Z_TYPE_P(op1) == IS_OBJECT) {
8212+
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
8213+
} else {
8214+
zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1)));
8215+
ZVAL_FALSE(EX_VAR(opline->result.var));
8216+
}
8217+
FREE_OP1();
8218+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8219+
}
8220+
}
8221+
8222+
ZEND_VM_HANDLER(192, ZEND_GET_CALLED_CLASS, UNUSED, UNUSED)
8223+
{
8224+
USE_OPLINE
8225+
8226+
if (Z_TYPE(EX(This)) == IS_OBJECT) {
8227+
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE(EX(This))->name);
8228+
} else if (Z_CE(EX(This))) {
8229+
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_CE(EX(This))->name);
8230+
} else {
8231+
ZVAL_FALSE(EX_VAR(opline->result.var));
8232+
if (UNEXPECTED(!EX(func)->common.scope)) {
8233+
SAVE_OPLINE();
8234+
zend_error(E_WARNING, "get_called_class() called from outside a class");
8235+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8236+
}
8237+
}
8238+
ZEND_VM_NEXT_OPCODE();
8239+
}
8240+
8241+
ZEND_VM_HANDLER(193, ZEND_GET_TYPE, CONST|TMP|VAR|CV, UNUSED)
8242+
{
8243+
USE_OPLINE
8244+
zend_free_op free_op1;
8245+
zval *op1;
8246+
zend_string *type;
8247+
8248+
SAVE_OPLINE();
8249+
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
8250+
type = zend_zval_get_type(op1);
8251+
if (EXPECTED(type)) {
8252+
ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type);
8253+
} else {
8254+
ZVAL_STRING(EX_VAR(opline->result.var), "unknown type");
8255+
}
8256+
FREE_OP1();
8257+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8258+
}
8259+
81918260
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))
81928261
{
81938262
USE_OPLINE

0 commit comments

Comments
 (0)