diff options
author | Anatol Belski <ab@php.net> | 2014-12-12 14:25:59 +0100 |
---|---|---|
committer | Anatol Belski <ab@php.net> | 2014-12-12 14:25:59 +0100 |
commit | dfb18b1188492efa48ade07029172c5535f65f93 (patch) | |
tree | 5da6d50a4918a06299162a22aa5cb98e5c76a26a /ext | |
parent | de99a94c384fdb6a71c20692df33dc24a2b81a4b (diff) | |
parent | f4311686cc2c7d07abce2b752b4e8597771c5b25 (diff) | |
download | php-git-dfb18b1188492efa48ade07029172c5535f65f93.tar.gz |
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
Diffstat (limited to 'ext')
-rw-r--r-- | ext/opcache/Optimizer/optimize_func_calls.c | 13 | ||||
-rw-r--r-- | ext/opcache/Optimizer/pass1_5.c | 2 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 20 | ||||
-rw-r--r-- | ext/opcache/zend_persist.c | 7 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 10 | ||||
-rw-r--r-- | ext/standard/array.c | 228 | ||||
-rw-r--r-- | ext/standard/php_array.h | 3 |
7 files changed, 175 insertions, 108 deletions
diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c index 9031a38f56..5c765cef4e 100644 --- a/ext/opcache/Optimizer/optimize_func_calls.c +++ b/ext/opcache/Optimizer/optimize_func_calls.c @@ -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; diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c index 15bca2adf8..6eb6a4ce02 100644 --- a/ext/opcache/Optimizer/pass1_5.c +++ b/ext/opcache/Optimizer/pass1_5.c @@ -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); diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 32009791ed..a36b6584b3 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -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); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index f6ade86acf..f790a5d778 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -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; diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 87901c7933..b0498e5532 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -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(¶m->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(¶m->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(¶m->fptr->op_array, precv->op2)) == IS_CONSTANT) { + RETURN_STR(zend_string_copy(Z_STR_P(RT_CONSTANT(¶m->fptr->op_array, precv->op2)))); } } /* }}} */ diff --git a/ext/standard/array.c b/ext/standard/array.c index bacd98cf30..1f03e5acb8 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -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; - - 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; - } + 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; - 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); - } + 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_TYPE_P(dest_zval) == IS_NULL) { - convert_to_array_ex(dest_zval); - add_next_index_null(dest_zval); + if (Z_ISREF_P(dest_entry)) { + if (Z_REFCOUNT_P(dest_entry) == 1) { + ZVAL_UNREF(dest_entry); } else { - convert_to_array_ex(dest_zval); + 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++; } - ZVAL_UNDEF(&tmp); - if (Z_TYPE_P(src_zval) == IS_OBJECT) { - ZVAL_DUP(&tmp, src_zval); - convert_to_array(&tmp); - src_zval = &tmp; + 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 (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); + if (!ret) { + return 0; } - 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); + } } } } diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h index 2c9b16463c..dee00e6218 100644 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@ -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); |