Merge remote-tracking branch 'origin/master' into native-tls

* origin/master:
  updated NEWS
  PowerPC64 support for add and sub with overflow check
  PowerPC64 support for operators with overflow check
  Fixed bug #68583 Crash in timeout thread
  Reduced size of zend_op on 64-bit systems.
  Make ZEND_INIT_FCALL keep predcalculted size of necessary stack space in opline->op1.num to avoid its recalculation on each execution.
  Removed unused variables
  Improved array_merge() and array_replace() (1-st array may be added using simple procedure).
  Replaced zendi_convert_to_long() with _zval_get_long_func()
  Moved zend_is_true() from zend_execute.h/zend_execute_API.c into zend_operators.h/zend_operators.c. Splited the most expensive part of inline i_zend_is_true() into a separate zend_object_is_true(). Replaced zendi_convert_to_long() with cals to zend_is_true().
  Revert "Save one xor instr"
  Save one xor instr

Conflicts:
	Zend/zend_execute_API.c
This commit is contained in:
Anatol Belski 2014-12-12 14:25:59 +01:00
commit dfb18b1188
21 changed files with 1834 additions and 1634 deletions

View file

@ -731,9 +731,6 @@ void zend_shutdown(TSRMLS_D) /* {{{ */
{
#ifdef ZEND_SIGNALS
zend_signal_shutdown(TSRMLS_C);
#endif
#ifdef ZEND_WIN32
zend_shutdown_timeout_thread();
#endif
zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
if (EG(active))

View file

@ -32,12 +32,6 @@
#include "zend_language_scanner.h"
#include "zend_inheritance.h"
#define CONSTANT_EX(op_array, op) \
(op_array)->literals[op]
#define CONSTANT(op) \
CONSTANT_EX(CG(active_op_array), op)
#define SET_NODE(target, src) do { \
target ## _type = (src)->op_type; \
if ((src)->op_type == IS_CONST) { \
@ -50,7 +44,7 @@
#define GET_NODE(target, src) do { \
(target)->op_type = src ## _type; \
if ((target)->op_type == IS_CONST) { \
(target)->u.constant = CONSTANT(src.constant); \
ZVAL_COPY_VALUE(&(target)->u.constant, CT_CONSTANT(src)); \
} else { \
(target)->u.op = src; \
} \
@ -291,11 +285,11 @@ static int lookup_cv(zend_op_array *op_array, zend_string* name TSRMLS_DC) /* {{
void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */
{
zval_dtor(&CONSTANT_EX(op_array, n));
zval_dtor(CT_CONSTANT_EX(op_array, n));
if (n + 1 == op_array->last_literal) {
op_array->last_literal--;
} else {
ZVAL_UNDEF(&CONSTANT_EX(op_array, n));
ZVAL_UNDEF(CT_CONSTANT_EX(op_array, n));
}
}
/* }}} */
@ -310,7 +304,7 @@ static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int li
Z_TYPE_FLAGS_P(zv) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
}
}
ZVAL_COPY_VALUE(&CONSTANT_EX(op_array, literal_position), zv);
ZVAL_COPY_VALUE(CT_CONSTANT_EX(op_array, literal_position), zv);
Z_CACHE_SLOT(op_array->literals[literal_position]) = -1;
}
/* }}} */
@ -752,13 +746,13 @@ static void str_dtor(zval *zv) /* {{{ */ {
void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC) /* {{{ */
{
zend_label *dest;
zend_long current, distance;
int current, distance;
zval *label;
if (pass2) {
label = opline->op2.zv;
label = RT_CONSTANT(op_array, opline->op2);
} else {
label = &CONSTANT_EX(op_array, opline->op2.constant);
label = CT_CONSTANT_EX(op_array, opline->op2.constant);
}
if (CG(context).labels == NULL ||
(dest = zend_hash_find_ptr(CG(context).labels, Z_STR_P(label))) == NULL) {
@ -888,11 +882,11 @@ ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opli
zval *op1, *op2;
if (compile_time) {
op1 = &CONSTANT_EX(op_array, opline->op1.constant);
op2 = &CONSTANT_EX(op_array, opline->op2.constant);
op1 = CT_CONSTANT_EX(op_array, opline->op1.constant);
op2 = CT_CONSTANT_EX(op_array, opline->op2.constant);
} else {
op1 = opline->op1.zv;
op2 = opline->op2.zv;
op1 = RT_CONSTANT(op_array, opline->op1);
op2 = RT_CONSTANT(op_array, opline->op2);
}
function = zend_hash_find_ptr(function_table, Z_STR_P(op1));
@ -928,11 +922,11 @@ ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const ze
zval *op1, *op2;
if (compile_time) {
op1 = &CONSTANT_EX(op_array, opline->op1.constant);
op2 = &CONSTANT_EX(op_array, opline->op2.constant);
op1 = CT_CONSTANT_EX(op_array, opline->op1.constant);
op2 = CT_CONSTANT_EX(op_array, opline->op2.constant);
} else {
op1 = opline->op1.zv;
op2 = opline->op2.zv;
op1 = RT_CONSTANT(op_array, opline->op1);
op2 = RT_CONSTANT(op_array, opline->op2);
}
if ((ce = zend_hash_find_ptr(class_table, Z_STR_P(op1))) == NULL) {
zend_error_noreturn(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(op1));
@ -965,11 +959,11 @@ ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array
zval *op1, *op2;
if (compile_time) {
op1 = &CONSTANT_EX(op_array, opline->op1.constant);
op2 = &CONSTANT_EX(op_array, opline->op2.constant);
op1 = CT_CONSTANT_EX(op_array, opline->op1.constant);
op2 = CT_CONSTANT_EX(op_array, opline->op2.constant);
} else {
op1 = opline->op1.zv;
op2 = opline->op2.zv;
op1 = RT_CONSTANT(op_array, opline->op1);
op2 = RT_CONSTANT(op_array, opline->op2);
}
ce = zend_hash_find_ptr(class_table, Z_STR_P(op1));
@ -1032,7 +1026,7 @@ void zend_do_early_binding(TSRMLS_D) /* {{{ */
zval *parent_name;
zend_class_entry *ce;
parent_name = &CONSTANT(fetch_class_opline->op2.constant);
parent_name = CT_CONSTANT(fetch_class_opline->op2);
if (((ce = zend_lookup_class(Z_STR_P(parent_name) TSRMLS_CC)) == NULL) ||
((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
(ce->type == ZEND_INTERNAL_CLASS))) {
@ -1071,7 +1065,7 @@ void zend_do_early_binding(TSRMLS_D) /* {{{ */
return;
}
zend_hash_del(table, Z_STR(CONSTANT(opline->op1.constant)));
zend_hash_del(table, Z_STR_P(CT_CONSTANT(opline->op1)));
zend_del_literal(CG(active_op_array), opline->op1.constant);
zend_del_literal(CG(active_op_array), opline->op2.constant);
MAKE_NOP(opline);
@ -1087,7 +1081,7 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS
CG(in_compilation) = 1;
while (opline_num != -1) {
if ((ce = zend_lookup_class(Z_STR_P(op_array->opcodes[opline_num-1].op2.zv) TSRMLS_CC)) != NULL) {
if ((ce = zend_lookup_class(Z_STR_P(RT_CONSTANT(op_array, op_array->opcodes[opline_num-1].op2)) TSRMLS_CC)) != NULL) {
do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), ce, 0 TSRMLS_CC);
}
opline_num = op_array->opcodes[opline_num].result.opline_num;
@ -2112,7 +2106,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node TSRMLS_CC);
if (opline->op2_type == IS_CONST) {
convert_to_string(&CONSTANT(opline->op2.constant));
convert_to_string(CT_CONSTANT(opline->op2));
zend_alloc_polymorphic_cache_slot(opline->op2.constant TSRMLS_CC);
}
@ -2509,6 +2503,10 @@ void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *
opline = &CG(active_op_array)->opcodes[opnum_init];
opline->extended_value = arg_count;
if (opline->opcode == ZEND_INIT_FCALL) {
opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc);
}
call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0);
opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL TSRMLS_CC);
opline->op1.num = call_flags;
@ -2662,7 +2660,7 @@ static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t
opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL TSRMLS_CC);
opline->extended_value = num_args;
opline->op1.num = zend_vm_calc_used_stack(num_args, fbc);
opline->op2_type = IS_CONST;
LITERAL_STR(opline->op2, lcname);
zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC);
@ -3515,7 +3513,7 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) /* {{{ */
opline = zend_emit_op(NULL, ZEND_CASE, &expr_node, &cond_node TSRMLS_CC);
SET_NODE(opline->result, &case_node);
if (opline->op1_type == IS_CONST) {
zval_copy_ctor(&CONSTANT(opline->op1.constant));
zval_copy_ctor(CT_CONSTANT(opline->op1));
}
jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0 TSRMLS_CC);

View file

@ -56,13 +56,34 @@ typedef struct _zend_compiler_context {
HashTable *labels;
} zend_compiler_context;
/* On 64-bi systems less optimal, but more compact VM code leads to better
* performance. So on 32-bit systems we use absolute addresses for jump
* targets and constants, but on 64-bit systems realtive 32-bit offsets */
#if SIZEOF_SIZE_T == 4
# define ZEND_USE_ABS_JMP_ADDR 1
# define ZEND_USE_ABS_CONST_ADDR 1
# define ZEND_EX_USE_LITERALS 0
# define ZEND_EX_USE_RUN_TIME_CACHE 1
#else
# define ZEND_USE_ABS_JMP_ADDR 0
# define ZEND_USE_ABS_CONST_ADDR 0
# define ZEND_EX_USE_LITERALS 1
# define ZEND_EX_USE_RUN_TIME_CACHE 1
#endif
typedef union _znode_op {
uint32_t constant;
uint32_t var;
uint32_t num;
uint32_t opline_num; /* Needs to be signed */
#if ZEND_USE_ABS_JMP_ADDR
zend_op *jmp_addr;
#else
uint32_t jmp_offset;
#endif
#if ZEND_USE_ABS_CONST_ADDR
zval *zv;
#endif
} znode_op;
typedef struct _znode { /* used only during compilation */
@ -112,8 +133,8 @@ struct _zend_op {
znode_op op1;
znode_op op2;
znode_op result;
zend_ulong extended_value;
uint lineno;
uint32_t extended_value;
uint32_t lineno;
zend_uchar opcode;
zend_uchar op1_type;
zend_uchar op2_type;
@ -374,12 +395,17 @@ typedef enum _zend_call_kind {
struct _zend_execute_data {
const zend_op *opline; /* executed opline */
zend_execute_data *call; /* current call */
void **run_time_cache;
zval *return_value;
zend_function *func; /* executed op_array */
zval This;
#if ZEND_EX_USE_RUN_TIME_CACHE
void **run_time_cache;
#endif
#if ZEND_EX_USE_LITERALS
zval *literals;
#endif
zend_class_entry *called_scope;
zend_execute_data *prev_execute_data;
zval *return_value;
zend_array *symbol_table;
};
@ -430,6 +456,136 @@ struct _zend_execute_data {
#define EX_VAR_TO_NUM(n) (ZEND_CALL_VAR(NULL, n) - ZEND_CALL_VAR_NUM(NULL, 0))
#define ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline_num) \
((char*)&(op_array)->opcodes[opline_num] - (char*)(opline))
#define ZEND_OFFSET_TO_OPLINE(base, offset) \
((zend_op*)(((char*)(base)) + (int)offset))
#define ZEND_OFFSET_TO_OPLINE_NUM(op_array, base, offset) \
(ZEND_OFFSET_TO_OPLINE(base, offset) - op_array->opcodes)
#if ZEND_USE_ABS_JMP_ADDR
/* run-time jump target */
# define OP_JMP_ADDR(opline, node) \
(node).jmp_addr
/* convert jump target from compile-time to run-time */
# define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
(node).jmp_addr = (op_array)->opcodes + (node).opline_num; \
} while (0)
/* convert jump target back from run-time to compile-time */
# define ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, node) do { \
(node).opline_num = (node).jmp_addr - (op_array)->opcodes; \
} while (0)
#else
/* run-time jump target */
# define OP_JMP_ADDR(opline, node) \
ZEND_OFFSET_TO_OPLINE(opline, (node).jmp_offset)
/* convert jump target from compile-time to run-time */
# define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
(node).jmp_offset = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, (node).opline_num); \
} while (0)
/* convert jump target back from run-time to compile-time */
# define ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, node) do { \
(node).opline_num = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, (node).jmp_offset); \
} while (0)
#endif
/* constant-time constant */
# define CT_CONSTANT_EX(op_array, num) \
((op_array)->literals + (num))
# define CT_CONSTANT(node) \
CT_CONSTANT_EX(CG(active_op_array), (node).constant)
#if ZEND_USE_ABS_CONST_ADDR
/* run-time constant */
# define RT_CONSTANT_EX(base, node) \
(node).zv
/* convert constant from compile-time to run-time */
# define ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, node) do { \
(node).zv = CT_CONSTANT_EX(op_array, (node).constant); \
} while (0)
/* convert constant back from run-time to compile-time */
# define ZEND_PASS_TWO_UNDO_CONSTANT(op_array, node) do { \
(node).constant = (node).zv - (op_array)->literals; \
} while (0)
#else
/* run-time constant */
# define RT_CONSTANT_EX(base, node) \
((zval*)(((char*)(base)) + (node).constant))
/* convert constant from compile-time to run-time */
# define ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, node) do { \
(node).constant *= sizeof(zval); \
} while (0)
/* convert constant back from run-time to compile-time (do nothing) */
# define ZEND_PASS_TWO_UNDO_CONSTANT(op_array, node) do { \
(node).constant /= sizeof(zval); \
} while (0)
#endif
#if ZEND_EX_USE_LITERALS
# define EX_LITERALS() \
EX(literals)
# define EX_LOAD_LITERALS(op_array) do { \
EX(literals) = (op_array)->literals; \
} while (0)
#else
# define EX_LITERALS() \
EX(func)->op_array.literals
# define EX_LOAD_LITERALS(op_array) do { \
} while (0)
#endif
/* run-time constant */
#define RT_CONSTANT(op_array, node) \
RT_CONSTANT_EX((op_array)->literals, node)
/* constant in currently executed function */
#define EX_CONSTANT(node) \
RT_CONSTANT_EX(EX_LITERALS(), node)
#if ZEND_EX_USE_RUN_TIME_CACHE
# define EX_RUN_TIME_CACHE() \
EX(run_time_cache)
# define EX_LOAD_RUN_TIME_CACHE(op_array) do { \
EX(run_time_cache) = (op_array)->run_time_cache; \
} while (0)
#else
# define EX_RUN_TIME_CACHE() \
EX(func)->op_array.run_time_cache
# define EX_LOAD_RUN_TIME_CACHE(op_array) do { \
} while (0)
#endif
#define IS_CONST (1<<0)
#define IS_TMP_VAR (1<<1)
#define IS_VAR (1<<2)

View file

@ -402,7 +402,7 @@ static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, const
} else {
*should_free = NULL;
if (op_type == IS_CONST) {
return node.zv;
return EX_CONSTANT(node);
} else {
ZEND_ASSERT(op_type == IS_CV);
return _get_zval_ptr_cv(execute_data, node.var, type TSRMLS_CC);
@ -422,7 +422,7 @@ static zend_always_inline zval *_get_zval_ptr_deref(int op_type, znode_op node,
} else {
*should_free = NULL;
if (op_type == IS_CONST) {
return node.zv;
return EX_CONSTANT(node);
} else {
ZEND_ASSERT(op_type == IS_CV);
return _get_zval_ptr_cv_deref(execute_data, node.var, type TSRMLS_CC);
@ -1674,7 +1674,8 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
if (!op_array->run_time_cache && op_array->last_cache_slot) {
op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
}
EX(run_time_cache) = op_array->run_time_cache;
EX_LOAD_RUN_TIME_CACHE(op_array);
EX_LOAD_LITERALS(op_array);
EG(current_execute_data) = execute_data;
}
@ -1698,7 +1699,8 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
if (!op_array->run_time_cache && op_array->last_cache_slot) {
op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
}
EX(run_time_cache) = op_array->run_time_cache;
EX_LOAD_RUN_TIME_CACHE(op_array);
EX_LOAD_LITERALS(op_array);
EG(current_execute_data) = execute_data;
}
@ -1772,7 +1774,8 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
}
}
EX(run_time_cache) = op_array->run_time_cache;
EX_LOAD_RUN_TIME_CACHE(op_array);
EX_LOAD_LITERALS(op_array);
EG(current_execute_data) = execute_data;
}
@ -1897,8 +1900,7 @@ static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data
OPLINE = new_op
#define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \
CHECK_SYMBOL_TABLES() \
OPLINE = ((zend_op*)(((char*)opline)+(offset)))
ZEND_VM_SET_OPCODE(ZEND_OFFSET_TO_OPLINE(opline, offset))
#define ZEND_VM_JMP(new_op) \
if (EXPECTED(!EG(exception))) { \

View file

@ -40,7 +40,6 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC);
ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC);
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
ZEND_API int zend_is_true(zval *op TSRMLS_DC);
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name TSRMLS_DC);
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload TSRMLS_DC);
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
@ -52,72 +51,6 @@ ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info
ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC);
ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC);
static zend_always_inline int i_zend_is_true(zval *op TSRMLS_DC)
{
int result;
again:
switch (Z_TYPE_P(op)) {
case IS_UNDEF:
case IS_NULL:
case IS_FALSE:
result = 0;
break;
case IS_TRUE:
result = 1;
break;
case IS_LONG:
result = (Z_LVAL_P(op)?1:0);
break;
case IS_RESOURCE:
result = (Z_RES_HANDLE_P(op)?1:0);
break;
case IS_DOUBLE:
result = (Z_DVAL_P(op) ? 1 : 0);
break;
case IS_STRING:
if (Z_STRLEN_P(op) == 0
|| (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
result = 0;
} else {
result = 1;
}
break;
case IS_ARRAY:
result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
break;
case IS_OBJECT:
if (Z_OBJ_HT_P(op)->cast_object) {
zval tmp;
if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL TSRMLS_CC) == SUCCESS) {
result = Z_TYPE(tmp) == IS_TRUE;
break;
}
zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", Z_OBJ_P(op)->ce->name->val);
} else if (Z_OBJ_HT_P(op)->get) {
zval rv;
zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv TSRMLS_CC);
if (Z_TYPE_P(tmp) != IS_OBJECT) {
/* for safety - avoid loop */
convert_to_boolean(tmp);
result = Z_TYPE_P(tmp) == IS_TRUE;
zval_ptr_dtor(tmp);
break;
}
}
result = 1;
break;
case IS_REFERENCE:
op = Z_REFVAL_P(op);
goto again;
break;
default:
result = 0;
break;
}
return result;
}
static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type TSRMLS_DC)
{
do {
@ -210,15 +143,10 @@ static zend_always_inline zval* zend_vm_stack_alloc(size_t size TSRMLS_DC)
return (zval*)top;
}
static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(uint32_t call_info, zend_function *func, uint32_t used_stack, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
{
uint32_t used_stack = ZEND_CALL_FRAME_SLOT + num_args;
zend_execute_data *call;
if (ZEND_USER_CODE(func->type)) {
used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args);
}
call = (zend_execute_data*)zend_vm_stack_alloc(used_stack * sizeof(zval) TSRMLS_CC);
zend_execute_data *call = (zend_execute_data*)zend_vm_stack_alloc(used_stack TSRMLS_CC);
call->func = func;
Z_OBJ(call->This) = object;
ZEND_SET_CALL_INFO(call, call_info);
@ -228,6 +156,24 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint3
return call;
}
static zend_always_inline uint32_t zend_vm_calc_used_stack(uint32_t num_args, zend_function *func)
{
uint32_t used_stack = ZEND_CALL_FRAME_SLOT + num_args;
if (ZEND_USER_CODE(func->type)) {
used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args);
}
return used_stack * sizeof(zval);
}
static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
{
uint32_t used_stack = zend_vm_calc_used_stack(num_args, func);
return zend_vm_stack_push_call_frame_ex(call_info,
func, used_stack, called_scope, object, prev TSRMLS_CC);
}
static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC)
{
uint32_t first_extra_arg = call->func->op_array.num_args - ((call->func->common.fn_flags & ZEND_ACC_VARIADIC) != 0);
@ -288,13 +234,6 @@ void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim TSRMLS_DC);
#ifdef ZEND_WIN32
void zend_init_timeout_thread(void);
void zend_shutdown_timeout_thread(void);
#define WM_REGISTER_ZEND_TIMEOUT (WM_USER+1)
#define WM_UNREGISTER_ZEND_TIMEOUT (WM_USER+2)
#endif
ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, uint32_t var);
#define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */
@ -319,20 +258,20 @@ ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_
void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC);
#define CACHED_PTR(num) \
EX(run_time_cache)[(num)]
EX_RUN_TIME_CACHE()[(num)]
#define CACHE_PTR(num, ptr) do { \
EX(run_time_cache)[(num)] = (ptr); \
EX_RUN_TIME_CACHE()[(num)] = (ptr); \
} while (0)
#define CACHED_POLYMORPHIC_PTR(num, ce) \
((EX(run_time_cache)[(num)] == (ce)) ? \
EX(run_time_cache)[(num) + 1] : \
((EX_RUN_TIME_CACHE()[(num)] == (ce)) ? \
EX_RUN_TIME_CACHE()[(num) + 1] : \
NULL)
#define CACHE_POLYMORPHIC_PTR(num, ce, ptr) do { \
EX(run_time_cache)[(num)] = (ce); \
EX(run_time_cache)[(num) + 1] = (ptr); \
EX_RUN_TIME_CACHE()[(num)] = (ce); \
EX_RUN_TIME_CACHE()[(num) + 1] = (ptr); \
} while (0)
#define CACHED_PTR_EX(slot) \

View file

@ -46,13 +46,10 @@ ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, {{0}, {{0}}, {0}},
ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL };
#ifdef ZEND_WIN32
#include <process.h>
static WNDCLASS wc;
static HWND timeout_window;
static HANDLE timeout_thread_event;
static HANDLE timeout_thread_handle;
static unsigned timeout_thread_id;
static volatile long timeout_thread_initialized=0;
#ifdef ZTS
__declspec(thread)
#endif
HANDLE tq_timer = NULL;
#endif
#if 0&&ZEND_DEBUG
@ -501,12 +498,6 @@ ZEND_API void _zval_internal_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ *
}
/* }}} */
ZEND_API int zend_is_true(zval *op TSRMLS_DC) /* {{{ */
{
return i_zend_is_true(op TSRMLS_CC);
}
/* }}} */
#define IS_VISITED_CONSTANT 0x80
#define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT)
#define MARK_CONSTANT_VISITED(p) Z_TYPE_INFO_P(p) |= IS_VISITED_CONSTANT
@ -1163,120 +1154,19 @@ ZEND_API void zend_timeout(int dummy) /* {{{ */
/* }}} */
#ifdef ZEND_WIN32
static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) /* {{{ */
VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
{
#ifdef ZTS
THREAD_T thread_id = (THREAD_T)wParam;
#endif
zend_bool *php_timed_out;
switch (message) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_REGISTER_ZEND_TIMEOUT:
/* wParam is the thread id pointer, lParam is the timeout amount in seconds */
if (lParam == 0) {
KillTimer(timeout_window, wParam);
} else {
#ifdef ZTS
void ***tsrm_ls;
#endif
SetTimer(timeout_window, wParam, lParam*1000, NULL);
#ifdef ZTS
tsrm_ls = ts_resource_ex(0, &thread_id);
if (!tsrm_ls) {
/* shouldn't normally happen */
break;
}
#endif
/* XXX this won't work with TLS enabled, EG is on a different thread.
But nothing happened anyway, no timeout here. */
/* EG(timed_out) = 0; */
}
break;
case WM_UNREGISTER_ZEND_TIMEOUT:
/* wParam is the thread id pointer */
KillTimer(timeout_window, wParam);
break;
case WM_TIMER: {
#ifdef ZTS
void ***tsrm_ls;
tsrm_ls = ts_resource_ex(0, &thread_id);
if (!tsrm_ls) {
/* Thread died before receiving its timeout? */
break;
}
#endif
KillTimer(timeout_window, wParam);
/* XXX this won't work with TLS enabled, EG is on a different thread.
Maybe an ide were to throw the timeout window right from here. */
/*EG(timed_out) = 1; */
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
/* }}} */
static unsigned __stdcall timeout_thread_proc(void *pArgs) /* {{{ */
{
MSG message;
wc.style=0;
wc.lpfnWndProc = zend_timeout_WndProc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hInstance=NULL;
wc.hIcon=NULL;
wc.hCursor=NULL;
wc.hbrBackground=(HBRUSH)(COLOR_BACKGROUND + 5);
wc.lpszMenuName=NULL;
wc.lpszClassName = "Zend Timeout Window";
if (!RegisterClass(&wc)) {
return -1;
}
timeout_window = CreateWindow(wc.lpszClassName, wc.lpszClassName, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
SetEvent(timeout_thread_event);
while (GetMessage(&message, NULL, 0, 0)) {
SendMessage(timeout_window, message.message, message.wParam, message.lParam);
if (message.message == WM_QUIT) {
break;
}
}
DestroyWindow(timeout_window);
UnregisterClass(wc.lpszClassName, NULL);
SetEvent(timeout_thread_handle);
return 0;
}
/* }}} */
void zend_init_timeout_thread(void) /* {{{ */
{
timeout_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL);
timeout_thread_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
_beginthreadex(NULL, 0, timeout_thread_proc, NULL, 0, &timeout_thread_id);
WaitForSingleObject(timeout_thread_event, INFINITE);
}
/* }}} */
void zend_shutdown_timeout_thread(void) /* {{{ */
{
if (!timeout_thread_initialized) {
/* The doc states it'll be always true, however it theoretically
could be FALSE when the thread was signaled. */
if (!timed_out) {
return;
}
PostThreadMessage(timeout_thread_id, WM_QUIT, 0, 0);
/* Wait for thread termination */
WaitForSingleObject(timeout_thread_handle, 5000);
CloseHandle(timeout_thread_handle);
timeout_thread_initialized = 0;
php_timed_out = (zend_bool *)arg;
*php_timed_out = 1;
}
/* }}} */
#endif
/* This one doesn't exists on QNX */
@ -1294,13 +1184,28 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
if(!seconds) {
return;
}
if (timeout_thread_initialized == 0 && InterlockedIncrement(&timeout_thread_initialized) == 1) {
/* We start up this process-wide thread here and not in zend_startup(), because if Zend
* is initialized inside a DllMain(), you're not supposed to start threads from it.
*/
zend_init_timeout_thread();
/* Don't use ChangeTimerQueueTimer() as it will not restart an expired
timer, so we could end up with just an ignored timeout. Instead
delete and recreate. */
if (NULL != tq_timer) {
if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
EG(timed_out) = 0;
tq_timer = NULL;
zend_error(E_ERROR, "Could not delete queued timer");
return;
}
tq_timer = NULL;
}
PostThreadMessage(timeout_thread_id, WM_REGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) seconds);
/* XXX passing NULL means the default timer queue provided by the system is used */
if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)&EG(timed_out), seconds*1000, 0, WT_EXECUTEONLYONCE)) {
EG(timed_out) = 0;
tq_timer = NULL;
zend_error(E_ERROR, "Could not queue new timer");
return;
}
EG(timed_out) = 0;
#else
# ifdef HAVE_SETITIMER
{
@ -1342,9 +1247,16 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
void zend_unset_timeout(TSRMLS_D) /* {{{ */
{
#ifdef ZEND_WIN32
if(timeout_thread_initialized) {
PostThreadMessage(timeout_thread_id, WM_UNREGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) 0);
if (NULL != tq_timer) {
if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
EG(timed_out) = 0;
tq_timer = NULL;
zend_error(E_ERROR, "Could not delete queued timer");
return;
}
tq_timer = NULL;
}
EG(timed_out) = 0;
#else
# ifdef HAVE_SETITIMER
if (EG(timeout_seconds)) {

View file

@ -454,7 +454,7 @@ static zend_string *zend_get_function_declaration(zend_function *fptr TSRMLS_DC)
}
}
if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
zval *zv = precv->op2.zv;
zval *zv = RT_CONSTANT(&fptr->op_array, precv->op2);
if (Z_TYPE_P(zv) == IS_CONSTANT) {
smart_str_append(&str, Z_STR_P(zv));

View file

@ -662,9 +662,10 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)
}
}
case ZEND_GOTO:
if (Z_TYPE(op_array->literals[opline->op2.constant]) != IS_LONG) {
if (Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) != IS_LONG) {
uint32_t num = opline->op2.constant;
opline->op2.zv = &op_array->literals[opline->op2.constant];
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC);
opline->op2.constant = num;
}
@ -717,12 +718,12 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
end = opline + op_array->last;
while (opline < end) {
if (opline->op1_type == IS_CONST) {
opline->op1.zv = &op_array->literals[opline->op1.constant];
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1);
} else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
opline->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op1.var);
}
if (opline->op2_type == IS_CONST) {
opline->op2.zv = &op_array->literals[opline->op2.constant];
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
} else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
opline->op2.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op2.var);
}
@ -735,17 +736,17 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
opline->extended_value = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->extended_value);
break;
case ZEND_GOTO:
if (Z_TYPE_P(opline->op2.zv) != IS_LONG) {
if (Z_TYPE_P(RT_CONSTANT(op_array, opline->op2)) != IS_LONG) {
zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC);
}
/* break omitted intentionally */
case ZEND_JMP:
case ZEND_FAST_CALL:
opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
break;
case ZEND_JMPZNZ:
/* absolute index to relative offset */
opline->extended_value = (char*)(op_array->opcodes + opline->extended_value) - (char*)opline;
opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
/* break omitted intentionally */
case ZEND_JMPZ:
case ZEND_JMPNZ:
@ -756,12 +757,12 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
case ZEND_NEW:
case ZEND_FE_RESET:
case ZEND_FE_FETCH:
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num];
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
break;
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
if (opline->op1_type != IS_CONST || Z_TYPE_P(opline->op1.zv) != IS_NULL) {
if (opline->op1_type != IS_CONST || Z_TYPE_P(RT_CONSTANT(op_array, opline->op1)) != IS_NULL) {
CG(zend_lineno) = opline->lineno;
zend_error_noreturn(E_COMPILE_ERROR, "Generators cannot return values using \"return\"");
}

View file

@ -220,88 +220,6 @@ try_again:
/* }}} */
/* {{{ zendi_convert_to_long */
#define zendi_convert_to_long(op, holder, result) \
if (op == result) { \
convert_to_long(op); \
} else if (Z_TYPE_P(op) != IS_LONG) { \
switch (Z_TYPE_P(op)) { \
case IS_NULL: \
case IS_FALSE: \
ZVAL_LONG(&(holder), 0); \
break; \
case IS_TRUE: \
ZVAL_LONG(&(holder), 1); \
break; \
case IS_DOUBLE: \
ZVAL_LONG(&holder, zend_dval_to_lval(Z_DVAL_P(op)));\
break; \
case IS_STRING: \
ZVAL_LONG(&holder, ZEND_STRTOL(Z_STRVAL_P(op), NULL, 10));\
break; \
case IS_ARRAY: \
ZVAL_LONG(&holder, zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
break; \
case IS_OBJECT: \
ZVAL_DUP(&(holder), (op)); \
convert_to_long_base(&(holder), 10); \
break; \
case IS_RESOURCE: \
ZVAL_LONG(&holder, Z_RES_HANDLE_P(op)); \
break; \
default: \
zend_error(E_WARNING, "Cannot convert to ordinal value"); \
ZVAL_LONG(&holder, 0); \
break; \
} \
(op) = &(holder); \
}
/* }}} */
/* {{{ zendi_convert_to_boolean */
#define zendi_convert_to_boolean(op, holder, result) \
if (op==result) { \
convert_to_boolean(op); \
} else if (Z_TYPE_P(op) != IS_FALSE && \
Z_TYPE_P(op) != IS_TRUE) { \
switch (Z_TYPE_P(op)) { \
case IS_NULL: \
ZVAL_BOOL(&holder, 0); \
break; \
case IS_RESOURCE: \
ZVAL_BOOL(&holder, Z_RES_HANDLE_P(op) ? 1 : 0); \
break; \
case IS_LONG: \
ZVAL_BOOL(&holder, Z_LVAL_P(op) ? 1 : 0); \
break; \
case IS_DOUBLE: \
ZVAL_BOOL(&holder, Z_DVAL_P(op) ? 1 : 0); \
break; \
case IS_STRING: \
if (Z_STRLEN_P(op) == 0 \
|| (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \
ZVAL_BOOL(&holder, 0); \
} else { \
ZVAL_BOOL(&holder, 1); \
} \
break; \
case IS_ARRAY: \
ZVAL_BOOL(&holder, zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
break; \
case IS_OBJECT: \
ZVAL_DUP(&(holder), (op)); \
convert_to_boolean(&(holder)); \
break; \
default: \
ZVAL_BOOL(&holder, 0); \
break; \
} \
(op) = &(holder); \
}
/* }}} */
/* {{{ convert_object_to_type */
#define convert_object_to_type(op, dst, ctype, conv_func) \
ZVAL_UNDEF(dst); \
@ -1199,51 +1117,58 @@ ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
zend_long op1_lval;
zend_long op1_lval, op2_lval;
do {
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
if (Z_ISREF_P(op1)) {
op1 = Z_REFVAL_P(op1);
if (Z_TYPE_P(op1) == IS_LONG) break;
if (Z_TYPE_P(op1) == IS_LONG) {
op1_lval = Z_LVAL_P(op1);
break;
}
}
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_MOD, mod_function);
zendi_convert_to_long(op1, op1_copy, result);
op1_lval = _zval_get_long_func(op1 TSRMLS_CC);
} else {
op1_lval = Z_LVAL_P(op1);
}
} while (0);
op1_lval = Z_LVAL_P(op1);
do {
if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
if (Z_ISREF_P(op2)) {
op2 = Z_REFVAL_P(op2);
if (Z_TYPE_P(op2) == IS_LONG) break;
if (Z_TYPE_P(op2) == IS_LONG) {
op2_lval = Z_LVAL_P(op2);
break;
}
}
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_MOD);
zendi_convert_to_long(op2, op2_copy, result);
op2_lval = _zval_get_long_func(op2 TSRMLS_CC);
} else {
op2_lval = Z_LVAL_P(op2);
}
} while (0);
if (Z_LVAL_P(op2) == 0) {
if (op2_lval == 0) {
zend_error(E_WARNING, "Division by zero");
ZVAL_BOOL(result, 0);
return FAILURE; /* modulus by zero */
}
if (Z_LVAL_P(op2) == -1) {
if (op2_lval == -1) {
/* Prevent overflow error/crash if op1==LONG_MIN */
ZVAL_LONG(result, 0);
return SUCCESS;
}
ZVAL_LONG(result, op1_lval % Z_LVAL_P(op2));
ZVAL_LONG(result, op1_lval % op2_lval);
return SUCCESS;
}
/* }}} */
ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
int op1_val, op2_val;
do {
@ -1263,8 +1188,7 @@ ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
}
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BOOL_XOR, boolean_xor_function);
zendi_convert_to_boolean(op1, op1_copy, result);
op1_val = (Z_TYPE_P(op1) == IS_TRUE);
op1_val = zval_is_true(op1);
}
} while (0);
do {
@ -1284,8 +1208,7 @@ ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
}
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BOOL_XOR);
zendi_convert_to_boolean(op2, op2_copy, result);
op2_val = (Z_TYPE_P(op2) == IS_TRUE);
op2_val = zval_is_true(op2);
}
} while (0);
@ -1296,8 +1219,6 @@ ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
{
zval op1_copy;
if (Z_TYPE_P(op1) < IS_TRUE) {
ZVAL_TRUE(result);
} else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
@ -1315,9 +1236,7 @@ ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
}
ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BOOL_NOT);
zendi_convert_to_boolean(op1, op1_copy, result);
ZVAL_BOOL(result, Z_TYPE_P(op1) == IS_FALSE);
ZVAL_BOOL(result, !zval_is_true(op1));
}
return SUCCESS;
}
@ -1357,8 +1276,7 @@ try_again:
ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
zend_long op1_lval;
zend_long op1_lval, op2_lval;
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
ZVAL_LONG(result, Z_LVAL_P(op1) | Z_LVAL_P(op2));
@ -1395,23 +1313,25 @@ ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_OR, bitwise_or_function);
zendi_convert_to_long(op1, op1_copy, result);
op1_lval = _zval_get_long_func(op1 TSRMLS_CC);
} else {
op1_lval = Z_LVAL_P(op1);
}
op1_lval = Z_LVAL_P(op1);
if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_OR);
zendi_convert_to_long(op2, op2_copy, result);
op2_lval = _zval_get_long_func(op2 TSRMLS_CC);
} else {
op2_lval = Z_LVAL_P(op2);
}
ZVAL_LONG(result, op1_lval | Z_LVAL_P(op2));
ZVAL_LONG(result, op1_lval | op2_lval);
return SUCCESS;
}
/* }}} */
ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
zend_long op1_lval;
zend_long op1_lval, op2_lval;
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
ZVAL_LONG(result, Z_LVAL_P(op1) & Z_LVAL_P(op2));
@ -1447,24 +1367,26 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function);
zendi_convert_to_long(op1, op1_copy, result);
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_or_function);
op1_lval = _zval_get_long_func(op1 TSRMLS_CC);
} else {
op1_lval = Z_LVAL_P(op1);
}
op1_lval = Z_LVAL_P(op1);
if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_AND);
zendi_convert_to_long(op2, op2_copy, result);
op2_lval = _zval_get_long_func(op2 TSRMLS_CC);
} else {
op2_lval = Z_LVAL_P(op2);
}
ZVAL_LONG(result, op1_lval & Z_LVAL_P(op2));
ZVAL_LONG(result, op1_lval & op2_lval);
return SUCCESS;
}
/* }}} */
ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
zend_long op1_lval;
zend_long op1_lval, op2_lval;
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
ZVAL_LONG(result, Z_LVAL_P(op1) ^ Z_LVAL_P(op2));
@ -1500,104 +1422,123 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function);
zendi_convert_to_long(op1, op1_copy, result);
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_or_function);
op1_lval = _zval_get_long_func(op1 TSRMLS_CC);
} else {
op1_lval = Z_LVAL_P(op1);
}
op1_lval = Z_LVAL_P(op1);
if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_XOR);
zendi_convert_to_long(op2, op2_copy, result);
op2_lval = _zval_get_long_func(op2 TSRMLS_CC);
} else {
op2_lval = Z_LVAL_P(op2);
}
ZVAL_LONG(result, op1_lval ^ Z_LVAL_P(op2));
ZVAL_LONG(result, op1_lval ^ op2_lval);
return SUCCESS;
}
/* }}} */
ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
zend_long op1_lval;
zend_long op1_lval, op2_lval;
do {
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
if (Z_ISREF_P(op1)) {
op1 = Z_REFVAL_P(op1);
if (Z_TYPE_P(op1) == IS_LONG) break;
if (Z_TYPE_P(op1) == IS_LONG) {
op1_lval = Z_LVAL_P(op1);
break;
}
}
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_SL, shift_left_function);
zendi_convert_to_long(op1, op1_copy, result);
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_SL, mod_function);
op1_lval = _zval_get_long_func(op1 TSRMLS_CC);
} else {
op1_lval = Z_LVAL_P(op1);
}
} while (0);
op1_lval = Z_LVAL_P(op1);
do {
if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
if (Z_ISREF_P(op2)) {
op2 = Z_REFVAL_P(op2);
if (Z_TYPE_P(op2) == IS_LONG) break;
if (Z_TYPE_P(op2) == IS_LONG) {
op2_lval = Z_LVAL_P(op2);
break;
}
}
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_SL);
zendi_convert_to_long(op2, op2_copy, result);
op2_lval = _zval_get_long_func(op2 TSRMLS_CC);
} else {
op2_lval = Z_LVAL_P(op2);
}
} while (0);
/* prevent wrapping quirkiness on some processors where << 64 + x == << x */
if (Z_LVAL_P(op2) >= SIZEOF_ZEND_LONG * 8) {
ZVAL_LONG(result, 0);
return SUCCESS;
if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
if (EXPECTED(op2_lval > 0)) {
ZVAL_LONG(result, 0);
return SUCCESS;
} else {
zend_error(E_WARNING, "Bit shift by negative number");
ZVAL_FALSE(result);
return FAILURE;
}
}
if (Z_LVAL_P(op2) < 0) {
zend_error(E_WARNING, "Bit shift by negative number");
ZVAL_FALSE(result);
return FAILURE;
}
ZVAL_LONG(result, op1_lval << Z_LVAL_P(op2));
ZVAL_LONG(result, op1_lval << op2_lval);
return SUCCESS;
}
/* }}} */
ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
zend_long op1_lval;
zend_long op1_lval, op2_lval;
do {
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
if (Z_ISREF_P(op1)) {
op1 = Z_REFVAL_P(op1);
if (Z_TYPE_P(op1) == IS_LONG) break;
if (Z_TYPE_P(op1) == IS_LONG) {
op1_lval = Z_LVAL_P(op1);
break;
}
}
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_SR, shift_right_function);
zendi_convert_to_long(op1, op1_copy, result);
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_SR, mod_function);
op1_lval = _zval_get_long_func(op1 TSRMLS_CC);
} else {
op1_lval = Z_LVAL_P(op1);
}
} while (0);
op1_lval = Z_LVAL_P(op1);
do {
if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
if (Z_ISREF_P(op2)) {
op2 = Z_REFVAL_P(op2);
if (Z_TYPE_P(op2) == IS_LONG) break;
if (Z_TYPE_P(op2) == IS_LONG) {
op2_lval = Z_LVAL_P(op2);
break;
}
}
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_SR);
zendi_convert_to_long(op2, op2_copy, result);
op2_lval = _zval_get_long_func(op2 TSRMLS_CC);
} else {
op2_lval = Z_LVAL_P(op2);
}
} while (0);
/* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */
if (Z_LVAL_P(op2) >= SIZEOF_ZEND_LONG * 8) {
ZVAL_LONG(result, (Z_LVAL_P(op1) < 0) ? -1 : 0);
return SUCCESS;
if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
if (EXPECTED(op2_lval > 0)) {
ZVAL_LONG(result, (op1_lval < 0) ? -1 : 0);
return SUCCESS;
} else {
zend_error(E_WARNING, "Bit shift by negative number");
ZVAL_FALSE(result);
return FAILURE;
}
}
if (Z_LVAL_P(op2) < 0) {
zend_error(E_WARNING, "Bit shift by negative number");
ZVAL_FALSE(result);
return FAILURE;
}
ZVAL_LONG(result, op1_lval >> Z_LVAL_P(op2));
ZVAL_LONG(result, op1_lval >> op2_lval);
return SUCCESS;
}
/* }}} */
@ -1953,20 +1894,16 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {
}
if (!converted) {
if (Z_TYPE_P(op1) == IS_NULL || Z_TYPE_P(op1) == IS_FALSE) {
zendi_convert_to_boolean(op2, op2_copy, result);
ZVAL_LONG(result, (Z_TYPE_P(op2) == IS_TRUE) ? -1 : 0);
ZVAL_LONG(result, zval_is_true(op2) ? -1 : 0);
return SUCCESS;
} else if (Z_TYPE_P(op2) == IS_NULL || Z_TYPE_P(op2) == IS_FALSE) {
zendi_convert_to_boolean(op1, op1_copy, result);
ZVAL_LONG(result, (Z_TYPE_P(op1) == IS_TRUE) ? 1 : 0);
ZVAL_LONG(result, zval_is_true(op1) ? 1 : 0);
return SUCCESS;
} else if (Z_TYPE_P(op1) == IS_TRUE) {
zendi_convert_to_boolean(op2, op2_copy, result);
ZVAL_LONG(result, (Z_TYPE_P(op2) == IS_TRUE) ? 0 : 1);
ZVAL_LONG(result, zval_is_true(op2) ? 0 : 1);
return SUCCESS;
} else if (Z_TYPE_P(op2) == IS_TRUE) {
zendi_convert_to_boolean(op1, op1_copy, result);
ZVAL_LONG(result, (Z_TYPE_P(op1) == IS_TRUE) ? 0 : -1);
ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1);
return SUCCESS;
} else {
zendi_convert_scalar_to_number(op1, op1_copy, result);
@ -2384,10 +2321,33 @@ try_again:
}
/* }}} */
ZEND_API int zval_is_true(zval *op) /* {{{ */
ZEND_API int zend_is_true(zval *op TSRMLS_DC) /* {{{ */
{
convert_to_boolean(op);
return (Z_TYPE_P(op) == IS_TRUE ? 1 : 0);
return i_zend_is_true(op TSRMLS_CC);
}
/* }}} */
ZEND_API int zend_object_is_true(zval *op TSRMLS_DC) /* {{{ */
{
if (Z_OBJ_HT_P(op)->cast_object) {
zval tmp;
if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL TSRMLS_CC) == SUCCESS) {
return Z_TYPE(tmp) == IS_TRUE;
}
zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", Z_OBJ_P(op)->ce->name->val);
} else if (Z_OBJ_HT_P(op)->get) {
int result;
zval rv;
zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv TSRMLS_CC);
if (Z_TYPE_P(tmp) != IS_OBJECT) {
/* for safety - avoid loop */
result = i_zend_is_true(tmp TSRMLS_CC);
zval_ptr_dtor(tmp);
return result;
}
}
return 1;
}
/* }}} */

View file

@ -252,7 +252,61 @@ ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2
#define convert_to_cstring(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); }
#define convert_to_string(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); }
ZEND_API int zval_is_true(zval *op);
ZEND_API int zend_is_true(zval *op TSRMLS_DC);
ZEND_API int zend_object_is_true(zval *op TSRMLS_DC);
#define zval_is_true(op) \
zend_is_true(op TSRMLS_CC)
static zend_always_inline int i_zend_is_true(zval *op TSRMLS_DC)
{
int result;
again:
switch (Z_TYPE_P(op)) {
case IS_UNDEF:
case IS_NULL:
case IS_FALSE:
result = 0;
break;
case IS_TRUE:
result = 1;
break;
case IS_LONG:
result = (Z_LVAL_P(op)?1:0);
break;
case IS_RESOURCE:
result = (Z_RES_HANDLE_P(op)?1:0);
break;
case IS_DOUBLE:
result = (Z_DVAL_P(op) ? 1 : 0);
break;
case IS_STRING:
if (Z_STRLEN_P(op) == 0
|| (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
result = 0;
} else {
result = 1;
}
break;
case IS_ARRAY:
result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
break;
case IS_OBJECT:
result = zend_object_is_true(op TSRMLS_CC);
break;
case IS_REFERENCE:
op = Z_REFVAL_P(op);
goto again;
break;
default:
result = 0;
break;
}
return result;
}
ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC);
@ -389,6 +443,33 @@ static zend_always_inline int fast_increment_function(zval *op1)
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "cc");
#elif defined(__GNUC__) && defined(__powerpc64__)
__asm__(
"ld 14, 0(%0)\n\t"
"li 15, 1\n\t"
"li 16, 0\n\t"
"mtxer 16\n\t"
"addo. 14, 14, 15\n\t"
"std 14, 0(%0)\n\t"
"bns+ 0f\n\t"
"xor 14, 14, 14\n\t"
"lis 15, 0x43e00000@h\n\t"
"ori 15, 15, 0x43e00000@l\n\t"
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
"stw 14, 0(%0)\n\t"
"stw 15, 0x4(%0)\n\t"
#else
"stw 14, 0x4(%0)\n\t"
"stw 15, 0(%0)\n\t"
#endif
"li 14, %1\n\t"
"stw 14, %c2(%0)\n"
"0:"
:
: "r"(&op1->value),
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "r14", "r15", "r16", "cc");
#else
if (UNEXPECTED(Z_LVAL_P(op1) == ZEND_LONG_MAX)) {
/* switch to double */
@ -431,6 +512,33 @@ static zend_always_inline int fast_decrement_function(zval *op1)
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "cc");
#elif defined(__GNUC__) && defined(__powerpc64__)
__asm__(
"ld 14, 0(%0)\n\t"
"li 15, 1\n\t"
"li 16, 0\n\t"
"mtxer 16\n\t"
"subo. 14, 14, 15\n\t"
"std 14, 0(%0)\n\t"
"bns+ 0f\n\t"
"xor 14, 14, 14\n\t"
"lis 15, 0xc3e00000@h\n\t"
"ori 15, 15, 0xc3e00000@l\n\t"
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
"stw 14, 0(%0)\n\t"
"stw 15, 0x4(%0)\n\t"
#else
"stw 14, 0x4(%0)\n\t"
"stw 15, 0(%0)\n\t"
#endif
"li 14, %1\n\t"
"stw 14, %c2(%0)\n"
"0:"
:
: "r"(&op1->value),
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "r14", "r15", "r16", "cc");
#else
if (UNEXPECTED(Z_LVAL_P(op1) == ZEND_LONG_MIN)) {
/* switch to double */
@ -494,6 +602,36 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "rax","cc");
#elif defined(__GNUC__) && defined(__powerpc64__)
__asm__(
"ld 14, 0(%1)\n\t"
"ld 15, 0(%2)\n\t"
"li 16, 0 \n\t"
"mtxer 16\n\t"
"addo. 14, 14, 15\n\t"
"bso- 0f\n\t"
"std 14, 0(%0)\n\t"
"li 14, %3\n\t"
"stw 14, %c5(%0)\n\t"
"b 1f\n"
"0:\n\t"
"lfd 0, 0(%1)\n\t"
"lfd 1, 0(%2)\n\t"
"fcfid 0, 0\n\t"
"fcfid 1, 1\n\t"
"fadd 0, 0, 1\n\t"
"li 14, %4\n\t"
"stw 14, %c5(%0)\n\t"
"stfd 0, 0(%0)\n"
"1:"
:
: "r"(&result->value),
"r"(&op1->value),
"r"(&op2->value),
"n"(IS_LONG),
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "r14","r15","r16","fr0","fr1","cc");
#else
/*
* 'result' may alias with op1 or op2, so we need to
@ -583,6 +721,36 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "rax","cc");
#elif defined(__GNUC__) && defined(__powerpc64__)
__asm__(
"ld 14, 0(%1)\n\t"
"ld 15, 0(%2)\n\t"
"li 16, 0\n\t"
"mtxer 16\n\t"
"subo. 14, 14, 15\n\t"
"bso- 0f\n\t"
"std 14, 0(%0)\n\t"
"li 14, %3\n\t"
"stw 14, %c5(%0)\n\t"
"b 1f\n"
"0:\n\t"
"lfd 0, 0(%1)\n\t"
"lfd 1, 0(%2)\n\t"
"fcfid 0, 0\n\t"
"fcfid 1, 1\n\t"
"fsub 0, 0, 1\n\t"
"li 14, %4\n\t"
"stw 14, %c5(%0)\n\t"
"stfd 0, 0(%0)\n"
"1:"
:
: "r"(&result->value),
"r"(&op1->value),
"r"(&op2->value),
"n"(IS_LONG),
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "r14","r15","r16","fr0","fr1","cc");
#else
ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2));

View file

@ -361,7 +361,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
/* here we are sure we are dealing with an object */
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) {
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) {
ZVAL_DEREF(zptr);
SEPARATE_ZVAL_NOREF(zptr);
@ -375,7 +375,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
zval rv;
if (Z_OBJ_HT_P(object)->read_property &&
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC)) != NULL) {
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC)) != NULL) {
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
zval rv;
zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC);
@ -388,7 +388,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
ZVAL_DEREF(z);
SEPARATE_ZVAL_NOREF(z);
binary_op(z, z, value TSRMLS_CC);
Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC);
Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), z);
}
@ -759,7 +759,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
/* here we are sure we are dealing with an object */
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) {
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) {
ZVAL_DEREF(zptr);
SEPARATE_ZVAL_NOREF(zptr);
@ -772,7 +772,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
zval rv;
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC);
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC);
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval rv;
@ -789,7 +789,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(retval, z);
}
Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC);
Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC);
zval_ptr_dtor(z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
@ -846,7 +846,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
/* here we are sure we are dealing with an object */
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) {
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) {
ZVAL_DEREF(zptr);
ZVAL_COPY_VALUE(retval, zptr);
@ -856,7 +856,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
} else {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
zval rv;
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC);
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC);
zval z_copy;
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
@ -872,7 +872,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
ZVAL_DUP(&z_copy, z);
incdec_op(&z_copy);
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC);
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(z);
} else {
@ -1118,10 +1118,10 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
zend_class_entry *ce;
if (OP2_TYPE == IS_CONST) {
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (OP1_TYPE != IS_CONST) {
zend_string_release(name);
@ -1130,12 +1130,12 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
retval = zend_std_get_static_property(ce, name, 0, ((OP1_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC);
retval = zend_std_get_static_property(ce, name, 0, ((OP1_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC);
FREE_OP1();
} else {
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
@ -1423,7 +1423,7 @@ ZEND_VM_C_LABEL(fetch_obj_r_no_object):
}
}
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
if (retval != EX_VAR(opline->result.var)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
@ -1452,7 +1452,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMPVAR|CV)
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1476,7 +1476,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1536,7 +1536,7 @@ ZEND_VM_C_LABEL(fetch_obj_is_no_object):
}
}
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
if (retval != EX_VAR(opline->result.var)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
@ -1570,7 +1570,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMPV
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1596,7 +1596,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1657,7 +1657,7 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, OP1_TYPE, property_name, OP2_TYPE, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, OP1_TYPE, property_name, OP2_TYPE, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
FREE_OP2();
FREE_OP1_VAR_PTR();
/* assign_obj has two opcodes! */
@ -1935,7 +1935,7 @@ ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
{
USE_OPLINE
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op1));
ZEND_VM_CONTINUE();
}
@ -1953,9 +1953,9 @@ ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, ANY)
ZEND_VM_CONTINUE();
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
if (OP1_TYPE == IS_CV) {
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
} else {
ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
ZEND_VM_CONTINUE();
}
}
@ -1963,7 +1963,7 @@ ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, ANY)
if (i_zend_is_true(val TSRMLS_CC)) {
opline++;
} else {
opline = opline->op2.jmp_addr;
opline = OP_JMP_ADDR(opline, opline->op2);
}
FREE_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
@ -1982,7 +1982,7 @@ ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, ANY)
val = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (Z_TYPE_P(val) == IS_TRUE) {
ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
ZEND_VM_CONTINUE();
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
if (OP1_TYPE == IS_CV) {
@ -1994,7 +1994,7 @@ ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, ANY)
}
if (i_zend_is_true(val TSRMLS_CC)) {
opline = opline->op2.jmp_addr;
opline = OP_JMP_ADDR(opline, opline->op2);
} else {
opline++;
}
@ -2019,17 +2019,17 @@ ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, ANY)
ZEND_VM_CONTINUE();
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
if (OP1_TYPE == IS_CV) {
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
} else {
ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
ZEND_VM_CONTINUE();
}
}
if (i_zend_is_true(val TSRMLS_CC)) {
opline = (zend_op*)(((char*)opline) + opline->extended_value);
opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
} else {
opline = opline->op2.jmp_addr;
opline = OP_JMP_ADDR(opline, opline->op2);
}
FREE_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
@ -2054,9 +2054,9 @@ ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, ANY)
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
ZVAL_FALSE(EX_VAR(opline->result.var));
if (OP1_TYPE == IS_CV) {
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
} else {
ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
ZEND_VM_CONTINUE();
}
}
@ -2068,7 +2068,7 @@ ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, ANY)
} else {
FREE_OP1();
ZVAL_FALSE(EX_VAR(opline->result.var));
opline = opline->op2.jmp_addr;
opline = OP_JMP_ADDR(opline, opline->op2);
}
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
@ -2087,7 +2087,7 @@ ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, ANY)
if (Z_TYPE_P(val) == IS_TRUE) {
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
ZEND_VM_CONTINUE();
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
ZVAL_FALSE(EX_VAR(opline->result.var));
@ -2100,7 +2100,7 @@ ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, ANY)
}
if (i_zend_is_true(val TSRMLS_CC)) {
ZVAL_TRUE(EX_VAR(opline->result.var));
opline = opline->op2.jmp_addr;
opline = OP_JMP_ADDR(opline, opline->op2);
} else {
ZVAL_FALSE(EX_VAR(opline->result.var));
opline++;
@ -2134,7 +2134,7 @@ ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP|UNUSED, CONST)
ZVAL_EMPTY_STRING(str);
}
add_char_to_string(str, str, opline->op2.zv);
add_char_to_string(str, str, EX_CONSTANT(opline->op2));
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
/*CHECK_EXCEPTION();*/
@ -2153,7 +2153,7 @@ ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP|UNUSED, CONST)
ZVAL_EMPTY_STRING(str);
}
add_string_to_string(str, str, opline->op2.zv);
add_string_to_string(str, str, EX_CONSTANT(opline->op2));
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
/*CHECK_EXCEPTION();*/
@ -2222,7 +2222,7 @@ ZEND_VM_C_LABEL(try_class_name):
if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) {
Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name));
} else {
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC);
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), EX_CONSTANT(opline->op2) + 1, opline->extended_value TSRMLS_CC);
CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var)));
}
} else if (Z_TYPE_P(class_name) == IS_OBJECT) {
@ -2335,7 +2335,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
}
/* First, locate the function. */
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL) TSRMLS_CC);
if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
}
@ -2375,17 +2375,17 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
if (OP1_TYPE == IS_CONST) {
/* no function found. try a static method in class */
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
if (UNEXPECTED(ce == NULL)) {
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
@ -2393,11 +2393,11 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
if (OP1_TYPE == IS_CONST &&
OP2_TYPE == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else if (OP1_TYPE != IS_CONST &&
OP2_TYPE == IS_CONST &&
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
/* do nothing */
} else if (OP2_TYPE != IS_UNUSED) {
zend_free_op free_op2;
@ -2415,7 +2415,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
if (ce->get_static_method) {
fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL) TSRMLS_CC);
}
if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
@ -2493,16 +2493,16 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMPVAR|CV)
zend_function *fbc;
zval *function_name, *func;
if (OP2_TYPE == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) {
function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
if (OP2_TYPE == IS_CONST && Z_TYPE_P(EX_CONSTANT(opline->op2)) == IS_STRING) {
function_name = (zval*)(EX_CONSTANT(opline->op2)+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
} else {
fbc = Z_FUNC_P(func);
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
}
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
@ -2673,7 +2673,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
}
}
} else {
zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(opline->op1.zv), error);
zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
efree(error);
func = (zend_function*)&zend_pass_function;
called_scope = NULL;
@ -2695,21 +2695,21 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
zval *func;
zend_function *fbc;
func_name = opline->op2.zv + 1;
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
func_name = EX_CONSTANT(opline->op2) + 1;
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else if ((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL) {
func_name++;
if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
} else {
fbc = Z_FUNC_P(func);
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
}
} else {
fbc = Z_FUNC_P(func);
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
}
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
@ -2736,8 +2736,8 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc);
}
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC);
EX(call) = zend_vm_stack_push_call_frame_ex(ZEND_CALL_NESTED_FUNCTION,
fbc, opline->op1.num, NULL, NULL, EX(call) TSRMLS_CC);
FREE_OP2();
@ -3080,12 +3080,12 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
} else {
catch_ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
catch_ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), catch_ce);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), catch_ce);
}
ce = EG(exception)->ce;
@ -3677,7 +3677,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
SAVE_OPLINE();
param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
if (arg_num > EX_NUM_ARGS()) {
ZVAL_COPY_VALUE(param, opline->op2.zv);
ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2));
if (Z_OPT_CONSTANT_P(param)) {
zval_update_constant(param, 0 TSRMLS_CC);
} else {
@ -3689,7 +3689,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
}
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
zend_verify_arg_type(EX(func), arg_num, param, opline->op2.zv TSRMLS_CC);
zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2) TSRMLS_CC);
}
CHECK_EXCEPTION();
@ -3760,7 +3760,7 @@ ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
zend_brk_cont_element *el;
SAVE_OPLINE();
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
&EX(func)->op_array, execute_data TSRMLS_CC);
ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
}
@ -3771,7 +3771,7 @@ ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
zend_brk_cont_element *el;
SAVE_OPLINE();
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
&EX(func)->op_array, execute_data TSRMLS_CC);
ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
}
@ -3783,7 +3783,7 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
zend_brk_cont_element *el;
SAVE_OPLINE();
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value,
el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->extended_value,
&EX(func)->op_array, execute_data TSRMLS_CC);
brk_opline = EX(func)->op_array.opcodes + el->brk;
@ -3793,7 +3793,7 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
}
}
ZEND_VM_JMP(opline->op1.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op1));
}
ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
@ -3821,15 +3821,15 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
SAVE_OPLINE();
if (OP1_TYPE == IS_CONST) {
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC);
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
@ -3852,7 +3852,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
} else {
OBJ_RELEASE(Z_OBJ(object_zval));
}
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
} else {
/* We are not handling overloaded classes right now */
EX(call) = zend_vm_stack_push_call_frame(
@ -3951,17 +3951,17 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
zend_constant *c;
zval *retval;
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
c = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if ((c = zend_quick_get_constant(opline->op2.zv + 1, opline->extended_value TSRMLS_CC)) == NULL) {
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value TSRMLS_CC)) == NULL) {
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv));
char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
if (!actual) {
ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(opline->op2.zv)));
ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(EX_CONSTANT(opline->op2))));
} else {
actual++;
ZVAL_STRINGL(EX_VAR(opline->result.var),
actual, Z_STRLEN_P(opline->op2.zv) - (actual - Z_STRVAL_P(opline->op2.zv)));
actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
}
/* non-qualified constant - allow text substitution */
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
@ -3969,10 +3969,10 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
} else {
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), c);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
}
retval = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(retval, &c->value);
@ -3989,33 +3989,33 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
zval *value;
if (OP1_TYPE == IS_CONST) {
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
value = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
ZVAL_DEREF(value);
ZVAL_DUP(EX_VAR(opline->result.var), value);
ZEND_VM_C_GOTO(constant_fetch_end);
} else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC);
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
if (UNEXPECTED(ce == NULL)) {
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce)) != NULL) {
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
ZVAL_DEREF(value);
ZVAL_DUP(EX_VAR(opline->result.var), value);
ZEND_VM_C_GOTO(constant_fetch_end);
}
}
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
ZVAL_DEREF(value);
if (Z_CONSTANT_P(value)) {
EG(scope) = ce;
@ -4023,16 +4023,16 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
EG(scope) = EX(func)->op_array.scope;
}
if (OP1_TYPE == IS_CONST) {
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), value);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
} else {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce, value);
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
}
ZVAL_DUP(EX_VAR(opline->result.var), value);
} else if (Z_STRLEN_P(opline->op2.zv) == sizeof("class")-1 && memcmp(Z_STRVAL_P(opline->op2.zv), "class", sizeof("class") - 1) == 0) {
} else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) {
/* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
} else {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
}
ZEND_VM_C_LABEL(constant_fetch_end):
@ -4432,10 +4432,10 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
zend_class_entry *ce;
if (OP2_TYPE == IS_CONST) {
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@ -4444,14 +4444,14 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
HANDLE_EXCEPTION();
}
if (UNEXPECTED(ce == NULL)) {
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op2.zv));
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
zend_std_unset_static_property(ce, Z_STR_P(varname), ((OP1_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC);
zend_std_unset_static_property(ce, Z_STR_P(varname), ((OP1_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
@ -4579,7 +4579,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
}
}
if (Z_OBJ_HT_P(container)->unset_property) {
Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@ -4744,7 +4744,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
if (OP1_TYPE == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
FREE_OP1_VAR_PTR();
}
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
}
p = fe_ht->arData + pos;
if (Z_TYPE(p->val) == IS_UNDEF ||
@ -4775,7 +4775,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
FREE_OP1_VAR_PTR();
}
if (is_empty) {
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
} else {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@ -4810,7 +4810,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
pos = ptr->pos;
if (UNEXPECTED(pos == INVALID_IDX)) {
/* reached end of iteration */
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
} else if (UNEXPECTED(ptr->ht != fe_ht)) {
ptr->ht = fe_ht;
pos = 0;
@ -4833,7 +4833,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
while (1) {
if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
/* reached end of iteration */
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
}
p = fe_ht->arData + pos;
value = &p->val;
@ -4891,7 +4891,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
pos = ptr->pos;
if (pos == INVALID_IDX) {
/* reached end of iteration */
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
} else if (UNEXPECTED(ptr->ht != fe_ht)) {
ptr->ht = fe_ht;
pos = 0;
@ -4914,7 +4914,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
while (1) {
if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
/* reached end of iteration */
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
}
p = fe_ht->arData + pos;
@ -4994,7 +4994,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
zval_ptr_dtor(array_ref);
HANDLE_EXCEPTION();
}
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
}
value = iter->funcs->get_current_data(iter TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
@ -5003,7 +5003,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
}
if (!value) {
/* failure in get_current_data */
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
}
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_MAKE_REF(value);
@ -5028,7 +5028,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
}
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
}
}
@ -5066,20 +5066,20 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
zend_class_entry *ce;
if (OP2_TYPE == IS_CONST) {
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((OP1_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC);
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((OP1_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC);
} else {
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
@ -5249,7 +5249,7 @@ ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|
ZEND_VM_C_LABEL(isset_no_object):
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
if ((opline->extended_value & ZEND_ISSET) == 0) {
result = !result;
}
@ -5365,7 +5365,7 @@ ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
FREE_OP1();
}
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
}
FREE_OP1();
@ -5400,7 +5400,7 @@ ZEND_VM_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, ANY)
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
FREE_OP1();
}
ZEND_VM_JMP(opline->op2.jmp_addr);
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
}
FREE_OP1();
@ -5489,8 +5489,8 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, ANY, ANY)
zval *zce, *orig_zce;
SAVE_OPLINE();
if ((zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op2.zv))) == NULL ||
((orig_zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op1.zv))) != NULL &&
if ((zce = zend_hash_find(EG(class_table), Z_STR_P(EX_CONSTANT(opline->op2)))) == NULL ||
((orig_zce = zend_hash_find(EG(class_table), Z_STR_P(EX_CONSTANT(opline->op1)))) != NULL &&
Z_CE_P(zce) != Z_CE_P(orig_zce))) {
do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
}
@ -5538,17 +5538,17 @@ ZEND_VM_C_LABEL(try_instanceof):
zend_class_entry *ce;
if (OP2_TYPE == IS_CONST) {
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
ZVAL_FALSE(EX_VAR(opline->result.var));
FREE_OP1();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
@ -5583,15 +5583,15 @@ ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, CONST)
zend_class_entry *iface;
SAVE_OPLINE();
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
iface = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
iface = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else {
iface = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_INTERFACE TSRMLS_CC);
iface = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_INTERFACE TSRMLS_CC);
if (UNEXPECTED(iface == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), iface);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), iface);
}
if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) {
@ -5610,11 +5610,11 @@ ZEND_VM_HANDLER(154, ZEND_ADD_TRAIT, ANY, ANY)
zend_class_entry *trait;
SAVE_OPLINE();
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
trait = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
trait = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else {
trait = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv),
opline->op2.zv + 1,
trait = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)),
EX_CONSTANT(opline->op2) + 1,
ZEND_FETCH_CLASS_TRAIT TSRMLS_CC);
if (UNEXPECTED(trait == NULL)) {
CHECK_EXCEPTION();
@ -5623,7 +5623,7 @@ ZEND_VM_HANDLER(154, ZEND_ADD_TRAIT, ANY, ANY)
if (!((trait->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT)) {
zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ce->name->val, trait->name->val);
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), trait);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), trait);
}
zend_do_implement_trait(ce, trait TSRMLS_CC);
@ -5832,7 +5832,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
SAVE_OPLINE();
if (UNEXPECTED((zfunc = zend_hash_find(EG(function_table), Z_STR_P(opline->op1.zv))) == NULL) ||
if (UNEXPECTED((zfunc = zend_hash_find(EG(function_table), Z_STR_P(EX_CONSTANT(opline->op1)))) == NULL) ||
UNEXPECTED(Z_FUNC_P(zfunc)->type != ZEND_USER_FUNCTION)) {
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
}
@ -6029,7 +6029,7 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
Z_OBJ_P(fast_call) = NULL;
/* set return address */
fast_call->u2.lineno = opline - EX(func)->op_array.opcodes;
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op1));
ZEND_VM_CONTINUE();
}
@ -6240,12 +6240,12 @@ ZEND_VM_HANDLER(122, ZEND_DEFINED, CONST, ANY)
zend_constant *c;
SAVE_OPLINE();
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
ZVAL_TRUE(EX_VAR(opline->result.var));
} else if ((c = zend_quick_get_constant(opline->op1.zv, 0 TSRMLS_CC)) == NULL) {
} else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op1), 0 TSRMLS_CC)) == NULL) {
ZVAL_FALSE(EX_VAR(opline->result.var));
} else {
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), c);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), c);
ZVAL_TRUE(EX_VAR(opline->result.var));
}
CHECK_EXCEPTION();

File diff suppressed because it is too large Load diff

View file

@ -137,7 +137,7 @@ $op1_get_zval_ptr = array(
"ANY" => "get_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, \\1)",
"TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1)",
"VAR" => "_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1)",
"CONST" => "opline->op1.zv",
"CONST" => "EX_CONSTANT(opline->op1)",
"UNUSED" => "NULL",
"CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op1.var TSRMLS_CC)",
"TMPVAR" => "_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1)",
@ -147,7 +147,7 @@ $op2_get_zval_ptr = array(
"ANY" => "get_zval_ptr(opline->op2_type, opline->op2, execute_data, &free_op2, \\1)",
"TMP" => "_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2)",
"VAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2)",
"CONST" => "opline->op2.zv",
"CONST" => "EX_CONSTANT(opline->op2)",
"UNUSED" => "NULL",
"CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)",
"TMPVAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2)",
@ -177,7 +177,7 @@ $op1_get_zval_ptr_deref = array(
"ANY" => "get_zval_ptr_deref(opline->op1_type, opline->op1, execute_data, &free_op1, \\1)",
"TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1)",
"VAR" => "_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1)",
"CONST" => "opline->op1.zv",
"CONST" => "EX_CONSTANT(opline->op1)",
"UNUSED" => "NULL",
"CV" => "_get_zval_ptr_cv_deref_\\1(execute_data, opline->op1.var TSRMLS_CC)",
"TMPVAR" => "???",
@ -187,7 +187,7 @@ $op2_get_zval_ptr_deref = array(
"ANY" => "get_zval_ptr_deref(opline->op2_type, opline->op2, execute_data, &free_op2, \\1)",
"TMP" => "_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2)",
"VAR" => "_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2)",
"CONST" => "opline->op2.zv",
"CONST" => "EX_CONSTANT(opline->op2)",
"UNUSED" => "NULL",
"CV" => "_get_zval_ptr_cv_deref_\\1(execute_data, opline->op2.var TSRMLS_CC)",
"TMPVAR" => "???",
@ -217,7 +217,7 @@ $op1_get_obj_zval_ptr = array(
"ANY" => "get_obj_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, \\1)",
"TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1)",
"VAR" => "_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1)",
"CONST" => "opline->op1.zv",
"CONST" => "EX_CONSTANT(opline->op1)",
"UNUSED" => "_get_obj_zval_ptr_unused(execute_data)",
"CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op1.var TSRMLS_CC)",
"TMPVAR" => "_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1)",
@ -227,7 +227,7 @@ $op2_get_obj_zval_ptr = array(
"ANY" => "get_obj_zval_ptr(opline->op2_type, opline->op2, execute_data, &free_op2, \\1)",
"TMP" => "_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2)",
"VAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2)",
"CONST" => "opline->op2.zv",
"CONST" => "EX_CONSTANT(opline->op2)",
"UNUSED" => "_get_obj_zval_ptr_unused(execute_data)",
"CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)",
"TMPVAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2)",
@ -237,7 +237,7 @@ $op1_get_obj_zval_ptr_deref = array(
"ANY" => "get_obj_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, \\1)",
"TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1)",
"VAR" => "_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1)",
"CONST" => "opline->op1.zv",
"CONST" => "EX_CONSTANT(opline->op1)",
"UNUSED" => "_get_obj_zval_ptr_unused(execute_data)",
"CV" => "_get_zval_ptr_cv_deref_\\1(execute_data, opline->op1.var TSRMLS_CC)",
"TMPVAR" => "???",
@ -247,7 +247,7 @@ $op2_get_obj_zval_ptr_deref = array(
"ANY" => "get_obj_zval_ptr(opline->op2_type, opline->op2, execute_data, &free_op2, \\1)",
"TMP" => "_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2)",
"VAR" => "_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2)",
"CONST" => "opline->op2.zv",
"CONST" => "EX_CONSTANT(opline->op2)",
"UNUSED" => "_get_obj_zval_ptr_unused(execute_data)",
"CV" => "_get_zval_ptr_cv_deref_\\1(execute_data, opline->op2.var TSRMLS_CC)",
"TMPVAR" => "???",

View file

@ -80,11 +80,13 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS
if (fcall->opcode == ZEND_INIT_FCALL_BY_NAME) {
fcall->opcode = ZEND_INIT_FCALL;
fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func);
Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
literal_dtor(&ZEND_OP2_LITERAL(fcall));
fcall->op2.constant = fcall->op2.constant + 1;
} else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
fcall->opcode = ZEND_INIT_FCALL;
fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func);
Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
literal_dtor(&op_array->literals[fcall->op2.constant]);
literal_dtor(&op_array->literals[fcall->op2.constant + 2]);
@ -92,17 +94,6 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS
} else {
ZEND_ASSERT(0);
}
} else if (call_stack[call].opline &&
call_stack[call].opline->opcode == ZEND_INIT_FCALL_BY_NAME &&
call_stack[call].opline->extended_value == 0 &&
ZEND_OP2_IS_CONST_STRING(call_stack[call].opline)) {
zend_op *fcall = call_stack[call].opline;
fcall->opcode = ZEND_INIT_FCALL;
Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
literal_dtor(&ZEND_OP2_LITERAL(fcall));
fcall->op2.constant = fcall->op2.constant + 1;
}
call_stack[call].func = NULL;
call_stack[call].opline = NULL;

View file

@ -401,7 +401,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML
opline->result_type = IS_UNUSED;
opline->op1.constant = send1_opline->op1.constant;
opline->op2.constant = send2_opline->op1.constant;
opline->result.zv = NULL;
opline->result.num = 0;
literal_dtor(&ZEND_OP2_LITERAL(init_opline));
MAKE_NOP(init_opline);

View file

@ -428,20 +428,20 @@ static void zend_accel_optimize(zend_op_array *op_array,
end = opline + op_array->last;
while (opline < end) {
if (opline->op1_type == IS_CONST) {
opline->op1.constant = opline->op1.zv - op_array->literals;
ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op1);
}
if (opline->op2_type == IS_CONST) {
opline->op2.constant = opline->op2.zv - op_array->literals;
ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op2);
}
switch (opline->opcode) {
case ZEND_JMP:
case ZEND_GOTO:
case ZEND_FAST_CALL:
ZEND_OP1(opline).opline_num = ZEND_OP1(opline).jmp_addr - op_array->opcodes;
ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP1(opline));
break;
case ZEND_JMPZNZ:
/* relative offset into absolute index */
opline->extended_value = (zend_op*)(((char*)opline) + opline->extended_value) - op_array->opcodes;
opline->extended_value = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
/* break omitted intentionally */
case ZEND_JMPZ:
case ZEND_JMPNZ:
@ -452,7 +452,7 @@ static void zend_accel_optimize(zend_op_array *op_array,
case ZEND_NEW:
case ZEND_FE_RESET:
case ZEND_FE_FETCH:
ZEND_OP2(opline).opline_num = ZEND_OP2(opline).jmp_addr - op_array->opcodes;
ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP2(opline));
break;
}
opline++;
@ -466,20 +466,20 @@ static void zend_accel_optimize(zend_op_array *op_array,
end = opline + op_array->last;
while (opline < end) {
if (opline->op1_type == IS_CONST) {
opline->op1.zv = &op_array->literals[opline->op1.constant];
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1);
}
if (opline->op2_type == IS_CONST) {
opline->op2.zv = &op_array->literals[opline->op2.constant];
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
}
switch (opline->opcode) {
case ZEND_JMP:
case ZEND_GOTO:
case ZEND_FAST_CALL:
ZEND_OP1(opline).jmp_addr = &op_array->opcodes[ZEND_OP1(opline).opline_num];
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP1(opline));
break;
case ZEND_JMPZNZ:
/* absolute index to relative offset */
opline->extended_value = (char*)(op_array->opcodes + opline->extended_value) - (char*)opline;
opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
/* break omitted intentionally */
case ZEND_JMPZ:
case ZEND_JMPNZ:
@ -490,7 +490,7 @@ static void zend_accel_optimize(zend_op_array *op_array,
case ZEND_NEW:
case ZEND_FE_RESET:
case ZEND_FE_FETCH:
ZEND_OP2(opline).jmp_addr = &op_array->opcodes[ZEND_OP2(opline).opline_num];
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP2(opline));
break;
}
ZEND_VM_SET_OPCODE_HANDLER(opline);

View file

@ -345,18 +345,21 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
op_array->opcodes = persist_ptr;
} else {
zend_op *new_opcodes = zend_accel_memdup(op_array->opcodes, sizeof(zend_op) * op_array->last);
#if ZEND_USE_ABS_CONST_ADDR || ZEND_USE_ABS_JMP_ADDR
zend_op *opline = new_opcodes;
zend_op *end = new_opcodes + op_array->last;
int offset = 0;
for (; opline < end ; opline++, offset++) {
# if ZEND_USE_ABS_CONST_ADDR
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
}
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
}
# endif
# if ZEND_USE_ABS_JMP_ADDR
if (ZEND_DONE_PASS_TWO(op_array)) {
/* fix jumps to point to new array */
switch (opline->opcode) {
@ -381,7 +384,9 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
break;
}
}
# endif
}
#endif
efree(op_array->opcodes);
op_array->opcodes = new_opcodes;

View file

@ -722,7 +722,7 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
zend_class_entry *old_scope;
string_write(str, " = ", sizeof(" = ")-1);
ZVAL_DUP(&zv, precv->op2.zv);
ZVAL_DUP(&zv, RT_CONSTANT(&fptr->op_array, precv->op2));
old_scope = EG(scope);
EG(scope) = fptr->common.scope;
zval_update_constant_ex(&zv, 1, NULL TSRMLS_CC);
@ -2618,7 +2618,7 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
return;
}
ZVAL_COPY_VALUE(return_value, precv->op2.zv);
ZVAL_COPY_VALUE(return_value, RT_CONSTANT(&param->fptr->op_array, precv->op2));
if (Z_CONSTANT_P(return_value)) {
zend_class_entry *old_scope = EG(scope);
@ -2648,7 +2648,7 @@ ZEND_METHOD(reflection_parameter, isDefaultValueConstant)
}
precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
if (precv && Z_TYPE_P(precv->op2.zv) == IS_CONSTANT) {
if (precv && Z_TYPE_P(RT_CONSTANT(&param->fptr->op_array, precv->op2)) == IS_CONSTANT) {
RETURN_TRUE;
}
@ -2673,8 +2673,8 @@ ZEND_METHOD(reflection_parameter, getDefaultValueConstantName)
}
precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
if (precv && Z_TYPE_P(precv->op2.zv) == IS_CONSTANT) {
RETURN_STR(zend_string_copy(Z_STR_P(precv->op2.zv)));
if (precv && Z_TYPE_P(RT_CONSTANT(&param->fptr->op_array, precv->op2)) == IS_CONSTANT) {
RETURN_STR(zend_string_copy(Z_STR_P(RT_CONSTANT(&param->fptr->op_array, precv->op2))));
}
}
/* }}} */

View file

@ -2348,99 +2348,104 @@ PHP_FUNCTION(array_slice)
}
/* }}} */
PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC) /* {{{ */
PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src TSRMLS_DC) /* {{{ */
{
zval *src_entry, *dest_entry;
zend_string *string_key;
if (recursive) {
ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
if (string_key) {
if ((dest_entry = zend_hash_find(dest, string_key)) != NULL) {
zval *src_zval = src_entry;
zval *dest_zval = dest_entry;
HashTable *thash;
zval tmp;
int ret;
ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
if (string_key) {
if ((dest_entry = zend_hash_find(dest, string_key)) != NULL) {
zval *src_zval = src_entry;
zval *dest_zval = dest_entry;
HashTable *thash;
zval tmp;
int ret;
ZVAL_DEREF(src_zval);
ZVAL_DEREF(dest_zval);
thash = Z_TYPE_P(dest_zval) == IS_ARRAY ? Z_ARRVAL_P(dest_zval) : NULL;
if ((thash && thash->u.v.nApplyCount > 1) || (src_entry == dest_entry && Z_ISREF_P(dest_entry) && (Z_REFCOUNT_P(dest_entry) % 2))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
ZVAL_DEREF(src_zval);
ZVAL_DEREF(dest_zval);
thash = Z_TYPE_P(dest_zval) == IS_ARRAY ? Z_ARRVAL_P(dest_zval) : NULL;
if ((thash && thash->u.v.nApplyCount > 1) || (src_entry == dest_entry && Z_ISREF_P(dest_entry) && (Z_REFCOUNT_P(dest_entry) % 2))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
return 0;
}
if (Z_ISREF_P(dest_entry)) {
if (Z_REFCOUNT_P(dest_entry) == 1) {
ZVAL_UNREF(dest_entry);
} else {
Z_DELREF_P(dest_entry);
ZVAL_DUP(dest_entry, dest_zval);
}
dest_zval = dest_entry;
} else {
SEPARATE_ZVAL(dest_zval);
}
if (Z_TYPE_P(dest_zval) == IS_NULL) {
convert_to_array_ex(dest_zval);
add_next_index_null(dest_zval);
} else {
convert_to_array_ex(dest_zval);
}
ZVAL_UNDEF(&tmp);
if (Z_TYPE_P(src_zval) == IS_OBJECT) {
ZVAL_DUP(&tmp, src_zval);
convert_to_array(&tmp);
src_zval = &tmp;
}
if (Z_TYPE_P(src_zval) == IS_ARRAY) {
if (thash && ZEND_HASH_APPLY_PROTECTION(thash)) {
thash->u.v.nApplyCount++;
}
ret = php_array_merge_recursive(Z_ARRVAL_P(dest_zval), Z_ARRVAL_P(src_zval) TSRMLS_CC);
if (thash && ZEND_HASH_APPLY_PROTECTION(thash)) {
thash->u.v.nApplyCount--;
}
if (!ret) {
return 0;
}
if (Z_ISREF_P(dest_entry)) {
if (Z_REFCOUNT_P(dest_entry) == 1) {
ZVAL_UNREF(dest_entry);
} else {
Z_DELREF_P(dest_entry);
ZVAL_DUP(dest_entry, dest_zval);
}
dest_zval = dest_entry;
} else {
SEPARATE_ZVAL(dest_zval);
}
if (Z_TYPE_P(dest_zval) == IS_NULL) {
convert_to_array_ex(dest_zval);
add_next_index_null(dest_zval);
} else {
convert_to_array_ex(dest_zval);
}
ZVAL_UNDEF(&tmp);
if (Z_TYPE_P(src_zval) == IS_OBJECT) {
ZVAL_DUP(&tmp, src_zval);
convert_to_array(&tmp);
src_zval = &tmp;
}
if (Z_TYPE_P(src_zval) == IS_ARRAY) {
if (thash && ZEND_HASH_APPLY_PROTECTION(thash)) {
thash->u.v.nApplyCount++;
}
ret = php_array_merge(Z_ARRVAL_P(dest_zval), Z_ARRVAL_P(src_zval), 1 TSRMLS_CC);
if (thash && ZEND_HASH_APPLY_PROTECTION(thash)) {
thash->u.v.nApplyCount--;
}
if (!ret) {
return 0;
}
} else {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_next_index_insert(Z_ARRVAL_P(dest_zval), src_zval);
}
zval_ptr_dtor(&tmp);
} else {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_add_new(dest, string_key, src_entry);
zend_hash_next_index_insert(Z_ARRVAL_P(dest_zval), src_zval);
}
zval_ptr_dtor(&tmp);
} else {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_next_index_insert_new(dest, src_entry);
zend_hash_add_new(dest, string_key, src_entry);
}
} ZEND_HASH_FOREACH_END();
} else {
ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
if (string_key) {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_update(dest, string_key, src_entry);
} else {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_next_index_insert_new(dest, src_entry);
} else {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
} ZEND_HASH_FOREACH_END();
}
zend_hash_next_index_insert_new(dest, src_entry);
}
} ZEND_HASH_FOREACH_END();
return 1;
}
/* }}} */
PHPAPI int php_array_merge(HashTable *dest, HashTable *src TSRMLS_DC) /* {{{ */
{
zval *src_entry;
zend_string *string_key;
ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
if (string_key) {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_update(dest, string_key, src_entry);
} else {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_next_index_insert_new(dest, src_entry);
}
} ZEND_HASH_FOREACH_END();
return 1;
}
/* }}} */
@ -2521,6 +2526,7 @@ PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src TSRMLS_DC
static void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive, int replace) /* {{{ */
{
zval *args = NULL;
zval *arg;
int argc, i, init_size = 0;
#ifndef FAST_ZPP
@ -2551,16 +2557,80 @@ static void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETERS, int
array_init_size(return_value, init_size);
for (i = 0; i < argc; i++) {
zval *arg = args + i;
if (replace) {
zend_string *string_key;
zval *src_entry;
zend_ulong idx;
HashTable *src, *dest;
/* copy first array */
arg = args;
ZVAL_DEREF(arg);
if (!replace) {
php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg), recursive TSRMLS_CC);
} else if (recursive && i > 0) { /* First array will be copied directly instead */
php_array_replace_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg) TSRMLS_CC);
src = Z_ARRVAL_P(arg);
dest = Z_ARRVAL_P(return_value);
ZEND_HASH_FOREACH_KEY_VAL(src, idx, string_key, src_entry) {
if (string_key) {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_add_new(dest, string_key, src_entry);
} else {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_index_add_new(dest, idx, src_entry);
}
} ZEND_HASH_FOREACH_END();
if (recursive) {
for (i = 1; i < argc; i++) {
arg = args + i;
ZVAL_DEREF(arg);
php_array_replace_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg) TSRMLS_CC);
}
} else {
zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg), zval_add_ref, 1);
for (i = 1; i < argc; i++) {
arg = args + i;
ZVAL_DEREF(arg);
zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg), zval_add_ref, 1);
}
}
} else {
zend_string *string_key;
zval *src_entry;
HashTable *src, *dest;
/* copy first array */
arg = args;
ZVAL_DEREF(arg);
src = Z_ARRVAL_P(arg);
dest = Z_ARRVAL_P(return_value);
ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
if (string_key) {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_add_new(dest, string_key, src_entry);
} else {
if (Z_REFCOUNTED_P(src_entry)) {
Z_ADDREF_P(src_entry);
}
zend_hash_next_index_insert_new(dest, src_entry);
}
} ZEND_HASH_FOREACH_END();
if (recursive) {
for (i = 1; i < argc; i++) {
arg = args + i;
ZVAL_DEREF(arg);
php_array_merge_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg) TSRMLS_CC);
}
} else {
for (i = 1; i < argc; i++) {
arg = args + i;
ZVAL_DEREF(arg);
php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg) TSRMLS_CC);
}
}
}
}

View file

@ -104,7 +104,8 @@ PHP_FUNCTION(array_chunk);
PHP_FUNCTION(array_combine);
PHPAPI HashTable* php_splice(HashTable *, int, int, zval *, int, HashTable *);
PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC);
PHPAPI int php_array_merge(HashTable *dest, HashTable *src TSRMLS_DC);
PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src TSRMLS_DC);
PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src TSRMLS_DC);
PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC);
PHPAPI zend_long php_count_recursive(zval *array, zend_long mode TSRMLS_DC);

View file

@ -64,7 +64,7 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, uint32_t
} break;
case IS_CONST:
asprintf(&decode, "C%u", phpdbg_decode_literal(ops, op->zv TSRMLS_CC));
asprintf(&decode, "C%u", phpdbg_decode_literal(ops, RT_CONSTANT(ops, *op) TSRMLS_CC));
break;
case IS_UNUSED:
@ -86,7 +86,7 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRM
#ifdef ZEND_FAST_CALL
case ZEND_FAST_CALL:
#endif
asprintf(&decode[1], "J%ld", op->op1.jmp_addr - ops->opcodes);
asprintf(&decode[1], "J%ld", OP_JMP_ADDR(op, op->op1) - ops->opcodes);
goto format;
case ZEND_JMPZNZ:
@ -103,7 +103,7 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRM
case ZEND_JMP_SET:
#endif
decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC);
asprintf(&decode[2], "J%ld", op->op2.jmp_addr - ops->opcodes);
asprintf(&decode[2], "J%ld", OP_JMP_ADDR(op, op->op2) - ops->opcodes);
goto result;
case ZEND_RECV_INIT: