summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend.h20
-rw-r--r--Zend/zend_ast.c359
-rw-r--r--Zend/zend_ast.h47
-rw-r--r--Zend/zend_builtin_functions.c2
-rw-r--r--Zend/zend_compile.c17
-rw-r--r--Zend/zend_compile.h6
-rw-r--r--Zend/zend_execute_API.c341
-rw-r--r--Zend/zend_extensions.h2
-rw-r--r--Zend/zend_language_parser.y80
-rw-r--r--Zend/zend_operators.c62
-rw-r--r--Zend/zend_operators.h4
-rw-r--r--Zend/zend_variables.c8
-rw-r--r--Zend/zend_vm_def.h1
-rw-r--r--Zend/zend_vm_execute.h1
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c56
-rw-r--r--ext/opcache/zend_persist.c29
-rw-r--r--ext/opcache/zend_persist_calc.c27
17 files changed, 656 insertions, 406 deletions
diff --git a/Zend/zend.h b/Zend/zend.h
index a949c5b0b6..a95473b76e 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -579,18 +579,18 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
/* data types */
/* All data types <= IS_BOOL have their constructor/destructors skipped */
-#define IS_NULL 0
-#define IS_LONG 1
-#define IS_DOUBLE 2
-#define IS_BOOL 3
-#define IS_ARRAY 4
-#define IS_OBJECT 5
-#define IS_STRING 6
-#define IS_RESOURCE 7
-#define IS_CONSTANT 8
+#define IS_NULL 0
+#define IS_LONG 1
+#define IS_DOUBLE 2
+#define IS_BOOL 3
+#define IS_ARRAY 4
+#define IS_OBJECT 5
+#define IS_STRING 6
+#define IS_RESOURCE 7
+#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
#define IS_CONSTANT_AST 10
-#define IS_CALLABLE 11
+#define IS_CALLABLE 11
/* Ugly hack to support constants as static array indices */
#define IS_CONSTANT_TYPE_MASK 0x00f
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index 21c08da510..7ebb8d2796 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -13,118 +13,317 @@
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Bob Weinand <bwoebi@php.net> |
+ | Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include "zend_ast.h"
-#include "zend_execute.h"
+#include "zend_API.h"
+#include "zend_operators.h"
-#define COPY_ZVAL_TO_OP(nr) \
- if (op##nr) { \
- Z_AST_P(result)->ops[nr] = emalloc(sizeof(zval)); \
- *Z_AST_P(result)->ops[nr] = *op##nr; \
- } else { \
- Z_AST_P(result)->ops[nr] = NULL; \
- }
-
-void zend_ast_add(zval *result, intermediary_ast_function_type func, char op_count) {
- zend_ast *ast = emalloc(sizeof(zend_ast) + op_count * sizeof(zval *));
- ast->op_count = op_count;
- ast->ops = (zval **)(ast + 1);
- ast->refcount = 1;
- ast->func = func;
- Z_AST_P(result) = ast;
- Z_TYPE_P(result) = IS_CONSTANT_AST;
+ZEND_API zend_ast *zend_ast_create_constant_node(zval *zv)
+{
+ zend_ast *node = emalloc(sizeof(zend_ast) + sizeof(zval));
+ node->kind = ZEND_CONST;
+ node->children = 0;
+ node->u.val = (zval*)(node + 1);
+ INIT_PZVAL_COPY(node->u.val, zv);
+ return node;
}
-/* Do operations on constant operators at compile time (AST building time) */
-
-void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0 TSRMLS_DC) {
- if (!op0 || !IS_CONSTANT_TYPE(Z_TYPE_P(op0))) {
- func(result, op0 TSRMLS_CC);
- if (op0) zval_dtor(op0);
- return;
- }
-
- zend_ast_add(result, (intermediary_ast_function_type)func, 1);
- COPY_ZVAL_TO_OP(0)
+ZEND_API zend_ast* zend_ast_create_node1(uint kind, zend_ast *op0)
+{
+ zend_ast *node = emalloc(sizeof(zend_ast));
+ node->kind = kind;
+ node->children = 1;
+ node->u.child[0] = op0;
+ return node;
}
-void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1 TSRMLS_DC) {
- if ((!op0 || !IS_CONSTANT_TYPE(Z_TYPE_P(op0))) && (!op1 || !IS_CONSTANT_TYPE(Z_TYPE_P(op1)))) {
- func(result, op0, op1 TSRMLS_CC);
- if (op0) zval_dtor(op0);
- if (op1) zval_dtor(op1);
- return;
- }
-
- zend_ast_add(result, (intermediary_ast_function_type)func, 2);
- COPY_ZVAL_TO_OP(0)
- COPY_ZVAL_TO_OP(1)
+ZEND_API zend_ast* zend_ast_create_node2(uint kind, zend_ast *op0, zend_ast *op1)
+{
+ zend_ast *node = emalloc(sizeof(zend_ast) + sizeof(zend_ast*));
+ node->kind = kind;
+ node->children = 2;
+ node->u.child[0] = op0;
+ node->u.child[1] = op1;
+ return node;
}
-void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2 TSRMLS_DC) {
- if ((!op0 || !IS_CONSTANT_TYPE(Z_TYPE_P(op0))) && (!op1 || !IS_CONSTANT_TYPE(Z_TYPE_P(op1))) && (!op2 || !IS_CONSTANT_TYPE(Z_TYPE_P(op2)))) {
- func(result, op0, op1, op2 TSRMLS_CC);
- if (op0) zval_dtor(op0);
- if (op1) zval_dtor(op1);
- if (op2) zval_dtor(op2);
- return;
- }
-
- zend_ast_add(result, (intermediary_ast_function_type)func, 3);
- COPY_ZVAL_TO_OP(0)
- COPY_ZVAL_TO_OP(1)
- COPY_ZVAL_TO_OP(2)
+ZEND_API zend_ast* zend_ast_create_node3(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2)
+{
+ zend_ast *node = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 2);
+ node->kind = kind;
+ node->children = 3;
+ node->u.child[0] = op0;
+ node->u.child[1] = op1;
+ node->u.child[2] = op2;
+ return node;
}
-void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC) {
+ZEND_API int zend_ast_is_ct_constant(zend_ast *ast)
+{
int i;
- zval **ops = emalloc((sizeof(zval *) + sizeof(zval)) * ast->op_count);
- for (i = ast->op_count; i--;) {
- if (ast->ops[i] && IS_CONSTANT_TYPE(Z_TYPE_P(ast->ops[i]))) {
- ops[i] = ((zval *)(ops + ast->op_count)) + i;
- *ops[i] = *ast->ops[i];
- zval_copy_ctor(ops[i]);
- zval_update_constant_ex(&ops[i], (void *)1, NULL TSRMLS_CC);
- } else {
- ops[i] = ast->ops[i];
+ if (ast->kind == ZEND_CONST) {
+ return !IS_CONSTANT_TYPE(Z_TYPE_P(ast->u.val));
+ } else {
+ for (i = 0; i < ast->children; i++) {
+ if (ast->u.child[i]) {
+ if (!zend_ast_is_ct_constant(ast->u.child[i])) {
+ return 0;
+ }
+ }
}
+ return 1;
}
+}
+
+ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC)
+{
+ zval op1, op2;
- switch (ast->op_count) {
- case 1:
- ((unary_ast_func)ast->func)(result, ops[0] TSRMLS_CC);
+ switch (ast->kind) {
+ case ZEND_ADD:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ add_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_SUB:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ sub_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_MUL:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ mul_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_DIV:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ div_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_MOD:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ mod_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_SL:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ shift_left_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_SR:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ shift_right_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_CONCAT:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ concat_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_BW_OR:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ bitwise_or_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
break;
- case 2:
- ((binary_ast_func)ast->func)(result, ops[0], ops[1] TSRMLS_CC);
+ case ZEND_BW_AND:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ bitwise_and_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
break;
- case 3:
- ((ternary_ast_func)ast->func)(result, ops[0], ops[1], ops[2] TSRMLS_CC);
+ case ZEND_BW_XOR:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ bitwise_xor_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
break;
+ case ZEND_BW_NOT:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ bitwise_not_function(result, &op1 TSRMLS_CC);
+ zval_dtor(&op1);
+ break;
+ case ZEND_BOOL_NOT:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ boolean_not_function(result, &op1 TSRMLS_CC);
+ zval_dtor(&op1);
+ break;
+ case ZEND_BOOL_XOR:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ boolean_xor_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_IS_IDENTICAL:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ is_identical_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_IS_NOT_IDENTICAL:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ is_not_identical_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_IS_EQUAL:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ is_equal_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_IS_NOT_EQUAL:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ is_not_equal_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_IS_SMALLER:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ is_smaller_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_IS_SMALLER_OR_EQUAL:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ is_smaller_or_equal_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+ case ZEND_CONST:
+ *result = *ast->u.val;
+ zval_copy_ctor(result);
+ if (IS_CONSTANT_TYPE(Z_TYPE_P(result))) {
+ zval_update_constant(&result, (void *) 1 TSRMLS_CC);
+ }
+ break;
+ case ZEND_BOOL_AND:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ if (zend_is_true(&op1)) {
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ ZVAL_BOOL(result, zend_is_true(&op2));
+ zval_dtor(&op2);
+ } else {
+ ZVAL_BOOL(result, 0);
+ }
+ zval_dtor(&op1);
+ break;
+ case ZEND_BOOL_OR:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ if (zend_is_true(&op1)) {
+ ZVAL_BOOL(result, 1);
+ } else {
+ zend_ast_evaluate(&op2, ast->u.child[1] TSRMLS_CC);
+ ZVAL_BOOL(result, zend_is_true(&op2));
+ zval_dtor(&op2);
+ }
+ zval_dtor(&op1);
+ break;
+ case ZEND_TERNARY:
+ zend_ast_evaluate(&op1, ast->u.child[0] TSRMLS_CC);
+ if (zend_is_true(&op1)) {
+ if (!ast->u.child[1]) {
+ *result = op1;
+ } else {
+ zend_ast_evaluate(result, ast->u.child[1] TSRMLS_CC);
+ zval_dtor(&op1);
+ }
+ } else {
+ zend_ast_evaluate(result, ast->u.child[2] TSRMLS_CC);
+ zval_dtor(&op1);
+ }
+ break;
+ case ZEND_UNARY_PLUS:
+ ZVAL_LONG(&op1, 0);
+ zend_ast_evaluate(&op2, ast->u.child[0] TSRMLS_CC);
+ add_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op2);
+ break;
+ case ZEND_UNARY_MINUS:
+ ZVAL_LONG(&op1, 0);
+ zend_ast_evaluate(&op2, ast->u.child[0] TSRMLS_CC);
+ sub_function(result, &op1, &op2 TSRMLS_CC);
+ zval_dtor(&op2);
+ break;
+ default:
+ zend_error(E_ERROR, "Unsupported constant expression");
}
+}
- for (i = ast->op_count; i--;) {
- if (ast->ops[i] != ops[i]) {
- zval_dtor(ops[i]);
+ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
+{
+ if (ast == NULL) {
+ return NULL;
+ } else if (ast->kind == ZEND_CONST) {
+ zend_ast *node = zend_ast_create_constant_node(ast->u.val);
+ zval_copy_ctor(node->u.val);
+ return node;
+ } else {
+ switch (ast->children) {
+ case 1:
+ return zend_ast_create_node1(
+ ast->kind,
+ zend_ast_copy(ast->u.child[0]));
+ case 2:
+ return zend_ast_create_node2(
+ ast->kind,
+ zend_ast_copy(ast->u.child[0]),
+ zend_ast_copy(ast->u.child[1]));
+ case 3:
+ return zend_ast_create_node3(
+ ast->kind,
+ zend_ast_copy(ast->u.child[0]),
+ zend_ast_copy(ast->u.child[1]),
+ zend_ast_copy(ast->u.child[2]));
}
}
-
- efree(ops);
+ return NULL;
}
-void zend_ast_destroy(zend_ast *ast TSRMLS_DC) {
+ZEND_API void zend_ast_destroy(zend_ast *ast)
+{
int i;
- for (i = ast->op_count; i--;) {
- if (ast->ops[i] && !Z_DELREF_P(ast->ops[i])) {
- zval_dtor(ast->ops[i]);
- efree(ast->ops[i]);
+ if (ast->kind == ZEND_CONST) {
+ zval_dtor(ast->u.val);
+ } else {
+ for (i = 0; i < ast->children; i++) {
+ if (ast->u.child[i]) {
+ zend_ast_destroy(ast->u.child[i]);
+ }
}
}
-
efree(ast);
}
diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h
index 218f2c02e0..4c94cf8ac2 100644
--- a/Zend/zend_ast.h
+++ b/Zend/zend_ast.h
@@ -13,6 +13,7 @@
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Bob Weinand <bwoebi@php.net> |
+ | Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
@@ -25,36 +26,36 @@ typedef struct _zend_ast zend_ast;
#include "zend.h"
-typedef void(*intermediary_ast_function_type)(zval *, ...);
-typedef int(*unary_ast_func)(zval *result, zval *op0 TSRMLS_DC);
-typedef int(*binary_ast_func)(zval *result, zval *op0, zval *op1 TSRMLS_DC);
-typedef int(*ternary_ast_func)(zval *result, zval *op0, zval *op1, zval *op2 TSRMLS_DC);
+typedef enum _zend_ast_node_kind {
+ /* first 256 node kinds are reserved for opcodes */
+ ZEND_CONST = 256,
+ ZEND_BOOL_AND,
+ ZEND_BOOL_OR,
+ ZEND_TERNARY,
+ ZEND_UNARY_PLUS,
+ ZEND_UNARY_MINUS,
+} zend_ast_ode_kind;
struct _zend_ast {
- char op_count;
- zval **ops;
- intermediary_ast_function_type func;
- int refcount;
+ unsigned short kind;
+ unsigned short children;
+ union {
+ zval *val;
+ zend_ast *child[1];
+ } u;
};
-void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0 TSRMLS_DC);
-void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1 TSRMLS_DC);
-void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2 TSRMLS_DC);
+ZEND_API zend_ast *zend_ast_create_constant_node(zval *zv);
-void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC);
+ZEND_API zend_ast *zend_ast_create_node1(uint kind, zend_ast *op0);
+ZEND_API zend_ast *zend_ast_create_node2(uint kind, zend_ast *op0, zend_ast *op1);
+ZEND_API zend_ast *zend_ast_create_node3(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2);
-void zend_ast_destroy(zend_ast *ast TSRMLS_DC);
+ZEND_API int zend_ast_is_ct_constant(zend_ast *ast);
-#define ZEND_AST_ADD_REF(ast) ++ast->refcount
+ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC);
-static inline int ZEND_AST_DEL_REF(zend_ast *ast) {
- if (ast->refcount == 1) {
- TSRMLS_FETCH();
-
- zend_ast_destroy(ast TSRMLS_CC);
- return 0;
- }
- return --ast->refcount;
-}
+ZEND_API zend_ast *zend_ast_copy(zend_ast *ast);
+ZEND_API void zend_ast_destroy(zend_ast *ast);
#endif
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 049864c54a..d779e8a5ee 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -946,7 +946,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
/* this is necessary to make it able to work with default array
* properties, returned to user */
- switch (IS_CONSTANT_TYPE(Z_TYPE_P(prop_copy))) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_P(prop_copy))) {
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 77da945153..07a9ae88d0 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -5793,8 +5793,8 @@ void zend_do_add_static_array_element(znode *result, znode *offset, const znode
key[len + 1] = 0;
zend_symtable_update(Z_ARRVAL(result->u.constant), key, len + 2, &element, sizeof(zval *), NULL);
efree(key);
+ break;
}
- break;
case IS_STRING:
zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+1, &element, sizeof(zval *), NULL);
zval_dtor(&offset->u.constant);
@@ -7133,6 +7133,21 @@ void zend_do_end_compilation(TSRMLS_D) /* {{{ */
}
/* }}} */
+void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ if (ast->kind == ZEND_CONST) {
+ result->u.constant = *ast->u.val;
+ efree(ast);
+ } else if (zend_ast_is_ct_constant(ast)) {
+ zend_ast_evaluate(&result->u.constant, ast TSRMLS_CC);
+ zend_ast_destroy(ast);
+ } else {
+ Z_TYPE(result->u.constant) = IS_CONSTANT_AST;
+ Z_AST(result->u.constant) = ast;
+ }
+}
+/* }}} */
+
/* {{{ zend_dirname
Returns directory name component of path */
ZEND_API size_t zend_dirname(char *path, size_t len)
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index b80a7cb84f..76b5348e37 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -93,6 +93,7 @@ typedef struct _znode { /* used only during compilation */
znode_op op;
zval constant; /* replaced by literal/zv */
zend_op_array *op_array;
+ zend_ast *ast;
} u;
zend_uint EA; /* extended attributes */
} znode;
@@ -639,6 +640,7 @@ void zend_do_end_namespace(TSRMLS_D);
void zend_verify_namespace(TSRMLS_D);
void zend_do_use(znode *name, znode *new_name, int is_global TSRMLS_DC);
void zend_do_end_compilation(TSRMLS_D);
+void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC);
void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC);
@@ -722,10 +724,6 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
#define ZEND_OP_DATA 137
-/* Pseudo-opcodes for internal object overloading */
-#define ZEND_BOOL_AND -1
-#define ZEND_BOOL_OR -2
-
/* END: OPCODES */
/* class fetches */
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 12047f0518..769b333d9d 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -478,205 +478,200 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
if (IS_CONSTANT_VISITED(p)) {
zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
- return FAILURE;
- }
- switch (Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) {
- case IS_CONSTANT: {
- int refcount;
- zend_uchar is_ref;
+ } else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
+ int refcount;
+ zend_uchar is_ref;
- SEPARATE_ZVAL_IF_NOT_REF(pp);
- p = *pp;
+ SEPARATE_ZVAL_IF_NOT_REF(pp);
+ p = *pp;
- MARK_CONSTANT_VISITED(p);
+ MARK_CONSTANT_VISITED(p);
- refcount = Z_REFCOUNT_P(p);
- is_ref = Z_ISREF_P(p);
+ refcount = Z_REFCOUNT_P(p);
+ is_ref = Z_ISREF_P(p);
- if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
- char *actual = Z_STRVAL_P(p);
+ if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
+ char *actual = Z_STRVAL_P(p);
- if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
- zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
- Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
+ if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
+ zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
+ Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
+ if (inline_change) {
+ colon = estrndup(colon, Z_STRLEN_P(p));
+ str_efree(Z_STRVAL_P(p));
+ Z_STRVAL_P(p) = colon;
+ } else {
+ Z_STRVAL_P(p) = colon + 1;
+ }
+ } else {
+ char *save = actual, *slash;
+ int actual_len = Z_STRLEN_P(p);
+ if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
+ actual = slash + 1;
+ actual_len -= (actual - Z_STRVAL_P(p));
if (inline_change) {
- colon = estrndup(colon, Z_STRLEN_P(p));
- str_efree(Z_STRVAL_P(p));
- Z_STRVAL_P(p) = colon;
- } else {
- Z_STRVAL_P(p) = colon + 1;
+ actual = estrndup(actual, actual_len);
+ Z_STRVAL_P(p) = actual;
+ Z_STRLEN_P(p) = actual_len;
}
- } else {
- char *save = actual, *slash;
- int actual_len = Z_STRLEN_P(p);
- if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
- actual = slash + 1;
- actual_len -= (actual - Z_STRVAL_P(p));
- if (inline_change) {
- actual = estrndup(actual, actual_len);
- Z_STRVAL_P(p) = actual;
- Z_STRLEN_P(p) = actual_len;
- }
+ }
+ if (actual[0] == '\\') {
+ if (inline_change) {
+ memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
+ --Z_STRLEN_P(p);
+ } else {
+ ++actual;
}
- if (actual[0] == '\\') {
- if (inline_change) {
- memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p)--);
- } else {
- ++actual;
- }
- --actual_len;
+ --actual_len;
+ }
+ if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
+ int fix_save = 0;
+ if (save[0] == '\\') {
+ save++;
+ fix_save = 1;
}
- if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
- int fix_save = 0;
- if (save[0] == '\\') {
- save++;
- fix_save = 1;
- }
- zend_error(E_ERROR, "Undefined constant '%s'", save);
- if (fix_save) {
- save--;
- }
- if (inline_change) {
- str_efree(save);
- }
- save = NULL;
+ zend_error(E_ERROR, "Undefined constant '%s'", save);
+ if (fix_save) {
+ save--;
}
- if (inline_change && save && save != actual) {
+ if (inline_change) {
str_efree(save);
}
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
- p->type = IS_STRING;
- if (!inline_change) {
- Z_STRVAL_P(p) = actual;
- Z_STRLEN_P(p) = actual_len;
- zval_copy_ctor(p);
- }
+ save = NULL;
}
- } else {
- if (inline_change) {
- str_efree(Z_STRVAL_P(p));
+ if (inline_change && save && save != actual) {
+ str_efree(save);
}
- *p = const_value;
+ zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
+ p->type = IS_STRING;
+ if (!inline_change) {
+ Z_STRVAL_P(p) = actual;
+ Z_STRLEN_P(p) = actual_len;
+ zval_copy_ctor(p);
+ }
+ }
+ } else {
+ if (inline_change) {
+ str_efree(Z_STRVAL_P(p));
}
+ *p = const_value;
+ }
- Z_SET_REFCOUNT_P(p, refcount);
- Z_SET_ISREF_TO_P(p, is_ref);
+ Z_SET_REFCOUNT_P(p, refcount);
+ Z_SET_ISREF_TO_P(p, is_ref);
+ } else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) {
+ zval **element, *new_val;
+ char *str_index;
+ uint str_index_len;
+ ulong num_index;
+ int ret;
+
+ SEPARATE_ZVAL_IF_NOT_REF(pp);
+ p = *pp;
+ Z_TYPE_P(p) = IS_ARRAY;
+
+ if (!inline_change) {
+ zval *tmp;
+ HashTable *tmp_ht = NULL;
+
+ ALLOC_HASHTABLE(tmp_ht);
+ zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
+ Z_ARRVAL_P(p) = tmp_ht;
}
- break;
-
- case IS_CONSTANT_ARRAY: {
- zval **element, *new_val;
- char *str_index;
- uint str_index_len;
- ulong num_index;
- int ret;
-
- SEPARATE_ZVAL_IF_NOT_REF(pp);
- p = *pp;
- Z_TYPE_P(p) = IS_ARRAY;
-
- if (!inline_change) {
- zval *tmp;
- HashTable *tmp_ht = NULL;
-
- ALLOC_HASHTABLE(tmp_ht);
- zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
- Z_ARRVAL_P(p) = tmp_ht;
- }
- /* First go over the array and see if there are any constant indices */
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
- while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
- if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
- zend_hash_move_forward(Z_ARRVAL_P(p));
- continue;
- }
- Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
- if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
- zend_hash_move_forward(Z_ARRVAL_P(p));
- continue;
- }
- if (str_index[str_index_len - 2] == IS_CONSTANT_AST) {
- zend_ast_evaluate(&const_value, *(zend_ast **)str_index TSRMLS_CC);
- ZEND_AST_DEL_REF(*(zend_ast **)str_index);
- } else if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
- char *actual;
- const char *save = str_index;
- if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
- zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
- str_index_len -= ((colon - str_index) + 1);
- str_index = colon;
- } else {
- if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
- if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
- actual++;
- str_index_len -= (actual - str_index);
- str_index = actual;
- }
- }
- if (str_index[0] == '\\') {
- ++str_index;
- --str_index_len;
- }
- if (save[0] == '\\') {
- ++save;
- }
- if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
- zend_error(E_ERROR, "Undefined constant '%s'", save);
+ /* First go over the array and see if there are any constant indices */
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
+ while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
+ if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
+ zend_hash_move_forward(Z_ARRVAL_P(p));
+ continue;
+ }
+ Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
+ if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
+ zend_hash_move_forward(Z_ARRVAL_P(p));
+ continue;
+ }
+ if (str_index[str_index_len - 2] == IS_CONSTANT_AST) {
+ zend_ast_evaluate(&const_value, *(zend_ast **)str_index TSRMLS_CC);
+ zend_ast_destroy(*(zend_ast **)str_index);
+ } else if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
+ char *actual;
+ const char *save = str_index;
+ if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
+ zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
+ str_index_len -= ((colon - str_index) + 1);
+ str_index = colon;
+ } else {
+ if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
+ if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
+ actual++;
+ str_index_len -= (actual - str_index);
+ str_index = actual;
}
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
}
- ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
+ if (str_index[0] == '\\') {
+ ++str_index;
+ --str_index_len;
+ }
+ if (save[0] == '\\') {
+ ++save;
+ }
+ if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
+ zend_error(E_ERROR, "Undefined constant '%s'", save);
+ }
+ zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
}
+ ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
+ }
- if (Z_REFCOUNT_PP(element) > 1) {
- ALLOC_ZVAL(new_val);
- *new_val = **element;
- zval_copy_ctor(new_val);
- Z_SET_REFCOUNT_P(new_val, 1);
- Z_UNSET_ISREF_P(new_val);
-
- /* preserve this bit for inheritance */
- Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
- zval_ptr_dtor(element);
- *element = new_val;
- }
+ if (Z_REFCOUNT_PP(element) > 1) {
+ ALLOC_ZVAL(new_val);
+ *new_val = **element;
+ zval_copy_ctor(new_val);
+ Z_SET_REFCOUNT_P(new_val, 1);
+ Z_UNSET_ISREF_P(new_val);
+
+ /* preserve this bit for inheritance */
+ Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
+ zval_ptr_dtor(element);
+ *element = new_val;
+ }
- switch (Z_TYPE(const_value)) {
- case IS_STRING:
- ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
- break;
- case IS_BOOL:
- case IS_LONG:
- ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
- break;
- case IS_DOUBLE:
- ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
- break;
- case IS_NULL:
- ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
- break;
- default:
- ret = SUCCESS;
- break;
- }
- if (ret == SUCCESS) {
- zend_hash_move_forward(Z_ARRVAL_P(p));
- }
- zval_dtor(&const_value);
+ switch (Z_TYPE(const_value)) {
+ case IS_STRING:
+ ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
+ break;
+ case IS_BOOL:
+ case IS_LONG:
+ ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
+ break;
+ case IS_DOUBLE:
+ ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
+ break;
+ case IS_NULL:
+ ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
+ break;
+ default:
+ ret = SUCCESS;
+ break;
+ }
+ if (ret == SUCCESS) {
+ zend_hash_move_forward(Z_ARRVAL_P(p));
}
- zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC);
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
+ zval_dtor(&const_value);
}
- break;
-
- case IS_CONSTANT_AST: {
- zend_ast *ast = Z_AST_P(p);
-
- zend_ast_evaluate(p, ast TSRMLS_CC);
- ZEND_AST_DEL_REF(ast);
+ zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC);
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
+ } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
+ SEPARATE_ZVAL_IF_NOT_REF(pp);
+ p = *pp;
+
+ zend_ast_evaluate(&const_value, Z_AST_P(p) TSRMLS_CC);
+ if (inline_change) {
+ zend_ast_destroy(Z_AST_P(p));
}
+ ZVAL_COPY_VALUE(p, &const_value);
}
return 0;
}
diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h
index 83cad7f38d..e7f289a656 100644
--- a/Zend/zend_extensions.h
+++ b/Zend/zend_extensions.h
@@ -28,7 +28,7 @@
/* The first number is the engine version and the rest is the date.
* This way engine 2/3 API no. is always greater than engine 1 API no..
*/
-#define ZEND_EXTENSION_API_NO 220121212
+#define ZEND_EXTENSION_API_NO 220131106
typedef struct _zend_extension_version_info {
int zend_extension_api_no;
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 19d6d839a2..b6926ea041 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -952,53 +952,53 @@ static_class_constant:
;
static_scalar: /* compile-time evaluated scalars */
- static_scalar_value { $$ = $1; }
- | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
- | '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
+ static_scalar_value { zend_do_constant_expression(&$$, $1.u.ast TSRMLS_CC); }
;
static_scalar_value:
- common_scalar { $$ = $1; }
- | static_class_name_scalar { $$ = $1; }
- | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); }
- | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); }
- | static_class_constant { $$ = $1; }
- | T_CLASS_C { $$ = $1; }
+ common_scalar { $$.u.ast = zend_ast_create_constant_node(&$1.u.constant); }
+ | static_class_name_scalar { $$.u.ast = zend_ast_create_constant_node(&$1.u.constant); }
+ | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); $$.u.ast = zend_ast_create_constant_node(&$$.u.constant); }
+ | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant_node(&$$.u.constant); }
+ | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant_node(&$$.u.constant); }
+ | static_class_constant { $$.u.ast = zend_ast_create_constant_node(&$1.u.constant); }
+ | T_CLASS_C { $$.u.ast = zend_ast_create_constant_node(&$1.u.constant); }
+ | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; $$.u.ast = zend_ast_create_constant_node(&$$.u.constant); }
+ | '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; $$.u.ast = zend_ast_create_constant_node(&$$.u.constant); }
| static_operation { $$ = $1; }
;
static_operation:
- static_scalar_value '+' static_scalar_value { zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value '-' static_scalar_value { zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value '*' static_scalar_value { zend_ast_add_binary(&$$.u.constant, mul_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value '/' static_scalar_value { zend_ast_add_binary(&$$.u.constant, div_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value '%' static_scalar_value { zend_ast_add_binary(&$$.u.constant, mod_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | '!' static_scalar_value { zend_ast_add_unary(&$$.u.constant, boolean_not_function, &$2.u.constant TSRMLS_CC); }
- | '~' static_scalar_value { zend_ast_add_unary(&$$.u.constant, bitwise_not_function, &$2.u.constant TSRMLS_CC); }
- | static_scalar_value '|' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value '&' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value '^' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_xor_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_SL static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_left_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_SR static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_right_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value '.' static_scalar_value { zend_ast_add_binary(&$$.u.constant, concat_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_LOGICAL_XOR static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_xor_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_LOGICAL_AND static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_LOGICAL_OR static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_BOOLEAN_AND static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_BOOLEAN_OR static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_IS_IDENTICAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_identical_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_IS_NOT_IDENTICAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_not_identical_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_IS_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_equal_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_IS_NOT_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_not_equal_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value '<' static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value '>' static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_function, &$3.u.constant, &$1.u.constant TSRMLS_CC); }
- | static_scalar_value T_IS_SMALLER_OR_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_or_equal_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
- | static_scalar_value T_IS_GREATER_OR_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_or_equal_function, &$3.u.constant, &$1.u.constant TSRMLS_CC); }
- | static_scalar_value '?' ':' static_scalar_value { zend_ast_add_ternary(&$$.u.constant, ternary_function, &$1.u.constant, NULL, &$4.u.constant TSRMLS_CC); }
- | static_scalar_value '?' static_scalar_value ':' static_scalar_value { zend_ast_add_ternary(&$$.u.constant, ternary_function, &$1.u.constant, &$3.u.constant, &$5.u.constant TSRMLS_CC); }
- | '+' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); }
- | '-' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); }
+ static_scalar_value '+' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_ADD, $1.u.ast, $3.u.ast); }
+ | static_scalar_value '-' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_SUB, $1.u.ast, $3.u.ast); }
+ | static_scalar_value '*' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_MUL, $1.u.ast, $3.u.ast); }
+ | static_scalar_value '/' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_DIV, $1.u.ast, $3.u.ast); }
+ | static_scalar_value '%' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_MOD, $1.u.ast, $3.u.ast); }
+ | '!' static_scalar_value { $$.u.ast = zend_ast_create_node1(ZEND_BOOL_NOT, $2.u.ast); }
+ | '~' static_scalar_value { $$.u.ast = zend_ast_create_node1(ZEND_BW_NOT, $2.u.ast); }
+ | static_scalar_value '|' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BW_OR, $1.u.ast, $3.u.ast); }
+ | static_scalar_value '&' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BW_AND, $1.u.ast, $3.u.ast); }
+ | static_scalar_value '^' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BW_XOR, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_SL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_SL, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_SR static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_SR, $1.u.ast, $3.u.ast); }
+ | static_scalar_value '.' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_CONCAT, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_LOGICAL_XOR static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BOOL_XOR, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_LOGICAL_AND static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BOOL_AND, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_LOGICAL_OR static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BOOL_OR, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_BOOLEAN_AND static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BOOL_AND, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_BOOLEAN_OR static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_BOOL_OR, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_IS_IDENTICAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_IDENTICAL, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_IS_NOT_IDENTICAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_NOT_IDENTICAL, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_IS_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_EQUAL, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_IS_NOT_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_NOT_EQUAL, $1.u.ast, $3.u.ast); }
+ | static_scalar_value '<' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_SMALLER, $1.u.ast, $3.u.ast); }
+ | static_scalar_value '>' static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_SMALLER, $3.u.ast, $1.u.ast); }
+ | static_scalar_value T_IS_SMALLER_OR_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_SMALLER_OR_EQUAL, $1.u.ast, $3.u.ast); }
+ | static_scalar_value T_IS_GREATER_OR_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_node2(ZEND_IS_SMALLER_OR_EQUAL, $3.u.ast, $1.u.ast); }
+ | static_scalar_value '?' ':' static_scalar_value { $$.u.ast = zend_ast_create_node3(ZEND_TERNARY, $1.u.ast, NULL, $4.u.ast); }
+ | static_scalar_value '?' static_scalar_value ':' static_scalar_value { $$.u.ast = zend_ast_create_node3(ZEND_TERNARY, $1.u.ast, $3.u.ast, $5.u.ast); }
+ | '+' static_scalar_value { $$.u.ast = zend_ast_create_node1(ZEND_UNARY_PLUS, $2.u.ast); }
+ | '-' static_scalar_value { $$.u.ast = zend_ast_create_node1(ZEND_UNARY_MINUS, $2.u.ast); }
| '(' static_scalar_value ')' { $$ = $2; }
;
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 8c083542f0..e8629291e5 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1082,46 +1082,6 @@ ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
/* }}} */
-ZEND_API int boolean_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
-{
- zval op1_copy, op2_copy;
- long op1_lval;
-
- if (Z_TYPE_P(op1) != IS_BOOL || Z_TYPE_P(op2) != IS_BOOL) {
- ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BOOL_AND);
-
- zendi_convert_to_boolean(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_boolean(op2, op2_copy, result);
- } else {
- op1_lval = Z_LVAL_P(op1);
- }
-
- ZVAL_BOOL(result, op1_lval & Z_LVAL_P(op2));
- return SUCCESS;
-}
-/* }}} */
-
-ZEND_API int boolean_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
-{
- zval op1_copy, op2_copy;
- long op1_lval;
-
- if (Z_TYPE_P(op1) != IS_BOOL || Z_TYPE_P(op2) != IS_BOOL) {
- ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BOOL_OR);
-
- zendi_convert_to_boolean(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_boolean(op2, op2_copy, result);
- } else {
- op1_lval = Z_LVAL_P(op1);
- }
-
- ZVAL_BOOL(result, op1_lval | Z_LVAL_P(op2));
- return SUCCESS;
-}
-/* }}} */
-
ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
{
zval op1_copy;
@@ -2363,28 +2323,6 @@ ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
}
/* }}} */
-#define PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(var) \
- *result = *var; \
- if (Z_REFCOUNT_P(var) == 1) { \
- Z_TYPE_P(var) = IS_NULL; \
- }
-
-ZEND_API int ternary_function(zval *result, zval *condition, zval *then, zval *if_not TSRMLS_DC) /* {{{ */
-{
- if (i_zend_is_true(condition)) {
- if (then) {
- PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(then);
- } else {
- PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(condition);
- }
- } else {
- PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(if_not);
- }
-
- return SUCCESS;
-}
-/* }}} */
-
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index 3f0fc2ef6a..ce21af3d2e 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -50,8 +50,6 @@ ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
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);
ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
-ZEND_API int boolean_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
-ZEND_API int boolean_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC);
ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC);
ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
@@ -378,8 +376,6 @@ ZEND_API int zend_atoi(const char *str, int str_len);
ZEND_API long zend_atol(const char *str, int str_len);
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
-
-ZEND_API int ternary_function(zval *result, zval *condition, zval *then, zval *if_not TSRMLS_DC);
END_EXTERN_C()
#define convert_to_ex_master(ppzv, lower_type, upper_type) \
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index 095c16ca91..3fa1b063a1 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -49,7 +49,7 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
}
break;
case IS_CONSTANT_AST:
- ZEND_AST_DEL_REF(Z_AST_P(zvalue));
+ zend_ast_destroy(Z_AST_P(zvalue));
break;
case IS_OBJECT:
{
@@ -85,11 +85,9 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
CHECK_ZVAL_STRING_REL(zvalue);
str_free(zvalue->value.str.val);
break;
- case IS_CONSTANT_AST:
- ZEND_AST_DEL_REF(Z_AST_P(zvalue));
- break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST:
case IS_OBJECT:
case IS_RESOURCE:
zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
@@ -147,7 +145,7 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
}
break;
case IS_CONSTANT_AST:
- ZEND_AST_ADD_REF(Z_AST_P(zvalue));
+ Z_AST_P(zvalue) = zend_ast_copy(Z_AST_P(zvalue));
break;
case IS_OBJECT:
{
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 006f2ec729..79719c8d7b 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -5200,7 +5200,6 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
}
-
c.flags = CONST_CS; /* non persistent, case sensetive */
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
c.name_len = Z_STRLEN_P(name)+1;
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 4f850c2978..5a2c2cf993 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4102,7 +4102,6 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
}
-
c.flags = CONST_CS; /* non persistent, case sensetive */
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
c.name_len = Z_STRLEN_P(name)+1;
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c
index 894da63aaa..8ced274cb2 100644
--- a/ext/opcache/zend_accelerator_util_funcs.c
+++ b/ext/opcache/zend_accelerator_util_funcs.c
@@ -222,6 +222,52 @@ static void zend_destroy_property_info(zend_property_info *property_info)
}
}
+#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
+static zend_ast *zend_ast_clone(zend_ast *ast TSRMLS_DC)
+{
+ int i;
+ zend_ast *node;
+
+ if (ast->kind == ZEND_CONST) {
+ node = emalloc(sizeof(zend_ast) + sizeof(zval));
+ node->kind = ZEND_CONST;
+ node->children = 0;
+ node->u.val = (zval*)(node + 1);
+ *node->u.val = *ast->u.val;
+ if ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
+ switch ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK)) {
+ case IS_STRING:
+ case IS_CONSTANT:
+ Z_STRVAL_P(node->u.val) = (char *) interned_estrndup(Z_STRVAL_P(ast->u.val), Z_STRLEN_P(ast->u.val));
+ break;
+ case IS_ARRAY:
+ case IS_CONSTANT_ARRAY:
+ if (ast->u.val->value.ht && ast->u.val->value.ht != &EG(symbol_table)) {
+ ALLOC_HASHTABLE(node->u.val->value.ht);
+ zend_hash_clone_zval(node->u.val->value.ht, ast->u.val->value.ht, 0);
+ }
+ break;
+ case IS_CONSTANT_AST:
+ Z_AST_P(node->u.val) = zend_ast_clone(Z_AST_P(ast->u.val) TSRMLS_CC);
+ break;
+ }
+ }
+ } else {
+ node = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
+ node->kind = ast->kind;
+ node->children = ast->children;
+ for (i = 0; i < ast->children; i++) {
+ if (ast->u.child[i]) {
+ node->u.child[i] = zend_ast_clone(ast->u.child[i] TSRMLS_CC);
+ } else {
+ node->u.child[i] = NULL;
+ }
+ }
+ }
+ return node;
+}
+#endif
+
static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC)
{
zval *ret, **ret_ptr = NULL;
@@ -259,6 +305,11 @@ static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC)
zend_hash_clone_zval(ret->value.ht, src->value.ht, 0);
}
break;
+#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
+ case IS_CONSTANT_AST:
+ Z_AST_P(ret) = zend_ast_clone(Z_AST_P(ret) TSRMLS_CC);
+ break;
+#endif
}
}
return ret;
@@ -376,6 +427,11 @@ static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
zend_hash_clone_zval(ppz->value.ht, ((zval*)p->pDataPtr)->value.ht, 0);
}
break;
+#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
+ case IS_CONSTANT_AST:
+ Z_AST_P(ppz) = zend_ast_clone(Z_AST_P(ppz) TSRMLS_CC);
+ break;
+#endif
}
}
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c
index 9f1940e061..bf13865666 100644
--- a/ext/opcache/zend_persist.c
+++ b/ext/opcache/zend_persist.c
@@ -51,6 +51,7 @@
typedef void (*zend_persist_func_t)(void * TSRMLS_DC);
static void zend_persist_zval_ptr(zval **zp TSRMLS_DC);
+static void zend_persist_zval(zval *z TSRMLS_DC);
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
static const Bucket *uninitialized_bucket = NULL;
@@ -138,6 +139,29 @@ static void zend_hash_persist(HashTable *ht, void (*pPersistElement)(void *pElem
#endif
}
+#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
+static zend_ast *zend_persist_ast(zend_ast *ast TSRMLS_DC)
+{
+ int i;
+ zend_ast *node;
+
+ if (ast->kind == ZEND_CONST) {
+ node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zval));
+ node->u.val = (zval*)(node + 1);
+ zend_persist_zval(node->u.val TSRMLS_CC);
+ } else {
+ node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
+ for (i = 0; i < ast->children; i++) {
+ if (node->u.child[i]) {
+ node->u.child[i] = zend_persist_ast(node->u.child[i] TSRMLS_CC);
+ }
+ }
+ }
+ efree(ast);
+ return node;
+}
+#endif
+
static void zend_persist_zval(zval *z TSRMLS_DC)
{
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
@@ -154,6 +178,11 @@ static void zend_persist_zval(zval *z TSRMLS_DC)
zend_accel_store(z->value.ht, sizeof(HashTable));
zend_hash_persist(z->value.ht, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
break;
+#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
+ case IS_CONSTANT_AST:
+ Z_AST_P(z) = zend_persist_ast(Z_AST_P(z) TSRMLS_CC);
+ break;
+#endif
}
}
diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c
index 18af756f6e..91438132d0 100644
--- a/ext/opcache/zend_persist_calc.c
+++ b/ext/opcache/zend_persist_calc.c
@@ -45,6 +45,7 @@
#endif
static uint zend_persist_zval_ptr_calc(zval **zp TSRMLS_DC);
+static uint zend_persist_zval_calc(zval *z TSRMLS_DC);
static uint zend_hash_persist_calc(HashTable *ht, int (*pPersistElement)(void *pElement TSRMLS_DC), size_t el_size TSRMLS_DC)
{
@@ -91,6 +92,27 @@ static uint zend_hash_persist_calc(HashTable *ht, int (*pPersistElement)(void *p
RETURN_SIZE();
}
+#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
+static uint zend_persist_ast_calc(zend_ast *ast TSRMLS_DC)
+{
+ int i;
+ START_SIZE();
+
+ if (ast->kind == ZEND_CONST) {
+ ADD_SIZE(sizeof(zend_ast) + sizeof(zval));
+ ADD_SIZE(zend_persist_zval_calc(ast->u.val TSRMLS_CC));
+ } else {
+ ADD_SIZE(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
+ for (i = 0; i < ast->children; i++) {
+ if (ast->u.child[i]) {
+ ADD_SIZE(zend_persist_ast_calc(ast->u.child[i] TSRMLS_CC));
+ }
+ }
+ }
+ RETURN_SIZE();
+}
+#endif
+
static uint zend_persist_zval_calc(zval *z TSRMLS_DC)
{
START_SIZE();
@@ -109,6 +131,11 @@ static uint zend_persist_zval_calc(zval *z TSRMLS_DC)
ADD_DUP_SIZE(z->value.ht, sizeof(HashTable));
ADD_SIZE(zend_hash_persist_calc(z->value.ht, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC));
break;
+#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
+ case IS_CONSTANT_AST:
+ ADD_SIZE(zend_persist_ast_calc(Z_AST_P(z) TSRMLS_CC));
+ break;
+#endif
}
RETURN_SIZE();
}