case ZEND_QM_ASSIGN:
ADD_OP1_TRACE_GUARD();
break;
+ case ZEND_VERIFY_RETURN_TYPE:
+ if (opline->op1_type == IS_UNUSED) {
+ /* Always throws */
+ break;
+ }
+ if (opline->op1_type == IS_CONST) {
+ /* TODO Different instruction format, has return value */
+ break;
+ }
+ if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Not worth bothering with */
+ break;
+ }
+ ADD_OP1_TRACE_GUARD();
+ break;
case ZEND_FETCH_DIM_FUNC_ARG:
if (!frame
|| !frame->call
goto jit_failure;
}
goto done;
+ case ZEND_VERIFY_RETURN_TYPE:
+ if (opline->op1_type == IS_UNUSED) {
+ /* Always throws */
+ break;
+ }
+ if (opline->op1_type == IS_CONST) {
+ /* TODO Different instruction format, has return value */
+ break;
+ }
+ if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Not worth bothering with */
+ break;
+ }
+ op1_info = OP1_INFO();
+ CHECK_OP1_TRACE_TYPE();
+ if (op1_info & MAY_BE_REF) {
+ /* TODO May need reference unwrapping. */
+ break;
+ }
+ if (!zend_jit_verify_return_type(&dasm_state, opline, op_array, op1_info)) {
+ goto jit_failure;
+ }
+ goto done;
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_DYNAMIC_CALL:
if (!zend_jit_trace_handler(&dasm_state, op_array, opline, zend_may_throw(opline, ssa_op, op_array, ssa), p + 1)) {
| mov dword [zv+offsetof(zval,u1.type_info)], type
|.endmacro
+|.macro GET_ZVAL_TYPE, reg, addr
+|| ZEND_ASSERT(Z_MODE(addr) == IS_MEM_ZVAL);
+| mov reg, byte [Ra(Z_REG(addr))+Z_OFFSET(addr)+offsetof(zval,u1.v.type)]
+|.endmacro
+
|.macro GET_ZVAL_TYPE_INFO, reg, addr
|| ZEND_ASSERT(Z_MODE(addr) == IS_MEM_ZVAL);
| mov reg, dword [Ra(Z_REG(addr))+Z_OFFSET(addr)+offsetof(zval,u1.type_info)]
zend_arg_info *arg_info = &op_array->arg_info[-1];
ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type));
zend_jit_addr op1_addr = OP1_ADDR();
-
- | LOAD_ZVAL_ADDR r0, op1_addr
-
+ zend_bool needs_slow_check = 1;
+ zend_bool slow_check_in_cold = 1;
uint32_t type_mask = ZEND_TYPE_PURE_MASK(arg_info->type) & MAY_BE_ANY;
+
if (type_mask == 0) {
- | jmp >7
- } else if (is_power_of_two(type_mask)) {
- uint32_t type_code = concrete_type(type_mask);
- | cmp byte [r0 + 8], type_code
- | jne >7
+ slow_check_in_cold = 0;
} else {
- | mov edx, 1
- | mov cl, byte [r0 + 8]
- | shl edx, cl
- | test edx, type_mask
- | je >7
- }
- |.cold_code
- |7:
- | SAVE_VALID_OPLINE opline, r1
- if (op1_info & MAY_BE_UNDEF) {
- | IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >8
- | mov FCARG1a, opline->op1.var
- | EXT_CALL zend_jit_undefined_op_helper, FCARG2a
- | LOAD_ADDR_ZTS r0, executor_globals, uninitialized_zval
+ if (((op1_info & MAY_BE_ANY) & type_mask) == 0) {
+ slow_check_in_cold = 0;
+ } else if (((op1_info & MAY_BE_ANY) | type_mask) == type_mask) {
+ needs_slow_check = 0;
+ } else if (is_power_of_two(type_mask)) {
+ uint32_t type_code = concrete_type(type_mask);
+ | IF_NOT_ZVAL_TYPE op1_addr, type_code, >7
+ } else {
+ | mov edx, 1
+ | GET_ZVAL_TYPE cl, op1_addr
+ | shl edx, cl
+ | test edx, type_mask
+ | je >7
+ }
}
- |8:
- | mov FCARG1a, r0
- | mov r0, EX->run_time_cache
- | add r0, opline->op2.num
- | mov FCARG2a, EX->func
- |.if X64
- | LOAD_ADDR CARG3, (ptrdiff_t)arg_info
- | mov CARG4, r0
- | EXT_CALL zend_jit_verify_return_slow, r0
- |.else
- | sub r4, 8
- | push r0
- | push (ptrdiff_t)arg_info
- | EXT_CALL zend_jit_verify_return_slow, r0
- | add r4, 8
- |.endif
- if (!zend_jit_check_exception(Dst)) {
- return 0;
+ if (needs_slow_check) {
+ if (slow_check_in_cold) {
+ |.cold_code
+ |7:
+ }
+ | SAVE_VALID_OPLINE opline, r1
+ if (op1_info & MAY_BE_UNDEF) {
+ | IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >8
+ | mov FCARG1a, opline->op1.var
+ | EXT_CALL zend_jit_undefined_op_helper, FCARG2a
+ | LOAD_ADDR_ZTS r0, executor_globals, uninitialized_zval
+ }
+ |8:
+ | LOAD_ZVAL_ADDR FCARG1a, op1_addr
+ | mov FCARG2a, EX->func
+ |.if X64
+ | LOAD_ADDR CARG3, (ptrdiff_t)arg_info
+ | mov r0, EX->run_time_cache
+ | lea CARG4, aword [r0+opline->op2.num]
+ | EXT_CALL zend_jit_verify_return_slow, r0
+ |.else
+ | sub r4, 8
+ | mov r0, EX->run_time_cache
+ | add r0, opline->op2.num
+ | push r0
+ | push (ptrdiff_t)arg_info
+ | EXT_CALL zend_jit_verify_return_slow, r0
+ | add r4, 8
+ |.endif
+ if (!zend_jit_check_exception(Dst)) {
+ return 0;
+ }
+ if (slow_check_in_cold) {
+ | jmp >9
+ |.code
+ }
}
- | jmp >9
- |.code
|9:
return 1;
}