break;
}
}
- }
- if (opcode == ZEND_CONCAT) {
+ } else if (opcode == ZEND_IS_IDENTICAL || opcode == ZEND_IS_NOT_IDENTICAL) {
+ /* convert $x === null to is_null($x) (i.e. ZEND_TYPE_CHECK opcode). Do the same thing for false/true. (covers IS_NULL, IS_FALSE, and IS_TRUE) */
+ if (left_node.op_type == IS_CONST) {
+ if (Z_TYPE(left_node.u.constant) <= IS_TRUE && Z_TYPE(left_node.u.constant) >= IS_NULL) {
+ zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &right_node, NULL);
+ opline->extended_value =
+ (opcode == ZEND_IS_IDENTICAL) ?
+ (1 << Z_TYPE(left_node.u.constant)) :
+ (MAY_BE_ANY - (1 << Z_TYPE(left_node.u.constant)));
+ return;
+ }
+ } else if (right_node.op_type == IS_CONST) {
+ if (Z_TYPE(right_node.u.constant) <= IS_TRUE && Z_TYPE(right_node.u.constant) >= IS_NULL) {
+ zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &left_node, NULL);
+ opline->extended_value =
+ (opcode == ZEND_IS_IDENTICAL) ?
+ (1 << Z_TYPE(right_node.u.constant)) :
+ (MAY_BE_ANY - (1 << Z_TYPE(right_node.u.constant)));
+ return;
+ }
+ }
+ } else if (opcode == ZEND_CONCAT) {
/* convert constant operands to strings at compile-time */
if (left_node.op_type == IS_CONST) {
if (Z_TYPE(left_node.u.constant) == IS_ARRAY) {
value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) {
ZEND_VM_C_LABEL(type_check_resource):
- if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE)
+ if (opline->extended_value != MAY_BE_RESOURCE
|| EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) {
result = 1;
}
value = RT_CONSTANT(opline, opline->op1);
if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) {
type_check_resource:
- if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE)
+ if (opline->extended_value != MAY_BE_RESOURCE
|| EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) {
result = 1;
}
value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC);
if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) {
type_check_resource:
- if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE)
+ if (opline->extended_value != MAY_BE_RESOURCE
|| EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) {
result = 1;
}
value = EX_VAR(opline->op1.var);
if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) {
type_check_resource:
- if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE)
+ if (opline->extended_value != MAY_BE_RESOURCE
|| EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) {
result = 1;
}
fprintf(stderr, " (bool)");
break;
default:
- fprintf(stderr, " (\?\?\?)");
+ fprintf(stderr, " TYPE");
+ zend_dump_type_info(opline->extended_value, NULL, 0, dump_flags);
break;
}
} else if (ZEND_VM_EXT_EVAL == (flags & ZEND_VM_EXT_MASK)) {
}
static inline uint32_t mask_for_type_check(uint32_t type) {
if (type & MAY_BE_ARRAY) {
- return MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
+ return type | (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
} else {
return type;
}
zend_bool smart_branch = 0;
zend_jit_addr op1_addr = zend_jit_decode_op(op_array, opline->op1_type, opline->op1, opline, NULL, -1);
- if (opline->extended_value & MAY_BE_RESOURCE) {
+ if (opline->extended_value == MAY_BE_RESOURCE) {
// TODO: support for is_resource() ???
goto fallback;
}