mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Implemented HYBRID VM instruction dispatch method that takes advantages of both CALL and GOTO VMs.
This commit is contained in:
parent
9d6b7435e4
commit
27e01cd918
7 changed files with 310 additions and 124 deletions
|
@ -28,7 +28,10 @@ ZEND_API void zend_vm_set_opcode_handler(zend_op* opcode);
|
|||
ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* opcode, uint32_t op1_info, uint32_t op2_info, uint32_t res_info);
|
||||
ZEND_API void zend_serialize_opcode_handler(zend_op *op);
|
||||
ZEND_API void zend_deserialize_opcode_handler(zend_op *op);
|
||||
ZEND_API const void *zend_get_real_opcode_handler(const zend_op *op);
|
||||
ZEND_API const zend_op *zend_get_real_exit_op(void);
|
||||
ZEND_API int zend_vm_call_opcode_handler(zend_execute_data *ex);
|
||||
ZEND_API int zend_vm_kind(void);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
|
|
|
@ -2478,7 +2478,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
|||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY)
|
||||
ZEND_VM_HOT_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
|
@ -2486,7 +2486,7 @@ ZEND_VM_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY)
|
|||
ZEND_VM_CONTINUE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
|
||||
ZEND_VM_HOT_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
|
@ -2518,7 +2518,7 @@ ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
|
|||
ZEND_VM_JMP(opline);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
|
||||
ZEND_VM_HOT_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
|
@ -2549,7 +2549,7 @@ ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
|
|||
ZEND_VM_JMP(opline);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, JMP_ADDR, JMP_ADDR)
|
||||
ZEND_VM_HOT_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, JMP_ADDR, JMP_ADDR)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
|
@ -3191,7 +3191,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM)
|
||||
ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_function *fbc;
|
||||
|
@ -3391,7 +3391,7 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM)
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM)
|
||||
ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op2;
|
||||
|
@ -3424,7 +3424,7 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM)
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
|
||||
ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_execute_data *call = EX(call);
|
||||
|
@ -3468,7 +3468,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
|
|||
ZEND_VM_CONTINUE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL))
|
||||
ZEND_VM_HOT_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL))
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_execute_data *call = EX(call);
|
||||
|
@ -3490,7 +3490,7 @@ ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL))
|
|||
ZEND_VM_ENTER();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
|
||||
ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_execute_data *call = EX(call);
|
||||
|
@ -3568,7 +3568,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
|
|||
ZEND_VM_CONTINUE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
|
||||
ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_execute_data *call = EX(call);
|
||||
|
@ -3743,7 +3743,7 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
|
|||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
|
||||
ZEND_VM_HOT_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
|
@ -4082,7 +4082,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV, JMP_ADDR)
|
|||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMPVAR, NUM)
|
||||
ZEND_VM_HOT_HANDLER(65, ZEND_SEND_VAL, CONST|TMPVAR, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *value, *arg;
|
||||
|
@ -4099,7 +4099,7 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMPVAR, NUM)
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, NUM, SPEC(QUICK_ARG))
|
||||
ZEND_VM_HOT_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, NUM, SPEC(QUICK_ARG))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *value, *arg;
|
||||
|
@ -4130,7 +4130,7 @@ ZEND_VM_C_LABEL(send_val_by_ref):
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(117, ZEND_SEND_VAR, VAR|CV, NUM)
|
||||
ZEND_VM_HOT_HANDLER(117, ZEND_SEND_VAR, VAR|CV, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *varptr, *arg;
|
||||
|
@ -4257,7 +4257,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, NUM)
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, NUM, SPEC(QUICK_ARG))
|
||||
ZEND_VM_HOT_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, NUM, SPEC(QUICK_ARG))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *varptr, *arg;
|
||||
|
@ -4574,7 +4574,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, NUM, ANY)
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(64, ZEND_RECV_INIT, NUM, CONST)
|
||||
ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST)
|
||||
{
|
||||
USE_OPLINE
|
||||
uint32_t arg_num;
|
||||
|
@ -6699,7 +6699,7 @@ ZEND_VM_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR)
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
|
||||
ZEND_VM_HOT_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
|
@ -7528,7 +7528,7 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH)
|
|||
ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, current_try_catch_offset, op_num, current_op_num);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
|
||||
ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
|
@ -8102,7 +8102,7 @@ ZEND_VM_HANDLER(188, ZEND_SWITCH_STRING, CONST|TMPVAR|CV, CONST, JMP_ADDR)
|
|||
}
|
||||
}
|
||||
|
||||
ZEND_VM_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))
|
||||
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
|
||||
zval *op1, *op2, *result;
|
||||
|
@ -8114,7 +8114,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (res_info == MAY_BE_LONG && op1_info == MAY_
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2, *result;
|
||||
|
@ -8126,7 +8126,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_LONG && op2_info == MAY_
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_ADD_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_ADD_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2, *result;
|
||||
|
@ -8138,7 +8138,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_DOUBLE && op2_info == MA
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_SUB_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SUB, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_SUB_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2, *result;
|
||||
|
@ -8150,7 +8150,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (res_info == MAY_BE_LONG && op1_info == MAY_
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_SUB_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_SUB_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2, *result;
|
||||
|
@ -8162,7 +8162,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_LONG && op2_info == MAY_
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_SUB_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_SUB_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2, *result;
|
||||
|
@ -8174,7 +8174,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_DOUBLE && op2_info == MA
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_MUL_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_MUL_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2, *result;
|
||||
|
@ -8186,7 +8186,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (res_info == MAY_BE_LONG && op1_info == MAY_
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_MUL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_MUL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2, *result;
|
||||
|
@ -8200,7 +8200,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_LONG && op2_info == MAY_
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_MUL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_MUL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2, *result;
|
||||
|
@ -8212,7 +8212,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_DOUBLE && op2_info == MA
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
|
@ -8226,7 +8226,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_LONG && op2_info ==
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
|
@ -8240,7 +8240,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_NOT_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_NOT_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
|
@ -8254,7 +8254,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_LONG && op2_inf
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_NOT_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_NOT_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
|
@ -8268,7 +8268,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_i
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
|
@ -8282,7 +8282,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_LONG && op2_info
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
|
@ -8296,7 +8296,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_DOUBLE && op2_inf
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_OR_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_OR_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
|
@ -8310,7 +8310,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_LONG &&
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_OR_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_OR_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *op1, *op2;
|
||||
|
@ -8324,7 +8324,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_DOUBLE &
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG_NO_OVERFLOW, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG_NO_OVERFLOW, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8337,7 +8337,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (res_info == MAY_BE_LONG && op1_info ==
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8350,7 +8350,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == MAY_BE_LONG), ZEND_PRE_INC_
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_PRE_INC_LONG_OR_DOUBLE, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_PRE_INC_LONG_OR_DOUBLE, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8367,7 +8367,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG_NO_OVERFLOW, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG_NO_OVERFLOW, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8380,7 +8380,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (res_info == MAY_BE_LONG && op1_info ==
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8393,7 +8393,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == MAY_BE_LONG), ZEND_PRE_DEC_
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_PRE_DEC_LONG_OR_DOUBLE, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_PRE_DEC_LONG_OR_DOUBLE, TMPVARCV, ANY, SPEC(RETVAL))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8410,7 +8410,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG_NO_OVERFLOW, TMPVARCV, ANY)
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG_NO_OVERFLOW, TMPVARCV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8421,7 +8421,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (res_info == MAY_BE_LONG && op1_info ==
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG, TMPVARCV, ANY)
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG, TMPVARCV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8432,7 +8432,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == MAY_BE_LONG), ZEND_POST_IN
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_POST_INC_LONG_OR_DOUBLE, TMPVARCV, ANY)
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_POST_INC_LONG_OR_DOUBLE, TMPVARCV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8447,7 +8447,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG_NO_OVERFLOW, TMPVARCV, ANY)
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG_NO_OVERFLOW, TMPVARCV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8458,7 +8458,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (res_info == MAY_BE_LONG && op1_info ==
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG, TMPVARCV, ANY)
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG, TMPVARCV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8469,7 +8469,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == MAY_BE_LONG), ZEND_POST_DE
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_POST_DEC_LONG_OR_DOUBLE, TMPVARCV, ANY)
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_POST_DEC_LONG_OR_DOUBLE, TMPVARCV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr;
|
||||
|
@ -8484,7 +8484,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_QM_ASSIGN_DOUBLE, CONST|TMPVARCV, ANY)
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_QM_ASSIGN_DOUBLE, CONST|TMPVARCV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
|
@ -8495,7 +8495,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_QM_A
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)))), ZEND_QM_ASSIGN_NOREF, CONST|TMPVARCV, ANY)
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)))), ZEND_QM_ASSIGN_NOREF, CONST|TMPVARCV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
|
@ -8506,7 +8506,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDE
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_FETCH_DIM_R, (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))), ZEND_FETCH_DIM_R_INDEX, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FETCH_DIM_R, (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))), ZEND_FETCH_DIM_R_INDEX, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
|
@ -8554,7 +8554,7 @@ ZEND_VM_C_LABEL(fetch_dim_r_index_undef):
|
|||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_SIMPLE, CV|VAR, NUM)
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_SIMPLE, CV|VAR, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *varptr, *arg;
|
||||
|
@ -8572,7 +8572,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF))
|
|||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SEND_VAR_EX, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_EX_SIMPLE, CV|VAR, NUM, SPEC(QUICK_ARG))
|
||||
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR_EX, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_EX_SIMPLE, CV|VAR, NUM, SPEC(QUICK_ARG))
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *varptr, *arg;
|
||||
|
|
|
@ -59177,6 +59177,38 @@ ZEND_API void zend_deserialize_opcode_handler(zend_op *op)
|
|||
op->handler = zend_opcode_handlers[(zend_uintptr_t)op->handler];
|
||||
}
|
||||
|
||||
ZEND_API const void *zend_get_real_opcode_handler(const zend_op *op)
|
||||
{
|
||||
#if ZEND_VM_KIND == ZEND_VM_KIND_CALL
|
||||
return op->handler;
|
||||
#elif ZEND_VM_KIND == ZEND_VM_KIND_HYBRID
|
||||
zval *zv;
|
||||
|
||||
if (!zend_handlers_table) {
|
||||
init_opcode_serialiser();
|
||||
}
|
||||
zv = zend_hash_index_find(zend_handlers_table, (zend_long)(zend_uintptr_t)op->handler);
|
||||
ZEND_ASSERT(zv != NULL);
|
||||
return zend_opcode_real_handlers[Z_LVAL_P(zv)];
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_API const zend_op *zend_get_real_exit_op(void)
|
||||
{
|
||||
#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID
|
||||
return &hybrid_return_op;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_API int zend_vm_kind(void)
|
||||
{
|
||||
return ZEND_VM_KIND;
|
||||
}
|
||||
|
||||
static const void *zend_vm_get_opcode_handler_ex(uint32_t spec, const zend_op* op)
|
||||
{
|
||||
static const int zend_vm_decode[] = {
|
||||
|
|
|
@ -83,3 +83,35 @@ ZEND_API void zend_deserialize_opcode_handler(zend_op *op)
|
|||
op->handler = zend_opcode_handlers[(zend_uintptr_t)op->handler];
|
||||
}
|
||||
|
||||
ZEND_API const void *zend_get_real_opcode_handler(const zend_op *op)
|
||||
{
|
||||
#if ZEND_VM_KIND == ZEND_VM_KIND_CALL
|
||||
return op->handler;
|
||||
#elif ZEND_VM_KIND == ZEND_VM_KIND_HYBRID
|
||||
zval *zv;
|
||||
|
||||
if (!zend_handlers_table) {
|
||||
init_opcode_serialiser();
|
||||
}
|
||||
zv = zend_hash_index_find(zend_handlers_table, (zend_long)(zend_uintptr_t)op->handler);
|
||||
ZEND_ASSERT(zv != NULL);
|
||||
return zend_opcode_real_handlers[Z_LVAL_P(zv)];
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_API const zend_op *zend_get_real_exit_op(void)
|
||||
{
|
||||
#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID
|
||||
return &hybrid_return_op;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_API int zend_vm_kind(void)
|
||||
{
|
||||
return ZEND_VM_KIND;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ error_reporting(E_ALL);
|
|||
const ZEND_VM_KIND_CALL = 1;
|
||||
const ZEND_VM_KIND_SWITCH = 2;
|
||||
const ZEND_VM_KIND_GOTO = 3;
|
||||
const ZEND_VM_KIND_HYBRID = 4;
|
||||
|
||||
$vm_op_flags = array(
|
||||
"ZEND_VM_OP_SPEC" => 1<<0,
|
||||
|
@ -134,6 +135,7 @@ $vm_kind_name = array(
|
|||
ZEND_VM_KIND_CALL => "ZEND_VM_KIND_CALL",
|
||||
ZEND_VM_KIND_SWITCH => "ZEND_VM_KIND_SWITCH",
|
||||
ZEND_VM_KIND_GOTO => "ZEND_VM_KIND_GOTO",
|
||||
ZEND_VM_KIND_HYBRID => "ZEND_VM_KIND_HYBRID",
|
||||
);
|
||||
|
||||
$op_types = array(
|
||||
|
@ -885,7 +887,7 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name, $extra_sp
|
|||
if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
|
||||
return "execute_data";
|
||||
} else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
|
||||
return "goto " . opcode_name($matches[1], $spec, $op1, $op2) . "_HANDLER";
|
||||
return "goto " . opcode_name($matches[1], $spec, $op1, $op2) . "_LABEL";
|
||||
} else {
|
||||
// ZEND_VM_DISPATCH_TO_HELPER
|
||||
if (isset($matches[2])) {
|
||||
|
@ -973,7 +975,7 @@ function skip_extra_spec_function($op1, $op2, $extra_spec) {
|
|||
}
|
||||
|
||||
// Generates opcode handler
|
||||
function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, $extra_spec = null, &$switch_labels = array()) {
|
||||
function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, $opcode, $extra_spec = null, &$switch_labels = array()) {
|
||||
global $definition_file, $prefix, $typecode, $opnames;
|
||||
|
||||
if ($spec && skip_extra_spec_function($op1, $op2, $extra_spec)) {
|
||||
|
@ -987,8 +989,17 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno,
|
|||
// Generate opcode handler's entry point according to selected threading model
|
||||
$spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):"");
|
||||
switch($kind) {
|
||||
case ZEND_VM_KIND_HYBRID:
|
||||
out($f,"\t\t\tHYBRID_CASE({$spec_name}):\n");
|
||||
out($f,"\t\t\t\t{$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
|
||||
out($f,"\t\t\t\tHYBRID_BREAK();\n");
|
||||
return;
|
||||
case ZEND_VM_KIND_CALL:
|
||||
out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
|
||||
if ($opcode["hot"] && ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
|
||||
} else {
|
||||
out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
|
||||
}
|
||||
break;
|
||||
case ZEND_VM_KIND_SWITCH:
|
||||
if ($spec) {
|
||||
|
@ -1006,7 +1017,7 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno,
|
|||
}
|
||||
break;
|
||||
case ZEND_VM_KIND_GOTO:
|
||||
out($f,"{$spec_name}_HANDLER: ZEND_VM_GUARD($spec_name);\n");
|
||||
out($f,"{$spec_name}_LABEL: ZEND_VM_GUARD($spec_name);\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1018,6 +1029,10 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno,
|
|||
function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, $inline, $extra_spec = null) {
|
||||
global $definition_file, $prefix;
|
||||
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($spec && skip_extra_spec_function($op1, $op2, $extra_spec)) {
|
||||
return;
|
||||
}
|
||||
|
@ -1068,7 +1083,7 @@ function gen_null_label($f, $kind, $prolog) {
|
|||
out($f,$prolog."(void*)(uintptr_t)-1,\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_GOTO:
|
||||
out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n");
|
||||
out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1219,7 +1234,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()
|
|||
$label++;
|
||||
break;
|
||||
case ZEND_VM_KIND_GOTO:
|
||||
out($f,$prolog."(void*)&&{$spec_name}_HANDLER,\n");
|
||||
out($f,$prolog."(void*)&&{$spec_name}_LABEL,\n");
|
||||
$label++;
|
||||
break;
|
||||
}
|
||||
|
@ -1265,7 +1280,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()
|
|||
out($f,$prolog."(void*)(uintptr_t)-1,\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_GOTO:
|
||||
out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n");
|
||||
out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n");
|
||||
break;
|
||||
}
|
||||
$next++;
|
||||
|
@ -1286,7 +1301,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()
|
|||
out($f,$prolog."(void*)(uintptr_t)".((string)$num).",\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_GOTO:
|
||||
out($f,$prolog."(void*)&&".$dsc["op"]."_HANDLER,\n");
|
||||
out($f,$prolog."(void*)&&".$dsc["op"]."_LABEL,\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -1298,7 +1313,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()
|
|||
out($f,$prolog."(void*)(uintptr_t)-1,\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_GOTO:
|
||||
out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n");
|
||||
out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1314,14 +1329,14 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()
|
|||
out($f,$prolog."(void*)(uintptr_t)-1\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_GOTO:
|
||||
out($f,$prolog."(void*)&&ZEND_NULL_HANDLER\n");
|
||||
out($f,$prolog."(void*)&&ZEND_NULL_LABEL\n");
|
||||
break;
|
||||
}
|
||||
$specs[$num + 1] = "$label";
|
||||
}
|
||||
|
||||
// Generates specialized offsets
|
||||
function gen_specs($f, $spec, $kind, $prolog, $specs) {
|
||||
function gen_specs($f, $prolog, $specs) {
|
||||
$lastdef = array_pop($specs);
|
||||
$last = 0;
|
||||
foreach ($specs as $num => $def) {
|
||||
|
@ -1462,7 +1477,7 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array())
|
|||
if (isset($opcodes[$num]["op1"][$op1]) &&
|
||||
isset($opcodes[$num]["op2"][$op2])) {
|
||||
// Generate handler code
|
||||
gen_handler($f, 1, $kind, $opcodes[$num]["op"], $op1, $op2, isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno, $extra_spec, $switch_labels);
|
||||
gen_handler($f, 1, $kind, $opcodes[$num]["op"], $op1, $op2, isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno, $opcodes[$num], $extra_spec, $switch_labels);
|
||||
}
|
||||
}
|
||||
} else if (isset($dsc["helper"])) {
|
||||
|
@ -1491,7 +1506,7 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array())
|
|||
$num = $dsc["handler"];
|
||||
// Generate handler code
|
||||
if ($num < 256) {
|
||||
gen_handler($f, 0, $kind, $opcodes[$num]["op"], "ANY", "ANY", isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno);
|
||||
gen_handler($f, 0, $kind, $opcodes[$num]["op"], "ANY", "ANY", isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno, $opcodes[$num]);
|
||||
}
|
||||
} else if (isset($dsc["helper"])) {
|
||||
$num = $dsc["helper"];
|
||||
|
@ -1520,10 +1535,19 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array())
|
|||
out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_GOTO:
|
||||
out($f,"ZEND_NULL_HANDLER:\n");
|
||||
out($f,"ZEND_NULL_LABEL:\n");
|
||||
out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
|
||||
out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_HYBRID:
|
||||
out($f,"\t\t\tHYBRID_CASE(HYBRID_RETURN):\n");
|
||||
out($f,"\t\t\t\texecute_data = orig_execute_data;\n");
|
||||
out($f,"\t\t\t\topline = orig_opline;\n");
|
||||
out($f,"\t\t\t\treturn;\n");
|
||||
out($f,"\t\t\tHYBRID_DEFAULT:\n");
|
||||
out($f,"\t\t\t\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
|
||||
out($f,"\t\t\t\tHYBRID_BREAK(); /* Never reached */\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1557,8 +1581,22 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
|
|||
out($f,"static const uint32_t *zend_spec_handlers;\n");
|
||||
out($f,"static const void **zend_opcode_handlers;\n");
|
||||
out($f,"static int zend_handlers_count;\n");
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
|
||||
out($f,"static const void **zend_opcode_real_handlers;\n");
|
||||
out($f,"static zend_op hybrid_return_op;\n");
|
||||
out($f,"#endif\n");
|
||||
}
|
||||
out($f,"static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);\n\n");
|
||||
switch ($kind) {
|
||||
case ZEND_VM_KIND_HYBRID:
|
||||
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
|
||||
out($f,"#define HYBRID_NEXT() goto *(void**)(OPLINE->handler)\n");
|
||||
out($f,"#define HYBRID_SWITCH() HYBRID_NEXT();\n");
|
||||
out($f,"#define HYBRID_CASE(op) op ## _LABEL\n");
|
||||
out($f,"#define HYBRID_BREAK() HYBRID_NEXT()\n");
|
||||
out($f,"#define HYBRID_DEFAULT ZEND_NULL_LABEL\n");
|
||||
out($f,"#endif\n");
|
||||
case ZEND_VM_KIND_CALL:
|
||||
out($f,"\n");
|
||||
out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
|
||||
|
@ -1593,7 +1631,17 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
|
|||
out($f,"# else\n");
|
||||
out($f,"# define ZEND_VM_CONTINUE() return\n");
|
||||
out($f,"# endif\n");
|
||||
out($f,"# define ZEND_VM_RETURN() opline = NULL; return\n");
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"# if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
|
||||
out($f,"# define ZEND_VM_RETURN() opline = &hybrid_return_op; return\n");
|
||||
out($f,"# define ZEND_VM_HOT zend_always_inline\n");
|
||||
out($f,"# else\n");
|
||||
out($f,"# define ZEND_VM_RETURN() opline = NULL; return\n");
|
||||
out($f,"# define ZEND_VM_HOT\n");
|
||||
out($f,"# endif\n");
|
||||
} else {
|
||||
out($f,"# define ZEND_VM_RETURN() opline = NULL; return\n");
|
||||
}
|
||||
out($f,"#else\n");
|
||||
out($f,"# define ZEND_OPCODE_HANDLER_RET int\n");
|
||||
out($f,"# define ZEND_VM_TAIL_CALL(call) return call\n");
|
||||
|
@ -1696,11 +1744,11 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
|
|||
out($f,"#undef HANDLE_EXCEPTION\n");
|
||||
out($f,"#undef HANDLE_EXCEPTION_LEAVE\n");
|
||||
if (ZEND_VM_SPEC) {
|
||||
out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_SPEC_HANDLER\n");
|
||||
out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_SPEC_HANDLER\n");
|
||||
out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_SPEC_LABEL\n");
|
||||
out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_SPEC_LABEL\n");
|
||||
} else {
|
||||
out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_HANDLER\n");
|
||||
out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_HANDLER\n");
|
||||
out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_LABEL\n");
|
||||
out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_LABEL\n");
|
||||
}
|
||||
out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n");
|
||||
out($f,"#define ZEND_VM_RETURN() return\n");
|
||||
|
@ -1712,12 +1760,15 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
|
|||
out($f,"\n");
|
||||
break;
|
||||
}
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
gen_executor_code($f, $spec, ZEND_VM_KIND_CALL, $m[1]);
|
||||
}
|
||||
break;
|
||||
case "EXECUTOR_NAME":
|
||||
out($f, $m[1].$executor_name.$m[3]."\n");
|
||||
break;
|
||||
case "HELPER_VARS":
|
||||
if ($kind != ZEND_VM_KIND_CALL) {
|
||||
if ($kind != ZEND_VM_KIND_CALL && $kind != ZEND_VM_KIND_HYBRID) {
|
||||
if ($kind == ZEND_VM_KIND_SWITCH) {
|
||||
out($f,$m[1]."const void *dispatch_handler;\n");
|
||||
}
|
||||
|
@ -1743,28 +1794,36 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
|
|||
}
|
||||
break;
|
||||
case "INTERNAL_LABELS":
|
||||
if ($kind == ZEND_VM_KIND_GOTO) {
|
||||
if ($kind == ZEND_VM_KIND_GOTO || $kind == ZEND_VM_KIND_HYBRID) {
|
||||
// Emit array of labels of opcode handlers and code for
|
||||
// zend_opcode_handlers initialization
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
|
||||
}
|
||||
$prolog = $m[1];
|
||||
out($f,$prolog."if (UNEXPECTED(execute_data == NULL)) {\n");
|
||||
out($f,$prolog."\tstatic const void* labels[] = {\n");
|
||||
gen_labels($f, $spec, $kind, $prolog."\t\t", $specs);
|
||||
gen_labels($f, $spec, ZEND_VM_KIND_GOTO, $prolog."\t\t", $specs);
|
||||
out($f,$prolog."\t};\n");
|
||||
out($f,$prolog."static const uint32_t specs[] = {\n");
|
||||
gen_specs($f, $spec, $kind, $prolog."\t", $specs);
|
||||
out($f,$prolog."};\n");
|
||||
out($f,$prolog."\tzend_opcode_handlers = (const void **) labels;\n");
|
||||
out($f,$prolog."\tzend_handlers_count = sizeof(labels) / sizeof(void*);\n");
|
||||
out($f,$prolog."\tzend_spec_handlers = (const uint32_t *) specs;\n");
|
||||
out($f,$prolog."\treturn;\n");
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,$prolog."\tmemset(&hybrid_return_op, 0, sizeof(hybrid_return_op));\n");
|
||||
out($f,$prolog."\thybrid_return_op.handler = (void*)&&HYBRID_RETURN_LABEL;\n");
|
||||
out($f,$prolog."\tgoto HYBRID_RETURN_LABEL;\n");
|
||||
} else {
|
||||
out($f,$prolog."\treturn;\n");
|
||||
}
|
||||
out($f,$prolog."}\n");
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#endif\n");
|
||||
}
|
||||
} else {
|
||||
skip_blanks($f, $m[1], $m[3]);
|
||||
}
|
||||
break;
|
||||
case "ZEND_VM_CONTINUE_LABEL":
|
||||
if ($kind == ZEND_VM_KIND_CALL) {
|
||||
if ($kind == ZEND_VM_KIND_CALL || $kind == ZEND_VM_KIND_HYBRID) {
|
||||
// Only SWITCH dispatch method use it
|
||||
out($f,"#if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG)\n");
|
||||
out($f,$m[1]."\tint ret;".$m[3]."\n");
|
||||
|
@ -1779,6 +1838,16 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
|
|||
case "ZEND_VM_DISPATCH":
|
||||
// Emit code that dispatches to opcode handler
|
||||
switch ($kind) {
|
||||
case ZEND_VM_KIND_SWITCH:
|
||||
out($f, $m[1]."dispatch_handler = OPLINE->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)(uintptr_t)dispatch_handler)".$m[3]."\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_GOTO:
|
||||
out($f, $m[1]."goto *(void**)(OPLINE->handler);".$m[3]."\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_HYBRID:
|
||||
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
|
||||
out($f, $m[1]."HYBRID_SWITCH();".$m[3]."\n");
|
||||
out($f,"#else\n");
|
||||
case ZEND_VM_KIND_CALL:
|
||||
out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
|
||||
out($f, $m[1]."((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
|
||||
|
@ -1786,18 +1855,25 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
|
|||
out($f,"#else\n");
|
||||
out($f, $m[1]."if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0))".$m[3]."\n");
|
||||
out($f,"#endif\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_SWITCH:
|
||||
out($f, $m[1]."dispatch_handler = OPLINE->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)(uintptr_t)dispatch_handler)".$m[3]."\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_GOTO:
|
||||
out($f, $m[1]."goto *(void**)(OPLINE->handler);".$m[3]."\n");
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#endif\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "INTERNAL_EXECUTOR":
|
||||
if ($kind == ZEND_VM_KIND_CALL) {
|
||||
// Executor is defined as a set of functions
|
||||
if ($kind != ZEND_VM_KIND_CALL) {
|
||||
// Emit executor code
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
|
||||
}
|
||||
gen_executor_code($f, $spec, $kind, $m[1], $switch_labels);
|
||||
}
|
||||
if ($kind == ZEND_VM_KIND_CALL || $kind == ZEND_VM_KIND_HYBRID) {
|
||||
// Executor is defined as a set of functions
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#else\n");
|
||||
}
|
||||
out($f,
|
||||
"#ifdef ZEND_VM_FP_GLOBAL_REG\n" .
|
||||
$m[1]."execute_data = orig_execute_data;\n" .
|
||||
|
@ -1816,9 +1892,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
|
|||
$m[1]."\treturn;\n".
|
||||
$m[1]."}\n".
|
||||
"#endif\n");
|
||||
} else {
|
||||
// Emit executor code
|
||||
gen_executor_code($f, $spec, $kind, $m[1], $switch_labels);
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#endif\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "EXTERNAL_EXECUTOR":
|
||||
|
@ -1835,18 +1911,31 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
|
|||
if ($kind == ZEND_VM_KIND_GOTO) {
|
||||
// Labels are defined in the executor itself, so we call it
|
||||
// with execute_data NULL and it sets zend_opcode_handlers array
|
||||
out($f,$prolog."");
|
||||
out($f,$prolog."static const uint32_t specs[] = {\n");
|
||||
gen_specs($f, $prolog."\t", $specs);
|
||||
out($f,$prolog."};\n");
|
||||
out($f,$prolog."zend_spec_handlers = specs;\n");
|
||||
out($f,$prolog.$executor_name."_ex(NULL);\n");
|
||||
} else {
|
||||
out($f,$prolog."static const void *labels[] = {\n");
|
||||
gen_labels($f, $spec, $kind, $prolog."\t", $specs, $switch_labels);
|
||||
gen_labels($f, $spec, ZEND_VM_KIND_CALL, $prolog."\t", $specs, $switch_labels);
|
||||
out($f,$prolog."};\n");
|
||||
out($f,$prolog."static const uint32_t specs[] = {\n");
|
||||
gen_specs($f, $spec, $kind, $prolog."\t", $specs);
|
||||
gen_specs($f, $prolog."\t", $specs);
|
||||
out($f,$prolog."};\n");
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
|
||||
out($f,$prolog."zend_opcode_real_handlers = labels;\n");
|
||||
out($f,$prolog."zend_spec_handlers = specs;\n");
|
||||
out($f,$prolog.$executor_name."_ex(NULL);\n");
|
||||
out($f,"#else\n");
|
||||
}
|
||||
out($f,$prolog."zend_opcode_handlers = labels;\n");
|
||||
out($f,$prolog."zend_handlers_count = sizeof(labels) / sizeof(void*);\n");
|
||||
out($f,$prolog."zend_spec_handlers = specs;\n");
|
||||
if ($kind == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#endif\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1973,22 +2062,24 @@ function gen_vm($def, $skel) {
|
|||
$export = array();
|
||||
foreach ($in as $line) {
|
||||
++$lineno;
|
||||
if (strpos($line,"ZEND_VM_HANDLER(") === 0) {
|
||||
if (strpos($line,"ZEND_VM_HANDLER(") === 0 ||
|
||||
strpos($line,"ZEND_VM_HOT_HANDLER(") === 0) {
|
||||
// Parsing opcode handler's definition
|
||||
if (preg_match(
|
||||
"/^ZEND_VM_HANDLER\(\s*([0-9]+)\s*,\s*([A-Z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
|
||||
"/^ZEND_VM_(HOT_)?HANDLER\(\s*([0-9]+)\s*,\s*([A-Z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
|
||||
$line,
|
||||
$m) == 0) {
|
||||
die("ERROR ($def:$lineno): Invalid ZEND_VM_HANDLER definition.\n");
|
||||
}
|
||||
$code = (int)$m[1];
|
||||
$op = $m[2];
|
||||
$hot = !empty($m[1]);
|
||||
$code = (int)$m[2];
|
||||
$op = $m[3];
|
||||
$len = strlen($op);
|
||||
$op1 = parse_operand_spec($def, $lineno, $m[3], $flags1);
|
||||
$op2 = parse_operand_spec($def, $lineno, $m[4], $flags2);
|
||||
$op1 = parse_operand_spec($def, $lineno, $m[4], $flags1);
|
||||
$op2 = parse_operand_spec($def, $lineno, $m[5], $flags2);
|
||||
$flags = $flags1 | ($flags2 << 8);
|
||||
if (!empty($m[6])) {
|
||||
$flags |= parse_ext_spec($def, $lineno, $m[6]);
|
||||
if (!empty($m[7])) {
|
||||
$flags |= parse_ext_spec($def, $lineno, $m[7]);
|
||||
}
|
||||
|
||||
if ($len > $max_opcode_len) {
|
||||
|
@ -2003,9 +2094,9 @@ function gen_vm($def, $skel) {
|
|||
if (isset($opnames[$op])) {
|
||||
die("ERROR ($def:$lineno): Opcode with name '$op' is already defined.\n");
|
||||
}
|
||||
$opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags);
|
||||
if (isset($m[8])) {
|
||||
$opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[8]);
|
||||
$opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags,"hot"=>$hot);
|
||||
if (isset($m[9])) {
|
||||
$opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[9]);
|
||||
if (isset($opcodes[$code]["spec"]["NO_CONST_CONST"])) {
|
||||
$opcodes[$code]["flags"] |= $vm_op_flags["ZEND_VM_NO_CONST_CONST"];
|
||||
}
|
||||
|
@ -2017,27 +2108,29 @@ function gen_vm($def, $skel) {
|
|||
$handler = $code;
|
||||
$helper = null;
|
||||
$list[$lineno] = array("handler"=>$handler);
|
||||
} else if (strpos($line,"ZEND_VM_TYPE_SPEC_HANDLER(") === 0) {
|
||||
} else if (strpos($line,"ZEND_VM_TYPE_SPEC_HANDLER(") === 0 ||
|
||||
strpos($line,"ZEND_VM_HOT_TYPE_SPEC_HANDLER(") === 0) {
|
||||
// Parsing opcode handler's definition
|
||||
if (preg_match(
|
||||
"/^ZEND_VM_TYPE_SPEC_HANDLER\(\s*([A-Z_]+)\s*,\s*([^,]+),\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
|
||||
"/^ZEND_VM_(HOT_)?TYPE_SPEC_HANDLER\(\s*([A-Z_]+)\s*,\s*([^,]+),\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
|
||||
$line,
|
||||
$m) == 0) {
|
||||
die("ERROR ($def:$lineno): Invalid ZEND_VM_TYPE_HANDLER_HANDLER definition.\n");
|
||||
}
|
||||
$orig_op = $m[1];
|
||||
$hot = !empty($m[1]);
|
||||
$orig_op = $m[2];
|
||||
if (!isset($opnames[$orig_op])) {
|
||||
die("ERROR ($def:$lineno): Opcode with name '$orig_op' is not defined.\n");
|
||||
}
|
||||
$orig_code = $opnames[$orig_op];
|
||||
$condition = $m[2];
|
||||
$condition = $m[3];
|
||||
$code = $extra_num++;
|
||||
$op = $m[3];
|
||||
$op1 = parse_operand_spec($def, $lineno, $m[4], $flags1);
|
||||
$op2 = parse_operand_spec($def, $lineno, $m[5], $flags2);
|
||||
$op = $m[4];
|
||||
$op1 = parse_operand_spec($def, $lineno, $m[5], $flags1);
|
||||
$op2 = parse_operand_spec($def, $lineno, $m[6], $flags2);
|
||||
$flags = $flags1 | ($flags2 << 8);
|
||||
if (!empty($m[7])) {
|
||||
$flags |= parse_ext_spec($def, $lineno, $m[7]);
|
||||
if (!empty($m[8])) {
|
||||
$flags |= parse_ext_spec($def, $lineno, $m[8]);
|
||||
}
|
||||
|
||||
if (isset($opcodes[$code])) {
|
||||
|
@ -2045,9 +2138,9 @@ function gen_vm($def, $skel) {
|
|||
}
|
||||
$opcodes[$orig_code]['type_spec'][$code] = $condition;
|
||||
$used_extra_spec["TYPE"] = 1;
|
||||
$opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags);
|
||||
if (isset($m[9])) {
|
||||
$opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[9]);
|
||||
$opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags,"hot"=>$hot);
|
||||
if (isset($m[10])) {
|
||||
$opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[10]);
|
||||
if (isset($opcodes[$code]["spec"]["NO_CONST_CONST"])) {
|
||||
$opcodes[$code]["flags"] |= $vm_op_flags["ZEND_VM_NO_CONST_CONST"];
|
||||
}
|
||||
|
@ -2174,7 +2267,17 @@ function gen_vm($def, $skel) {
|
|||
fputs($f, "#define ZEND_VM_KIND_CALL\t" . ZEND_VM_KIND_CALL . "\n");
|
||||
fputs($f, "#define ZEND_VM_KIND_SWITCH\t" . ZEND_VM_KIND_SWITCH . "\n");
|
||||
fputs($f, "#define ZEND_VM_KIND_GOTO\t" . ZEND_VM_KIND_GOTO . "\n");
|
||||
fputs($f, "#define ZEND_VM_KIND\t\t" . $GLOBALS["vm_kind_name"][ZEND_VM_KIND] . "\n");
|
||||
fputs($f, "#define ZEND_VM_KIND_HYBRID\t" . ZEND_VM_KIND_HYBRID . "\n");
|
||||
if ($GLOBALS["vm_kind_name"][ZEND_VM_KIND] === "ZEND_VM_KIND_HYBRID") {
|
||||
fputs($f, "/* HYBRID requires support for cmputed GOTO and global register variables*/\n");
|
||||
fputs($f, "#if (defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS))\n");
|
||||
fputs($f, "# define ZEND_VM_KIND\t\tZEND_VM_KIND_HYBRID\n");
|
||||
fputs($f, "#else\n");
|
||||
fputs($f, "# define ZEND_VM_KIND\t\tZEND_VM_KIND_CALL\n");
|
||||
fputs($f, "#endif\n");
|
||||
} else {
|
||||
fputs($f, "#define ZEND_VM_KIND\t\t" . $GLOBALS["vm_kind_name"][ZEND_VM_KIND] . "\n");
|
||||
}
|
||||
fputs($f, "\n");
|
||||
foreach($vm_op_flags as $name => $val) {
|
||||
fprintf($f, "#define %-24s 0x%08x\n", $name, $val);
|
||||
|
@ -2405,9 +2508,14 @@ function gen_vm($def, $skel) {
|
|||
out($f, "}\n\n");
|
||||
|
||||
// Generate zend_vm_call_opcode_handler() function
|
||||
if (ZEND_VM_KIND == ZEND_VM_KIND_CALL) {
|
||||
if (ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
|
||||
out($f, "ZEND_API int zend_vm_call_opcode_handler(zend_execute_data* ex)\n");
|
||||
out($f, "{\n");
|
||||
if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
|
||||
out($f, "\topcode_handler_t handler;\n");
|
||||
out($f,"#endif\n");
|
||||
}
|
||||
out($f, "\tint ret;\n");
|
||||
out($f, "#ifdef ZEND_VM_IP_GLOBAL_REG\n");
|
||||
out($f, "\tconst zend_op *orig_opline = opline;\n");
|
||||
|
@ -2420,7 +2528,14 @@ function gen_vm($def, $skel) {
|
|||
out($f, "#endif\n");
|
||||
out($f, "\n");
|
||||
out($f, "\tLOAD_OPLINE();\n");
|
||||
out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
|
||||
if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
|
||||
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
|
||||
out($f, "\thandler = (opcode_handler_t)zend_get_real_opcode_handler(opline);\n");
|
||||
out($f, "\thandler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
|
||||
out($f,"#elif defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
|
||||
} else {
|
||||
out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
|
||||
}
|
||||
out($f, "\t((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
|
||||
out($f, "\tif (EXPECTED(opline)) {\n");
|
||||
out($f, "\t\tret = execute_data != ex ? (int)(execute_data->prev_execute_data != ex) + 1 : 0;\n");
|
||||
|
@ -2523,9 +2638,9 @@ function gen_vm($def, $skel) {
|
|||
function usage() {
|
||||
echo("\nUsage: php zend_vm_gen.php [options]\n".
|
||||
"\nOptions:".
|
||||
"\n --with-vm-kind=CALL|SWITCH|GOTO - select threading model (default is CALL)".
|
||||
"\n --without-specializer - disable executor specialization".
|
||||
"\n --with-lines - enable #line directives".
|
||||
"\n --with-vm-kind=CALL|SWITCH|GOTO|HYBRID - select threading model (default is CALL)".
|
||||
"\n --without-specializer - disable executor specialization".
|
||||
"\n --with-lines - enable #line directives".
|
||||
"\n\n");
|
||||
}
|
||||
|
||||
|
@ -2543,6 +2658,9 @@ for ($i = 1; $i < $argc; $i++) {
|
|||
case "GOTO":
|
||||
define("ZEND_VM_KIND", ZEND_VM_KIND_GOTO);
|
||||
break;
|
||||
case "HYBRID":
|
||||
define("ZEND_VM_KIND", ZEND_VM_KIND_HYBRID);
|
||||
break;
|
||||
default:
|
||||
echo("ERROR: Invalid vm kind '$kind'\n");
|
||||
usage();
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define ZEND_VM_KIND_CALL 1
|
||||
#define ZEND_VM_KIND_SWITCH 2
|
||||
#define ZEND_VM_KIND_GOTO 3
|
||||
#define ZEND_VM_KIND_HYBRID 4
|
||||
#define ZEND_VM_KIND ZEND_VM_KIND_CALL
|
||||
|
||||
#define ZEND_VM_OP_SPEC 0x00000001
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include "phpdbg_wait.h"
|
||||
#include "phpdbg_eol.h"
|
||||
|
||||
#if ZEND_VM_KIND != ZEND_VM_KIND_CALL
|
||||
#if ZEND_VM_KIND != ZEND_VM_KIND_CALL && ZEND_VM_KIND != ZEND_VM_KIND_HYBRID
|
||||
#error "phpdbg can only be built with CALL zend vm kind"
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue