mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Support for IS_IDENTICAL/IS_NOT_IDENTICAL
This commit is contained in:
@@ -1078,8 +1078,9 @@ static void* dasm_labels[zend_lb_MAX];
|
||||
| bne label
|
||||
|.endmacro
|
||||
|
||||
|.macro IF_Z_TYPE, zv, val, label
|
||||
| IF_TYPE byte [zv+offsetof(zval, u1.v.type)], val, label
|
||||
|.macro IF_Z_TYPE, zv, val, label, tmp_reg
|
||||
| ldrb tmp_reg, [zv, #offsetof(zval, u1.v.type)]
|
||||
| IF_TYPE tmp_reg, val, label
|
||||
|.endmacro
|
||||
|
||||
|.macro IF_NOT_Z_TYPE, zv, val, label, tmp_reg
|
||||
@@ -6127,7 +6128,387 @@ static int zend_jit_identical(dasm_State **Dst,
|
||||
uint32_t identical_label = (uint32_t)-1;
|
||||
uint32_t not_identical_label = (uint32_t)-1;
|
||||
|
||||
| NIY // TODO
|
||||
if (smart_branch_opcode && !exit_addr) {
|
||||
if (opline->opcode != ZEND_IS_NOT_IDENTICAL) {
|
||||
if (smart_branch_opcode == ZEND_JMPZ) {
|
||||
not_identical_label = target_label;
|
||||
} else if (smart_branch_opcode == ZEND_JMPNZ) {
|
||||
identical_label = target_label;
|
||||
} else if (smart_branch_opcode == ZEND_JMPZNZ) {
|
||||
not_identical_label = target_label;
|
||||
identical_label = target_label2;
|
||||
} else {
|
||||
ZEND_UNREACHABLE();
|
||||
}
|
||||
} else {
|
||||
if (smart_branch_opcode == ZEND_JMPZ) {
|
||||
identical_label = target_label;
|
||||
} else if (smart_branch_opcode == ZEND_JMPNZ) {
|
||||
not_identical_label = target_label;
|
||||
} else if (smart_branch_opcode == ZEND_JMPZNZ) {
|
||||
identical_label = target_label;
|
||||
not_identical_label = target_label2;
|
||||
} else {
|
||||
ZEND_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((op1_info & (MAY_BE_REF|MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG &&
|
||||
(op2_info & (MAY_BE_REF|MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) {
|
||||
if (!zend_jit_cmp_long_long(Dst, opline, op1_range, op1_addr, op2_range, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr, skip_comparison)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
} else if ((op1_info & (MAY_BE_REF|MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_DOUBLE &&
|
||||
(op2_info & (MAY_BE_REF|MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_DOUBLE) {
|
||||
if (!zend_jit_cmp_double_double(Dst, opline, op1_addr, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((op1_info & MAY_BE_UNDEF) && (op2_info & MAY_BE_UNDEF)) {
|
||||
op1_info |= MAY_BE_NULL;
|
||||
op2_info |= MAY_BE_NULL;
|
||||
| LOAD_ZVAL_ADDR FCARG1x, op1_addr
|
||||
| IF_Z_TYPE FCARG1x, IS_UNDEF, >1, TMP1w
|
||||
|.cold_code
|
||||
|1:
|
||||
| // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))));
|
||||
| SET_EX_OPLINE opline, REG0
|
||||
| LOAD_32BIT_VAL FCARG1w, opline->op1.var
|
||||
| EXT_CALL zend_jit_undefined_op_helper, REG0
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception_undef_result(Dst, opline);
|
||||
}
|
||||
| LOAD_ADDR_ZTS FCARG1x, executor_globals, uninitialized_zval
|
||||
| b >1
|
||||
|.code
|
||||
|1:
|
||||
| LOAD_ZVAL_ADDR FCARG2x, op2_addr
|
||||
| IF_Z_TYPE FCARG2x, IS_UNDEF, >1, TMP1w
|
||||
|.cold_code
|
||||
|1:
|
||||
| // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))));
|
||||
| SET_EX_OPLINE opline, REG0
|
||||
| str FCARG1x, T1 // save
|
||||
| LOAD_32BIT_VAL FCARG1w, opline->op2.var
|
||||
| EXT_CALL zend_jit_undefined_op_helper, REG0
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception_undef_result(Dst, opline);
|
||||
}
|
||||
| ldr FCARG1x, T1 // restore
|
||||
| LOAD_ADDR_ZTS FCARG2x, executor_globals, uninitialized_zval
|
||||
| b >1
|
||||
|.code
|
||||
|1:
|
||||
} else if (op1_info & MAY_BE_UNDEF) {
|
||||
op1_info |= MAY_BE_NULL;
|
||||
| LOAD_ZVAL_ADDR FCARG1x, op1_addr
|
||||
| IF_Z_TYPE FCARG1x, IS_UNDEF, >1, TMP1w
|
||||
|.cold_code
|
||||
|1:
|
||||
| // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))));
|
||||
| SET_EX_OPLINE opline, REG0
|
||||
| LOAD_32BIT_VAL FCARG1w, opline->op1.var
|
||||
| EXT_CALL zend_jit_undefined_op_helper, REG0
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception_undef_result(Dst, opline);
|
||||
}
|
||||
| LOAD_ADDR_ZTS FCARG1x, executor_globals, uninitialized_zval
|
||||
| b >1
|
||||
|.code
|
||||
|1:
|
||||
if (opline->op2_type != IS_CONST) {
|
||||
| LOAD_ZVAL_ADDR FCARG2x, op2_addr
|
||||
}
|
||||
} else if (op2_info & MAY_BE_UNDEF) {
|
||||
op2_info |= MAY_BE_NULL;
|
||||
| LOAD_ZVAL_ADDR FCARG2x, op2_addr
|
||||
| IF_Z_TYPE FCARG2x, IS_UNDEF, >1, TMP1w
|
||||
|.cold_code
|
||||
|1:
|
||||
| // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))));
|
||||
| SET_EX_OPLINE opline, REG0
|
||||
| LOAD_32BIT_VAL FCARG1w, opline->op2.var
|
||||
| EXT_CALL zend_jit_undefined_op_helper, REG0
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception_undef_result(Dst, opline);
|
||||
}
|
||||
| LOAD_ADDR_ZTS FCARG2x, executor_globals, uninitialized_zval
|
||||
| b >1
|
||||
|.code
|
||||
|1:
|
||||
if (opline->op1_type != IS_CONST) {
|
||||
| LOAD_ZVAL_ADDR FCARG1x, op1_addr
|
||||
}
|
||||
} else if ((op1_info & op2_info & MAY_BE_ANY) != 0) {
|
||||
if (opline->op1_type != IS_CONST) {
|
||||
if (Z_MODE(op1_addr) == IS_REG) {
|
||||
zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op1.var);
|
||||
if (!zend_jit_spill_store(Dst, op1_addr, real_addr, op1_info, 1)) {
|
||||
return 0;
|
||||
}
|
||||
op1_addr = real_addr;
|
||||
}
|
||||
| LOAD_ZVAL_ADDR FCARG1x, op1_addr
|
||||
}
|
||||
if (opline->op2_type != IS_CONST) {
|
||||
if (Z_MODE(op2_addr) == IS_REG) {
|
||||
zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
|
||||
if (!zend_jit_spill_store(Dst, op2_addr, real_addr, op2_info, 1)) {
|
||||
return 0;
|
||||
}
|
||||
op2_addr = real_addr;
|
||||
}
|
||||
| LOAD_ZVAL_ADDR FCARG2x, op2_addr
|
||||
}
|
||||
}
|
||||
|
||||
if ((op1_info & op2_info & MAY_BE_ANY) == 0) {
|
||||
if ((opline->opcode != ZEND_CASE_STRICT &&
|
||||
(opline->op1_type & (IS_VAR|IS_TMP_VAR)) &&
|
||||
(op1_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) ||
|
||||
((opline->op2_type & (IS_VAR|IS_TMP_VAR)) &&
|
||||
(op2_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)))) {
|
||||
| SET_EX_OPLINE opline, REG0
|
||||
if (opline->opcode != ZEND_CASE_STRICT) {
|
||||
| FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline, ZREG_TMP1, ZREG_TMP2
|
||||
}
|
||||
| FREE_OP opline->op2_type, opline->op2, op2_info, 1, opline, ZREG_TMP1, ZREG_TMP2
|
||||
}
|
||||
if (smart_branch_opcode) {
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception_undef_result(Dst, opline);
|
||||
}
|
||||
if (exit_addr) {
|
||||
if (smart_branch_opcode == ZEND_JMPZ) {
|
||||
| NIY // b &exit_addr
|
||||
}
|
||||
} else if (not_identical_label != (uint32_t)-1) {
|
||||
| b =>not_identical_label
|
||||
}
|
||||
} else {
|
||||
| SET_ZVAL_TYPE_INFO res_addr, (opline->opcode != ZEND_IS_NOT_IDENTICAL ? IS_FALSE : IS_TRUE), TMP1w, TMP2
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception(Dst);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (opline->op1_type & (IS_CV|IS_VAR)) {
|
||||
| ZVAL_DEREF FCARG1x, op1_info, TMP1w
|
||||
}
|
||||
if (opline->op2_type & (IS_CV|IS_VAR)) {
|
||||
| ZVAL_DEREF FCARG2x, op2_info, TMP1w
|
||||
}
|
||||
|
||||
if (has_concrete_type(op1_info)
|
||||
&& has_concrete_type(op2_info)
|
||||
&& concrete_type(op1_info) == concrete_type(op2_info)
|
||||
&& concrete_type(op1_info) <= IS_TRUE) {
|
||||
if (smart_branch_opcode) {
|
||||
if (exit_addr) {
|
||||
if (smart_branch_opcode == ZEND_JMPNZ) {
|
||||
| NIY // b &exit_addr
|
||||
}
|
||||
} else if (identical_label != (uint32_t)-1) {
|
||||
| b =>identical_label
|
||||
}
|
||||
} else {
|
||||
| SET_ZVAL_TYPE_INFO res_addr, (opline->opcode != ZEND_IS_NOT_IDENTICAL ? IS_TRUE : IS_FALSE), TMP1w, TMP2
|
||||
}
|
||||
} else if (Z_MODE(op1_addr) == IS_CONST_ZVAL && Z_MODE(op2_addr) == IS_CONST_ZVAL) {
|
||||
if (zend_is_identical(Z_ZV(op1_addr), Z_ZV(op2_addr))) {
|
||||
if (smart_branch_opcode) {
|
||||
if (exit_addr) {
|
||||
if (smart_branch_opcode == ZEND_JMPNZ) {
|
||||
| NIY // b &exit_addr
|
||||
}
|
||||
} else if (identical_label != (uint32_t)-1) {
|
||||
| b =>identical_label
|
||||
}
|
||||
} else {
|
||||
| SET_ZVAL_TYPE_INFO res_addr, (opline->opcode != ZEND_IS_NOT_IDENTICAL ? IS_TRUE : IS_FALSE), TMP1w, TMP2
|
||||
}
|
||||
} else {
|
||||
if (smart_branch_opcode) {
|
||||
if (exit_addr) {
|
||||
if (smart_branch_opcode == ZEND_JMPZ) {
|
||||
| NIY // b &exit_addr
|
||||
}
|
||||
} else if (not_identical_label != (uint32_t)-1) {
|
||||
| b =>not_identical_label
|
||||
}
|
||||
} else {
|
||||
| SET_ZVAL_TYPE_INFO res_addr, (opline->opcode != ZEND_IS_NOT_IDENTICAL ? IS_FALSE : IS_TRUE), TMP1w, TMP2
|
||||
}
|
||||
}
|
||||
} else if (Z_MODE(op1_addr) == IS_CONST_ZVAL && Z_TYPE_P(Z_ZV(op1_addr)) <= IS_TRUE) {
|
||||
zval *val = Z_ZV(op1_addr);
|
||||
|
||||
| ldrb TMP1w, [FCARG2x, #offsetof(zval, u1.v.type)]
|
||||
| cmp TMP1w, #Z_TYPE_P(val)
|
||||
if (smart_branch_opcode) {
|
||||
if (opline->op2_type == IS_VAR && (op2_info & MAY_BE_REF)) {
|
||||
| bne >8
|
||||
| SET_EX_OPLINE opline, REG0
|
||||
| FREE_OP opline->op2_type, opline->op2, op2_info, 1, opline, ZREG_TMP1, ZREG_TMP2
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception_undef_result(Dst, opline);
|
||||
}
|
||||
if (exit_addr && smart_branch_opcode == ZEND_JMPNZ) {
|
||||
| NIY // b &exit_addr
|
||||
} else if (identical_label != (uint32_t)-1) {
|
||||
| b =>identical_label
|
||||
} else {
|
||||
| b >9
|
||||
}
|
||||
|8:
|
||||
} else if (exit_addr && smart_branch_opcode == ZEND_JMPNZ) {
|
||||
| NIY // beq &exit_addr
|
||||
} else if (identical_label != (uint32_t)-1) {
|
||||
| beq =>identical_label
|
||||
} else {
|
||||
| beq >9
|
||||
}
|
||||
} else {
|
||||
if (opline->opcode != ZEND_IS_NOT_IDENTICAL) {
|
||||
| cset REG0w, eq
|
||||
} else {
|
||||
| cset REG0w, ne
|
||||
}
|
||||
| add REG0w, REG0w, #2
|
||||
| SET_ZVAL_TYPE_INFO_FROM_REG res_addr, REG0w, TMP1
|
||||
}
|
||||
if ((opline->op2_type & (IS_VAR|IS_TMP_VAR)) &&
|
||||
(op2_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) {
|
||||
| SET_EX_OPLINE opline, REG0
|
||||
| FREE_OP opline->op2_type, opline->op2, op2_info, 1, opline, ZREG_TMP1, ZREG_TMP2
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception_undef_result(Dst, opline);
|
||||
}
|
||||
}
|
||||
if (exit_addr) {
|
||||
if (smart_branch_opcode == ZEND_JMPZ) {
|
||||
| NIY // b &exit_addr
|
||||
}
|
||||
} else if (smart_branch_opcode && not_identical_label != (uint32_t)-1) {
|
||||
| b =>not_identical_label
|
||||
}
|
||||
} else if (Z_MODE(op2_addr) == IS_CONST_ZVAL && Z_TYPE_P(Z_ZV(op2_addr)) <= IS_TRUE) {
|
||||
zval *val = Z_ZV(op2_addr);
|
||||
|
||||
| ldrb TMP1w, [FCARG1x, #offsetof(zval, u1.v.type)]
|
||||
| cmp TMP1w, #Z_TYPE_P(val)
|
||||
if (smart_branch_opcode) {
|
||||
if (opline->opcode != ZEND_CASE_STRICT
|
||||
&& opline->op1_type == IS_VAR && (op1_info & MAY_BE_REF)) {
|
||||
| bne >8
|
||||
| SET_EX_OPLINE opline, REG0
|
||||
| FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline, ZREG_TMP1, ZREG_TMP2
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception_undef_result(Dst, opline);
|
||||
}
|
||||
if (exit_addr && smart_branch_opcode == ZEND_JMPNZ) {
|
||||
| NIY // b &exit_addr
|
||||
} else if (identical_label != (uint32_t)-1) {
|
||||
| b =>identical_label
|
||||
} else {
|
||||
| b >9
|
||||
}
|
||||
|8:
|
||||
} else if (exit_addr && smart_branch_opcode == ZEND_JMPNZ) {
|
||||
| NIY // beq &exit_addr
|
||||
} else if (identical_label != (uint32_t)-1) {
|
||||
| beq =>identical_label
|
||||
} else {
|
||||
| beq >9
|
||||
}
|
||||
} else {
|
||||
if (opline->opcode != ZEND_IS_NOT_IDENTICAL) {
|
||||
| cset REG0w, eq
|
||||
} else {
|
||||
| cset REG0w, ne
|
||||
}
|
||||
| add REG0w, REG0w, #2
|
||||
| SET_ZVAL_TYPE_INFO_FROM_REG res_addr, REG0w, TMP1
|
||||
}
|
||||
if (opline->opcode != ZEND_CASE_STRICT
|
||||
&& (opline->op1_type & (IS_VAR|IS_TMP_VAR)) &&
|
||||
(op1_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) {
|
||||
| SET_EX_OPLINE opline, REG0
|
||||
| FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline, ZREG_TMP1, ZREG_TMP2
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception_undef_result(Dst, opline);
|
||||
}
|
||||
}
|
||||
if (smart_branch_opcode) {
|
||||
if (exit_addr) {
|
||||
if (smart_branch_opcode == ZEND_JMPZ) {
|
||||
| NIY // b &exit_addr
|
||||
}
|
||||
} else if (not_identical_label != (uint32_t)-1) {
|
||||
| b =>not_identical_label
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
| LOAD_ZVAL_ADDR FCARG1x, op1_addr
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
| LOAD_ZVAL_ADDR FCARG2x, op2_addr
|
||||
}
|
||||
| EXT_CALL zend_is_identical, REG0
|
||||
if ((opline->opcode != ZEND_CASE_STRICT &&
|
||||
(opline->op1_type & (IS_VAR|IS_TMP_VAR)) &&
|
||||
(op1_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) ||
|
||||
((opline->op2_type & (IS_VAR|IS_TMP_VAR)) &&
|
||||
(op2_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)))) {
|
||||
| str REG0, T1 // save
|
||||
| SET_EX_OPLINE opline, REG0
|
||||
if (opline->opcode != ZEND_CASE_STRICT) {
|
||||
| FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline, ZREG_TMP1, ZREG_TMP2
|
||||
}
|
||||
| FREE_OP opline->op2_type, opline->op2, op2_info, 1, opline, ZREG_TMP1, ZREG_TMP2
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception_undef_result(Dst, opline);
|
||||
}
|
||||
| ldr REG0, T1 // restore
|
||||
}
|
||||
if (smart_branch_opcode) {
|
||||
| cmp RETVALw, #0
|
||||
if (exit_addr) {
|
||||
if (smart_branch_opcode == ZEND_JMPNZ) {
|
||||
| NIY // bne &exit_addr
|
||||
} else {
|
||||
| NIY // beq &exit_addr
|
||||
}
|
||||
} else if (not_identical_label != (uint32_t)-1) {
|
||||
| beq =>not_identical_label
|
||||
if (identical_label != (uint32_t)-1) {
|
||||
| b =>identical_label
|
||||
}
|
||||
} else if (identical_label != (uint32_t)-1) {
|
||||
| bne =>identical_label
|
||||
}
|
||||
} else {
|
||||
if (opline->opcode != ZEND_IS_NOT_IDENTICAL) {
|
||||
| add RETVALw, RETVALw, #2
|
||||
} else {
|
||||
| neg RETVALw, RETVALw
|
||||
| add RETVALw, RETVALw, #3
|
||||
}
|
||||
| SET_ZVAL_TYPE_INFO_FROM_REG res_addr, RETVALw, TMP1
|
||||
}
|
||||
}
|
||||
|
||||
|9:
|
||||
if (may_throw) {
|
||||
zend_jit_check_exception(Dst);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
31
ext/opcache/tests/jit/identical_001.phpt
Normal file
31
ext/opcache/tests/jit/identical_001.phpt
Normal file
@@ -0,0 +1,31 @@
|
||||
--TEST--
|
||||
JIT IDENTICAL: 001
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.file_update_protection=0
|
||||
opcache.jit_buffer_size=1M
|
||||
opcache.protect_memory=1
|
||||
--EXTENSIONS--
|
||||
opcache
|
||||
--FILE--
|
||||
<?php
|
||||
function foo($a, $b) {
|
||||
return $a === $b;
|
||||
}
|
||||
var_dump(foo(0, 0));
|
||||
var_dump(foo(0, 1));
|
||||
var_dump(foo(0, 0.0));
|
||||
var_dump(foo(0.0, 0.0));
|
||||
var_dump(foo(0.0, 1.0));
|
||||
var_dump(foo("ab", "ab"));
|
||||
var_dump(foo("ab", "cd"));
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(false)
|
||||
131
ext/opcache/tests/jit/identical_002.phpt
Normal file
131
ext/opcache/tests/jit/identical_002.phpt
Normal file
@@ -0,0 +1,131 @@
|
||||
--TEST--
|
||||
JIT IDENTICAL: 002 Comparison with NaN
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.file_update_protection=0
|
||||
opcache.jit_buffer_size=1M
|
||||
opcache.protect_memory=1
|
||||
--EXTENSIONS--
|
||||
opcache
|
||||
--FILE--
|
||||
<?php
|
||||
function t() {
|
||||
echo "!";
|
||||
return true;
|
||||
}
|
||||
function f() {
|
||||
echo "!";
|
||||
return false;
|
||||
}
|
||||
$a = 0.0;
|
||||
$b = 0.0;
|
||||
$c = 1.0;
|
||||
$d = NAN;
|
||||
var_dump($a === $b);
|
||||
var_dump($a === $c);
|
||||
var_dump($a === $d);
|
||||
var_dump($a !== $b);
|
||||
var_dump($a !== $c);
|
||||
var_dump($a !== $d);
|
||||
var_dump($a === $b ? 1 : 0);
|
||||
var_dump($a === $c ? 1 : 0);
|
||||
var_dump($a === $d ? 1 : 0);
|
||||
var_dump($a !== $b ? 1 : 0);
|
||||
var_dump($a !== $c ? 1 : 0);
|
||||
var_dump($a !== $d ? 1 : 0);
|
||||
if ($a === $b) {
|
||||
echo "1\n";
|
||||
}
|
||||
if ($a === $c) {
|
||||
echo "2\n";
|
||||
}
|
||||
if ($a === $d) {
|
||||
echo "3\n";
|
||||
}
|
||||
if ($a !== $b) {
|
||||
echo "4\n";
|
||||
}
|
||||
if ($a !== $c) {
|
||||
echo "5\n";
|
||||
}
|
||||
if ($a !== $d) {
|
||||
echo "6\n";
|
||||
}
|
||||
if ($a === $b) {
|
||||
} else {
|
||||
echo "7\n";
|
||||
}
|
||||
if ($a === $c) {
|
||||
} else {
|
||||
echo "8\n";
|
||||
}
|
||||
if ($a === $d) {
|
||||
} else {
|
||||
echo "9\n";
|
||||
}
|
||||
if ($a !== $b) {
|
||||
} else {
|
||||
echo "A\n";
|
||||
}
|
||||
if ($a !== $c) {
|
||||
} else {
|
||||
echo "B\n";
|
||||
}
|
||||
if ($a !== $d) {
|
||||
} else {
|
||||
echo "C\n";
|
||||
}
|
||||
var_dump($a === $b && t());
|
||||
var_dump($a === $c && t());
|
||||
var_dump($a === $d && t());
|
||||
var_dump($a !== $b && t());
|
||||
var_dump($a !== $c && t());
|
||||
var_dump($a !== $d && t());
|
||||
var_dump($a === $b || f());
|
||||
var_dump($a === $c || f());
|
||||
var_dump($a === $d || f());
|
||||
var_dump($a !== $b || f());
|
||||
var_dump($a !== $c || f());
|
||||
var_dump($a !== $d || f());
|
||||
$a=NAN;
|
||||
var_dump($a === $d);
|
||||
var_dump($a !== $d);
|
||||
var_dump($a === $d ? 1 : 0);
|
||||
var_dump($a !== $d ? 1 : 0);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
int(1)
|
||||
int(0)
|
||||
int(0)
|
||||
int(0)
|
||||
int(1)
|
||||
int(1)
|
||||
1
|
||||
5
|
||||
6
|
||||
8
|
||||
9
|
||||
A
|
||||
!bool(true)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
!bool(true)
|
||||
!bool(true)
|
||||
bool(true)
|
||||
!bool(false)
|
||||
!bool(false)
|
||||
!bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
int(0)
|
||||
int(1)
|
||||
Reference in New Issue
Block a user