Optimized constant lookup

This commit is contained in:
Dmitry Stogov 2014-04-25 00:56:15 +04:00
parent 0ca57dd1d3
commit df7ca608ce
9 changed files with 138 additions and 96 deletions

View file

@ -223,7 +223,7 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
break; break;
case ZEND_CONST: case ZEND_CONST:
ZVAL_DUP(result, &ast->u.val); ZVAL_DUP(result, &ast->u.val);
if (Z_CONSTANT_P(result)) { if (Z_OPT_CONSTANT_P(result)) {
zval_update_constant_ex(result, (void *) 1, scope TSRMLS_CC); zval_update_constant_ex(result, (void *) 1, scope TSRMLS_CC);
} }
break; break;

View file

@ -729,16 +729,13 @@ repeat:
Check whether a constant exists */ Check whether a constant exists */
ZEND_FUNCTION(defined) ZEND_FUNCTION(defined)
{ {
char *name; zend_string *name;
int name_len;
zval c;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &name) == FAILURE) {
return; return;
} }
if (zend_get_constant_ex(name, name_len, &c, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC)) { if (zend_get_constant_ex(name, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC)) {
zval_dtor(&c);
RETURN_TRUE; RETURN_TRUE;
} else { } else {
RETURN_FALSE; RETURN_FALSE;
@ -927,7 +924,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 /* this is necessary to make it able to work with default array
* properties, returned to user */ * properties, returned to user */
if (Z_CONSTANT(prop_copy)) { if (Z_OPT_CONSTANT(prop_copy)) {
zval_update_constant(&prop_copy, 0 TSRMLS_CC); zval_update_constant(&prop_copy, 0 TSRMLS_CC);
} }

View file

@ -278,12 +278,14 @@ static zend_constant *zend_get_special_constant(const char *name, uint name_len
} }
ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC) ZEND_API zval *zend_get_constant_str(const char *name, uint name_len TSRMLS_DC)
{ {
zend_constant *c; zend_constant *c;
ALLOCA_FLAG(use_heap)
if ((c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len)) == NULL) { if ((c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len)) == NULL) {
char *lcname = zend_str_tolower_dup(name, name_len); char *lcname = do_alloca(name_len + 1, use_heap);
zend_str_tolower_copy(lcname, name, name_len);
if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name_len)) != NULL) { if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name_len)) != NULL) {
if (c->flags & CONST_CS) { if (c->flags & CONST_CS) {
c = NULL; c = NULL;
@ -291,29 +293,47 @@ ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSR
} else { } else {
c = zend_get_special_constant(name, name_len TSRMLS_CC); c = zend_get_special_constant(name, name_len TSRMLS_CC);
} }
efree(lcname); free_alloca(lcname, use_heap);
} }
if (c) { return c ? &c->value : NULL;
ZVAL_DUP(result, &c->value);
return 1;
}
return 0;
} }
ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC) ZEND_API zval *zend_get_constant(zend_string *name TSRMLS_DC)
{
zend_constant *c;
ALLOCA_FLAG(use_heap)
if ((c = zend_hash_find_ptr(EG(zend_constants), name)) == NULL) {
char *lcname = do_alloca(name->len + 1, use_heap);
zend_str_tolower_copy(lcname, name->val, name->len);
if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name->len)) != NULL) {
if (c->flags & CONST_CS) {
c = NULL;
}
} else {
c = zend_get_special_constant(name->val, name->len TSRMLS_CC);
}
free_alloca(lcname, use_heap);
}
return c ? &c->value : NULL;
}
ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, ulong flags TSRMLS_DC)
{ {
zend_constant *c; zend_constant *c;
int retval = 1;
const char *colon; const char *colon;
zend_class_entry *ce = NULL; zend_class_entry *ce = NULL;
zend_string *class_name; zend_string *class_name;
const char *name = cname->val;
uint name_len = cname->len;
/* Skip leading \\ */ /* Skip leading \\ */
if (name[0] == '\\') { if (name[0] == '\\') {
name += 1; name += 1;
name_len -= 1; name_len -= 1;
cname = NULL;
} }
if ((colon = zend_memrchr(name, ':', name_len)) && if ((colon = zend_memrchr(name, ':', name_len)) &&
@ -321,12 +341,13 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
int class_name_len = colon - name - 1; int class_name_len = colon - name - 1;
int const_name_len = name_len - class_name_len - 2; int const_name_len = name_len - class_name_len - 2;
zend_string *constant_name = STR_INIT(colon + 1, const_name_len, 0); zend_string *constant_name = STR_INIT(colon + 1, const_name_len, 0);
zend_string *lcname; char *lcname;
zval *ret_constant = NULL; zval *ret_constant = NULL;
ALLOCA_FLAG(use_heap)
class_name = STR_INIT(name, class_name_len, 0); class_name = STR_INIT(name, class_name_len, 0);
lcname = STR_ALLOC(class_name_len, 0); lcname = do_alloca(class_name_len + 1, use_heap);
zend_str_tolower_copy(lcname->val, name, class_name_len); zend_str_tolower_copy(lcname, name, class_name_len);
if (!scope) { if (!scope) {
if (EG(in_execution)) { if (EG(in_execution)) {
scope = EG(scope); scope = EG(scope);
@ -336,16 +357,14 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
} }
if (class_name_len == sizeof("self")-1 && if (class_name_len == sizeof("self")-1 &&
!memcmp(lcname->val, "self", sizeof("self")-1)) { !memcmp(lcname, "self", sizeof("self")-1)) {
if (scope) { if (scope) {
ce = scope; ce = scope;
} else { } else {
zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
retval = 0;
} }
STR_FREE(lcname);
} else if (class_name_len == sizeof("parent")-1 && } else if (class_name_len == sizeof("parent")-1 &&
!memcmp(lcname->val, "parent", sizeof("parent")-1)) { !memcmp(lcname, "parent", sizeof("parent")-1)) {
if (!scope) { if (!scope) {
zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
} else if (!scope->parent) { } else if (!scope->parent) {
@ -353,38 +372,33 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
} else { } else {
ce = scope->parent; ce = scope->parent;
} }
STR_FREE(lcname);
} else if (class_name_len == sizeof("static")-1 && } else if (class_name_len == sizeof("static")-1 &&
!memcmp(lcname->val, "static", sizeof("static")-1)) { !memcmp(lcname, "static", sizeof("static")-1)) {
if (EG(called_scope)) { if (EG(called_scope)) {
ce = EG(called_scope); ce = EG(called_scope);
} else { } else {
zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
} }
STR_FREE(lcname);
} else { } else {
STR_FREE(lcname);
ce = zend_fetch_class(class_name, flags TSRMLS_CC); ce = zend_fetch_class(class_name, flags TSRMLS_CC);
} }
if (retval && ce) { free_alloca(lcname, use_heap);
if ((ret_constant = zend_hash_find(&ce->constants_table, constant_name)) == NULL) { if (ce) {
retval = 0; ret_constant = zend_hash_find(&ce->constants_table, constant_name);
if (ret_constant == NULL) {
if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) { if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name->val, constant_name->val); zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name->val, constant_name->val);
} }
} else if (Z_ISREF_P(ret_constant)) { } else if (Z_ISREF_P(ret_constant)) {
ret_constant = Z_REFVAL_P(ret_constant); ret_constant = Z_REFVAL_P(ret_constant);
} }
} else if (!ce) {
retval = 0;
} }
STR_FREE(class_name); STR_FREE(class_name);
STR_FREE(constant_name); STR_FREE(constant_name);
if (retval) { if (ret_constant && Z_CONSTANT_P(ret_constant)) {
zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC); zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
ZVAL_DUP(result, ret_constant);
} }
return retval; return ret_constant;
} }
/* non-class constant */ /* non-class constant */
@ -393,45 +407,43 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
int prefix_len = colon - name; int prefix_len = colon - name;
int const_name_len = name_len - prefix_len - 1; int const_name_len = name_len - prefix_len - 1;
const char *constant_name = colon + 1; const char *constant_name = colon + 1;
zend_string *lcname; char *lcname;
int found_const = 0; int lcname_len;
ALLOCA_FLAG(use_heap)
lcname = STR_ALLOC(prefix_len + 1 + const_name_len, 0); lcname_len = prefix_len + 1 + const_name_len;
zend_str_tolower_copy(lcname->val, name, prefix_len); lcname = do_alloca(lcname_len + 1, use_heap);
zend_str_tolower_copy(lcname, name, prefix_len);
/* Check for namespace constant */ /* Check for namespace constant */
lcname->val[prefix_len] = '\\'; lcname[prefix_len] = '\\';
memcpy(lcname->val + prefix_len + 1, constant_name, const_name_len + 1); memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
if ((c = zend_hash_find_ptr(EG(zend_constants), lcname)) != NULL) { if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) == NULL) {
found_const = 1;
} else {
/* try lowercase */ /* try lowercase */
zend_str_tolower(lcname->val + prefix_len + 1, const_name_len); zend_str_tolower(lcname + prefix_len + 1, const_name_len);
STR_FORGET_HASH_VAL(lcname); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) {
if ((c = zend_hash_find_ptr(EG(zend_constants), lcname)) != NULL) { if ((c->flags & CONST_CS) != 0) {
if ((c->flags & CONST_CS) == 0) { c = NULL;
found_const = 1;
} }
} }
} }
STR_FREE(lcname); free_alloca(lcname, use_heap);
if (found_const) { if (c) {
ZVAL_COPY_VALUE(result, &c->value); return &c->value;
zval_update_constant_ex(result, (void*)1, NULL TSRMLS_CC);
zval_copy_ctor(result);
return 1;
} }
/* name requires runtime resolution, need to check non-namespaced name */ /* name requires runtime resolution, need to check non-namespaced name */
if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) { if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) {
name = constant_name; return zend_get_constant_str(constant_name, const_name_len TSRMLS_CC);
name_len = const_name_len;
return zend_get_constant(name, name_len, result TSRMLS_CC);
} }
return 0; return NULL;
} }
return zend_get_constant(name, name_len, result TSRMLS_CC); if (cname) {
return zend_get_constant(cname TSRMLS_CC);
} else {
return zend_get_constant_str(name, name_len TSRMLS_CC);
}
} }
zend_constant *zend_quick_get_constant(const zval *key, ulong flags TSRMLS_DC) zend_constant *zend_quick_get_constant(const zval *key, ulong flags TSRMLS_DC)

View file

@ -65,8 +65,9 @@ int zend_startup_constants(TSRMLS_D);
int zend_shutdown_constants(TSRMLS_D); int zend_shutdown_constants(TSRMLS_D);
void zend_register_standard_constants(TSRMLS_D); void zend_register_standard_constants(TSRMLS_D);
void clean_non_persistent_constants(TSRMLS_D); void clean_non_persistent_constants(TSRMLS_D);
ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC); ZEND_API zval *zend_get_constant(zend_string *name TSRMLS_DC);
ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC); ZEND_API zval *zend_get_constant_str(const char *name, uint name_len TSRMLS_DC);
ZEND_API zval *zend_get_constant_ex(zend_string *name, zend_class_entry *scope, ulong flags TSRMLS_DC);
ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_bool bval, int flags, int module_number TSRMLS_DC); ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_bool bval, int flags, int module_number TSRMLS_DC);
ZEND_API void zend_register_null_constant(const char *name, uint name_len, int flags, int module_number TSRMLS_DC); ZEND_API void zend_register_null_constant(const char *name, uint name_len, int flags, int module_number TSRMLS_DC);
ZEND_API void zend_register_long_constant(const char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC); ZEND_API void zend_register_long_constant(const char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC);

View file

@ -509,7 +509,7 @@ ZEND_API int zend_is_true(zval *op TSRMLS_DC) /* {{{ */
ZEND_API int zval_update_constant_ex(zval *p, void *arg, zend_class_entry *scope TSRMLS_DC) /* {{{ */ ZEND_API int zval_update_constant_ex(zval *p, void *arg, zend_class_entry *scope TSRMLS_DC) /* {{{ */
{ {
zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg; zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg;
zval const_value; zval *const_value, tmp;
char *colon; char *colon;
if (IS_CONSTANT_VISITED(p)) { if (IS_CONSTANT_VISITED(p)) {
@ -520,7 +520,8 @@ ZEND_API int zval_update_constant_ex(zval *p, void *arg, zend_class_entry *scope
SEPARATE_ZVAL_IF_NOT_REF(p); SEPARATE_ZVAL_IF_NOT_REF(p);
MARK_CONSTANT_VISITED(p); MARK_CONSTANT_VISITED(p);
refcount = Z_REFCOUNTED_P(p) ? Z_REFCOUNT_P(p) : 1; refcount = Z_REFCOUNTED_P(p) ? Z_REFCOUNT_P(p) : 1;
if (!zend_get_constant_ex(Z_STRVAL_P(p), Z_STRLEN_P(p), &const_value, scope, Z_CONST_FLAGS_P(p) TSRMLS_CC)) { const_value = zend_get_constant_ex(Z_STR_P(p), scope, Z_CONST_FLAGS_P(p) TSRMLS_CC);
if (!const_value) {
char *actual = Z_STRVAL_P(p); char *actual = Z_STRVAL_P(p);
if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) { if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
@ -584,7 +585,12 @@ ZEND_API int zval_update_constant_ex(zval *p, void *arg, zend_class_entry *scope
if (inline_change) { if (inline_change) {
STR_RELEASE(Z_STR_P(p)); STR_RELEASE(Z_STR_P(p));
} }
ZVAL_COPY_VALUE(p, &const_value); //???!
ZVAL_COPY_VALUE(p, const_value);
if (Z_OPT_CONSTANT_P(p)) {
zval_update_constant_ex(p, (void*)1, NULL TSRMLS_CC);
}
zval_opt_copy_ctor(p);
} }
if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount); if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount);
@ -619,10 +625,11 @@ ZEND_API int zval_update_constant_ex(zval *p, void *arg, zend_class_entry *scope
if (GC_FLAGS(str_index) & IS_STR_AST) { if (GC_FLAGS(str_index) & IS_STR_AST) {
zend_ast_ref *ast = *(zend_ast_ref **)str_index->val; zend_ast_ref *ast = *(zend_ast_ref **)str_index->val;
zend_ast_evaluate(&const_value, ast->ast, scope TSRMLS_CC); zend_ast_evaluate(&tmp, ast->ast, scope TSRMLS_CC);
zend_ast_destroy(ast->ast); zend_ast_destroy(ast->ast);
efree(ast); efree(ast);
} else if (!zend_get_constant_ex(str_index->val, str_index->len, &const_value, scope, GC_FLAGS(str_index) & ~(IS_STR_PERSISTENT | IS_STR_INTERNED |IS_STR_PERMANENT) TSRMLS_CC)) { const_value = &tmp;
} else if (!(const_value = zend_get_constant_ex(str_index, scope, GC_FLAGS(str_index) & ~(IS_STR_PERSISTENT | IS_STR_INTERNED |IS_STR_PERMANENT) TSRMLS_CC))) {
char *actual, *str; char *actual, *str;
const char *save = str_index->val; const char *save = str_index->val;
int len; int len;
@ -654,10 +661,19 @@ ZEND_API int zval_update_constant_ex(zval *p, void *arg, zend_class_entry *scope
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str, str); zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str, str);
} }
if (str == str_index->val && len == str_index->len) { if (str == str_index->val && len == str_index->len) {
ZVAL_STR(&const_value, STR_COPY(str_index)); ZVAL_STR(&tmp, STR_COPY(str_index));
} else { } else {
ZVAL_STRINGL(&const_value, str, len); ZVAL_STRINGL(&tmp, str, len);
} }
const_value = &tmp;
} else {
//???!
ZVAL_COPY_VALUE(&tmp, const_value);
if (Z_OPT_CONSTANT(tmp)) {
zval_update_constant_ex(&tmp, (void*)1, NULL TSRMLS_CC);
}
zval_opt_copy_ctor(&tmp);
const_value = &tmp;
} }
if (Z_REFCOUNTED_P(element) && Z_REFCOUNT_P(element) > 1) { if (Z_REFCOUNTED_P(element) && Z_REFCOUNT_P(element) > 1) {
@ -666,16 +682,16 @@ ZEND_API int zval_update_constant_ex(zval *p, void *arg, zend_class_entry *scope
ZVAL_COPY_VALUE(element, &new_val); ZVAL_COPY_VALUE(element, &new_val);
} }
switch (Z_TYPE(const_value)) { switch (Z_TYPE_P(const_value)) {
case IS_STRING: case IS_STRING:
ret = zend_symtable_update_current_key_ex(Z_ARRVAL_P(p), Z_STR(const_value), HASH_UPDATE_KEY_IF_BEFORE); ret = zend_symtable_update_current_key_ex(Z_ARRVAL_P(p), Z_STR_P(const_value), HASH_UPDATE_KEY_IF_BEFORE);
break; break;
case IS_BOOL: case IS_BOOL:
case IS_LONG: case IS_LONG:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE); ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, Z_LVAL_P(const_value), HASH_UPDATE_KEY_IF_BEFORE);
break; break;
case IS_DOUBLE: case IS_DOUBLE:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE); ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, zend_dval_to_lval(Z_DVAL_P(const_value)), HASH_UPDATE_KEY_IF_BEFORE);
break; break;
case IS_NULL: case IS_NULL:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, STR_EMPTY_ALLOC(), 0, HASH_UPDATE_KEY_IF_BEFORE); ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, STR_EMPTY_ALLOC(), 0, HASH_UPDATE_KEY_IF_BEFORE);
@ -687,19 +703,19 @@ ZEND_API int zval_update_constant_ex(zval *p, void *arg, zend_class_entry *scope
if (ret == SUCCESS) { if (ret == SUCCESS) {
zend_hash_move_forward(Z_ARRVAL_P(p)); zend_hash_move_forward(Z_ARRVAL_P(p));
} }
zval_dtor(&const_value); zval_dtor(const_value);
} }
zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC); 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)); zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
} else if (Z_TYPE_P(p) == IS_CONSTANT_AST) { } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
SEPARATE_ZVAL_IF_NOT_REF(p); SEPARATE_ZVAL_IF_NOT_REF(p);
zend_ast_evaluate(&const_value, Z_ASTVAL_P(p), scope TSRMLS_CC); zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope TSRMLS_CC);
if (inline_change) { if (inline_change) {
zend_ast_destroy(Z_ASTVAL_P(p)); zend_ast_destroy(Z_ASTVAL_P(p));
efree(Z_AST_P(p)); efree(Z_AST_P(p));
} }
ZVAL_COPY_VALUE(p, &const_value); ZVAL_COPY_VALUE(p, &tmp);
} }
return 0; return 0;
} }

View file

@ -112,15 +112,24 @@ static void zend_ini_add_string(zval *result, zval *op1, zval *op2)
*/ */
static void zend_ini_get_constant(zval *result, zval *name TSRMLS_DC) static void zend_ini_get_constant(zval *result, zval *name TSRMLS_DC)
{ {
zval z_constant; zval *c, tmp;
/* If name contains ':' it is not a constant. Bug #26893. */ /* If name contains ':' it is not a constant. Bug #26893. */
if (!memchr(Z_STRVAL_P(name), ':', Z_STRLEN_P(name)) if (!memchr(Z_STRVAL_P(name), ':', Z_STRLEN_P(name))
&& zend_get_constant(Z_STRVAL_P(name), Z_STRLEN_P(name), &z_constant TSRMLS_CC)) { && (c = zend_get_constant(Z_STR_P(name) TSRMLS_CC)) != 0) {
/* z_constant is emalloc()'d */ if (Z_TYPE_P(c) != IS_STRING) {
convert_to_string(&z_constant); ZVAL_COPY_VALUE(&tmp, c);
ZVAL_PSTRINGL(result, Z_STRVAL(z_constant), Z_STRLEN(z_constant)); if (Z_OPT_CONSTANT(tmp)) {
zval_dtor(&z_constant); zval_update_constant_ex(&tmp, (void*)1, NULL TSRMLS_CC);
}
zval_opt_copy_ctor(&tmp);
convert_to_string(&tmp);
c = &tmp;
}
ZVAL_PSTRINGL(result, Z_STRVAL_P(c), Z_STRLEN_P(c));
if (c == &tmp) {
zval_dtor(&tmp);
}
STR_FREE(Z_STR_P(name)); STR_FREE(Z_STR_P(name));
} else { } else {
*result = *name; *result = *name;

View file

@ -218,16 +218,16 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
/* substitute __COMPILER_HALT_OFFSET__ constant */ /* substitute __COMPILER_HALT_OFFSET__ constant */
zend_bool orig_in_execution = EG(in_execution); zend_bool orig_in_execution = EG(in_execution);
zend_op_array *orig_op_array = EG(active_op_array); zend_op_array *orig_op_array = EG(active_op_array);
zval offset; zval *offset;
EG(in_execution) = 1; EG(in_execution) = 1;
EG(active_op_array) = op_array; EG(active_op_array) = op_array;
if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &offset TSRMLS_CC)) { if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1 TSRMLS_CC)) != NULL) {
zend_uint tv = ZEND_RESULT(opline).var; zend_uint tv = ZEND_RESULT(opline).var;
literal_dtor(&ZEND_OP2_LITERAL(opline)); literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline); MAKE_NOP(opline);
replace_tmp_by_const(op_array, opline, tv, &offset TSRMLS_CC); replace_tmp_by_const(op_array, opline, tv, offset TSRMLS_CC);
} }
EG(active_op_array) = orig_op_array; EG(active_op_array) = orig_op_array;
EG(in_execution) = orig_in_execution; EG(in_execution) = orig_in_execution;

View file

@ -198,15 +198,15 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
if (main_persistent_script) { if (main_persistent_script) {
zend_bool orig_in_execution = EG(in_execution); zend_bool orig_in_execution = EG(in_execution);
zend_op_array *orig_op_array = EG(active_op_array); zend_op_array *orig_op_array = EG(active_op_array);
zval offset; zval *offset;
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
main_persistent_script->early_binding = -1; main_persistent_script->early_binding = -1;
#endif #endif
EG(in_execution) = 1; EG(in_execution) = 1;
EG(active_op_array) = op_array; EG(active_op_array) = op_array;
if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &offset TSRMLS_CC)) { if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1 TSRMLS_CC)) != NULL) {
main_persistent_script->compiler_halt_offset = Z_LVAL(offset); main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset);
} }
EG(active_op_array) = orig_op_array; EG(active_op_array) = orig_op_array;
EG(in_execution) = orig_in_execution; EG(in_execution) = orig_in_execution;

View file

@ -3854,15 +3854,22 @@ PHP_MINFO_FUNCTION(basic) /* {{{ */
Given the name of a constant this function will return the constant's associated value */ Given the name of a constant this function will return the constant's associated value */
PHP_FUNCTION(constant) PHP_FUNCTION(constant)
{ {
char *const_name; zend_string *const_name;
int const_name_len; zval *c;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &const_name, &const_name_len) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &const_name) == FAILURE) {
return; return;
} }
if (!zend_get_constant_ex(const_name, const_name_len, return_value, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC)) { c = zend_get_constant_ex(const_name, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't find constant %s", const_name); if (c) {
ZVAL_COPY_VALUE(return_value, c);
if (Z_CONSTANT_P(return_value)) {
zval_update_constant_ex(return_value, (void*)1, NULL TSRMLS_CC);
}
zval_copy_ctor(return_value);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't find constant %s", const_name->val);
RETURN_NULL(); RETURN_NULL();
} }
} }