summaryrefslogtreecommitdiff
path: root/Zend/zend_operators.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r--Zend/zend_operators.c157
1 files changed, 83 insertions, 74 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index c08622084d..a19990e605 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -217,6 +217,9 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
ZVAL_COPY(&(holder), op); \
convert_to_long_base(&(holder), 10); \
if (UNEXPECTED(EG(exception))) { \
+ if (result != op1) { \
+ ZVAL_UNDEF(result); \
+ } \
return FAILURE; \
} \
if (Z_TYPE(holder) == IS_LONG) { \
@@ -252,7 +255,7 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
/* }}} */
-#define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, op, op_func) \
+#define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, op, op_func) \
do { \
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { \
if (Z_ISREF_P(op1)) { \
@@ -265,6 +268,9 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(op, op_func); \
op1_lval = _zval_get_long_func_noisy(op1); \
if (UNEXPECTED(EG(exception))) { \
+ if (result != op1) { \
+ ZVAL_UNDEF(result); \
+ } \
return FAILURE; \
} \
} else { \
@@ -283,6 +289,9 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(op); \
op2_lval = _zval_get_long_func_noisy(op2); \
if (UNEXPECTED(EG(exception))) { \
+ if (result != op1) { \
+ ZVAL_UNDEF(result); \
+ } \
return FAILURE; \
} \
} else { \
@@ -421,19 +430,6 @@ try_again:
ZEND_API void ZEND_FASTCALL convert_to_null(zval *op) /* {{{ */
{
- if (Z_TYPE_P(op) == IS_OBJECT) {
- if (Z_OBJ_HT_P(op)->cast_object) {
- zval org;
-
- ZVAL_COPY_VALUE(&org, op);
- if (Z_OBJ_HT_P(op)->cast_object(&org, op, IS_NULL) == SUCCESS) {
- zval_dtor(&org);
- return;
- }
- ZVAL_COPY_VALUE(op, &org);
- }
- }
-
zval_ptr_dtor(op);
ZVAL_NULL(op);
}
@@ -529,11 +525,7 @@ try_again:
break;
}
case IS_TRUE:
- if (CG(one_char_string)['1']) {
- ZVAL_INTERNED_STR(op, CG(one_char_string)['1']);
- } else {
- ZVAL_NEW_STR(op, zend_string_init("1", 1, 0));
- }
+ ZVAL_INTERNED_STR(op, ZSTR_CHAR('1'));
break;
case IS_STRING:
break;
@@ -545,7 +537,7 @@ try_again:
break;
}
case IS_LONG: {
- ZVAL_NEW_STR(op, zend_long_to_str(Z_LVAL_P(op)));
+ ZVAL_STR(op, zend_long_to_str(Z_LVAL_P(op)));
break;
}
case IS_DOUBLE: {
@@ -611,25 +603,17 @@ try_again:
if (obj_ht) {
zend_array *arr;
+ /* fast copy */
if (!Z_OBJCE_P(op)->default_properties_count &&
obj_ht == Z_OBJ_P(op)->properties &&
- !ZEND_HASH_GET_APPLY_COUNT(Z_OBJ_P(op)->properties)) {
- /* fast copy */
- if (EXPECTED(Z_OBJ_P(op)->handlers == &std_object_handlers)) {
- arr = obj_ht;
- if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(op)->properties) & IS_ARRAY_IMMUTABLE))) {
- GC_REFCOUNT(Z_OBJ_P(op)->properties)++;
- }
- } else {
- arr = zend_array_dup(obj_ht);
- }
- zval_dtor(op);
- ZVAL_ARR(op, arr);
+ !ZEND_HASH_GET_APPLY_COUNT(Z_OBJ_P(op)->properties) &&
+ EXPECTED(Z_OBJ_P(op)->handlers == &std_object_handlers)) {
+ arr = zend_proptable_to_symtable(obj_ht, 0);
} else {
- arr = zend_array_dup(obj_ht);
- zval_dtor(op);
- ZVAL_ARR(op, arr);
+ arr = zend_proptable_to_symtable(obj_ht, 1);
}
+ zval_dtor(op);
+ ZVAL_ARR(op, arr);
return;
}
} else {
@@ -668,10 +652,12 @@ try_again:
case IS_ARRAY:
{
HashTable *ht = Z_ARR_P(op);
- if (Z_IMMUTABLE_P(op)) {
+ ht = zend_symtable_to_proptable(ht);
+ if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
/* TODO: try not to duplicate immutable arrays as well ??? */
ht = zend_array_dup(ht);
}
+ zval_dtor(op);
object_and_properties_init(op, zend_standard_class_def, ht);
break;
}
@@ -687,7 +673,7 @@ try_again:
zval tmp;
ZVAL_COPY_VALUE(&tmp, op);
object_init(op);
- zend_hash_add_new(Z_OBJPROP_P(op), CG(known_strings)[ZEND_STR_SCALAR], &tmp);
+ zend_hash_add_new(Z_OBJPROP_P(op), ZSTR_KNOWN(ZEND_STR_SCALAR), &tmp);
break;
}
}
@@ -860,11 +846,7 @@ try_again:
case IS_FALSE:
return ZSTR_EMPTY_ALLOC();
case IS_TRUE:
- if (CG(one_char_string)['1']) {
- return CG(one_char_string)['1'];
- } else {
- return zend_string_init("1", 1, 0);
- }
+ return ZSTR_CHAR('1');
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;
@@ -960,6 +942,9 @@ ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* {
}
converted = 1;
} else {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
zend_throw_error(NULL, "Unsupported operand types");
return FAILURE; /* unknown datatype */
}
@@ -1007,6 +992,9 @@ ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* {
}
converted = 1;
} else {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
zend_throw_error(NULL, "Unsupported operand types");
return FAILURE; /* unknown datatype */
}
@@ -1059,6 +1047,9 @@ ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2) /* {
}
converted = 1;
} else {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
zend_throw_error(NULL, "Unsupported operand types");
return FAILURE; /* unknown datatype */
}
@@ -1157,6 +1148,9 @@ ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* {
}
converted = 1;
} else {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
zend_throw_error(NULL, "Unsupported operand types");
return FAILURE;
}
@@ -1227,6 +1221,9 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {
}
converted = 1;
} else {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
zend_throw_error(NULL, "Unsupported operand types");
return FAILURE; /* unknown datatype */
}
@@ -1239,7 +1236,7 @@ ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* {
{
zend_long op1_lval, op2_lval;
- convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_MOD, mod_function);
+ convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_MOD, mod_function);
if (op2_lval == 0) {
/* modulus by zero */
@@ -1359,11 +1356,7 @@ try_again:
if (Z_STRLEN_P(op1) == 1) {
zend_uchar not = (zend_uchar) ~*Z_STRVAL_P(op1);
- if (CG(one_char_string)[not]) {
- ZVAL_INTERNED_STR(result, CG(one_char_string)[not]);
- } else {
- ZVAL_NEW_STR(result, zend_string_init((char *) &not, 1, 0));
- }
+ ZVAL_INTERNED_STR(result, ZSTR_CHAR(not));
} else {
ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(op1), 0));
for (i = 0; i < Z_STRLEN_P(op1); i++) {
@@ -1379,6 +1372,9 @@ try_again:
default:
ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BW_NOT);
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
zend_throw_error(NULL, "Unsupported operand types");
return FAILURE;
}
@@ -1408,11 +1404,7 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op
if (result==op1) {
zend_string_release(Z_STR_P(result));
}
- if (CG(one_char_string)[or]) {
- ZVAL_INTERNED_STR(result, CG(one_char_string)[or]);
- } else {
- ZVAL_NEW_STR(result, zend_string_init((char *) &or, 1, 0));
- }
+ ZVAL_INTERNED_STR(result, ZSTR_CHAR(or));
return SUCCESS;
}
longer = op1;
@@ -1438,6 +1430,9 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_OR, bitwise_or_function);
op1_lval = _zval_get_long_func_noisy(op1);
if (UNEXPECTED(EG(exception))) {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
} else {
@@ -1447,6 +1442,9 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_OR);
op2_lval = _zval_get_long_func_noisy(op2);
if (UNEXPECTED(EG(exception))) {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
} else {
@@ -1484,11 +1482,7 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o
if (result==op1) {
zend_string_release(Z_STR_P(result));
}
- if (CG(one_char_string)[and]) {
- ZVAL_INTERNED_STR(result, CG(one_char_string)[and]);
- } else {
- ZVAL_NEW_STR(result, zend_string_init((char *) &and, 1, 0));
- }
+ ZVAL_INTERNED_STR(result, ZSTR_CHAR(and));
return SUCCESS;
}
longer = op1;
@@ -1514,6 +1508,9 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function);
op1_lval = _zval_get_long_func_noisy(op1);
if (UNEXPECTED(EG(exception))) {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
} else {
@@ -1523,6 +1520,9 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_AND);
op2_lval = _zval_get_long_func_noisy(op2);
if (UNEXPECTED(EG(exception))) {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
} else {
@@ -1560,11 +1560,7 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o
if (result==op1) {
zend_string_release(Z_STR_P(result));
}
- if (CG(one_char_string)[xor]) {
- ZVAL_INTERNED_STR(result, CG(one_char_string)[xor]);
- } else {
- ZVAL_NEW_STR(result, zend_string_init((char *) &xor, 1, 0));
- }
+ ZVAL_INTERNED_STR(result, ZSTR_CHAR(xor));
return SUCCESS;
}
longer = op1;
@@ -1590,6 +1586,9 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function);
op1_lval = _zval_get_long_func_noisy(op1);
if (UNEXPECTED(EG(exception))) {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
} else {
@@ -1599,6 +1598,9 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_XOR);
op2_lval = _zval_get_long_func_noisy(op2);
if (UNEXPECTED(EG(exception))) {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
} else {
@@ -1617,7 +1619,7 @@ ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op
{
zend_long op1_lval, op2_lval;
- convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SL, shift_left_function);
+ convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_SL, shift_left_function);
/* prevent wrapping quirkiness on some processors where << 64 + x == << x */
if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
@@ -1653,7 +1655,7 @@ ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *o
{
zend_long op1_lval, op2_lval;
- convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SR, shift_right_function);
+ convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_SR, shift_right_function);
/* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */
if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
@@ -1702,6 +1704,9 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /
if (use_copy1) {
if (UNEXPECTED(EG(exception))) {
zval_dtor(&op1_copy);
+ if (orig_op1 != result) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
if (result == op1) {
@@ -1727,6 +1732,9 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /
zval_dtor(op1);
}
zval_dtor(&op2_copy);
+ if (orig_op1 != result) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
op2 = &op2_copy;
@@ -2285,12 +2293,7 @@ static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */
if (Z_STRLEN_P(str) == 0) {
zend_string_release(Z_STR_P(str));
- if (CG(one_char_string)['1']) {
- ZVAL_INTERNED_STR(str, CG(one_char_string)['1']);
- } else {
- Z_STR_P(str) = zend_string_init("1", sizeof("1")-1, 0);
- Z_TYPE_INFO_P(str) = IS_STRING_EX;
- }
+ ZVAL_INTERNED_STR(str, ZSTR_CHAR('1'));
return;
}
@@ -2873,9 +2876,13 @@ ZEND_API void ZEND_FASTCALL zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_D
ZEND_API zend_string* ZEND_FASTCALL zend_long_to_str(zend_long num) /* {{{ */
{
- char buf[MAX_LENGTH_OF_LONG + 1];
- char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, num);
- return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
+ if ((zend_ulong)num <= 9) {
+ return ZSTR_CHAR((zend_uchar)'0' + (zend_uchar)num);
+ } else {
+ char buf[MAX_LENGTH_OF_LONG + 1];
+ char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, num);
+ return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
+ }
}
/* }}} */
@@ -3146,4 +3153,6 @@ ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d)
* c-basic-offset: 4
* indent-tabs-mode: t
* End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
*/