Use macros to update specific parts of GC_TYPE_INFO() (direct assignments to GC_TYPE(), GC_FLAGS() and GC_INFO() are prohibited)

This commit is contained in:
Dmitry Stogov 2018-02-28 00:52:12 +03:00
parent 42022bc943
commit 6f483dc94c
11 changed files with 90 additions and 69 deletions

View File

@ -91,14 +91,6 @@
((v) & ~GC_COLOR) ((v) & ~GC_COLOR)
#define GC_INFO_GET_COLOR(v) \ #define GC_INFO_GET_COLOR(v) \
(((zend_uintptr_t)(v)) & GC_COLOR) (((zend_uintptr_t)(v)) & GC_COLOR)
#define GC_INFO_SET_ADDRESS(v, a) \
do {(v) = ((v) & GC_COLOR) | (a);} while (0)
#define GC_INFO_SET_COLOR(v, c) \
do {(v) = ((v) & ~GC_COLOR) | (c);} while (0)
#define GC_INFO_SET_BLACK(v) \
do {(v) = (v) & ~GC_COLOR;} while (0)
#define GC_INFO_SET_PURPLE(v) \
do {(v) = (v) | GC_COLOR;} while (0)
/* one (0) is reserved */ /* one (0) is reserved */
#define GC_ROOT_BUFFER_MAX_ENTRIES 10001 #define GC_ROOT_BUFFER_MAX_ENTRIES 10001
@ -192,16 +184,26 @@ static zend_gc_globals gc_globals;
# define GC_TRACE(str) # define GC_TRACE(str)
#endif #endif
#define GC_REF_SET_ADDRESS(ref, a) \ #define GC_REF_SET_INFO(ref, info) do { \
GC_INFO_SET_ADDRESS(GC_INFO(ref), a) GC_TYPE_INFO(ref) = ((info) << GC_INFO_SHIFT) | \
(GC_TYPE_INFO(ref) & (GC_TYPE_MASK | GC_FLAGS_MASK)); \
} while (0)
#define GC_REF_SET_ADDRESS(ref, a) do {\
GC_TYPE_INFO(ref) = ((info) << GC_INFO_SHIFT) | \
(GC_TYPE_INFO(ref) & (GC_TYPE_MASK | GC_FLAGS_MASK | (GC_COLOR << GC_INFO_SHIFT))); \
} while (0)
#define GC_REF_GET_COLOR(ref) \ #define GC_REF_GET_COLOR(ref) \
GC_INFO_GET_COLOR(GC_INFO(ref)) GC_INFO_GET_COLOR(GC_INFO(ref))
#define GC_REF_SET_COLOR(ref, c) \ #define GC_REF_SET_COLOR(ref, c) do { \
do { GC_TRACE_SET_COLOR(ref, c); GC_INFO_SET_COLOR(GC_INFO(ref), c); } while (0) GC_TYPE_INFO(ref) = ((c) << GC_INFO_SHIFT) | \
#define GC_REF_SET_BLACK(ref) \ (GC_TYPE_INFO(ref) & (GC_TYPE_MASK | GC_FLAGS_MASK | ~(GC_COLOR << GC_INFO_SHIFT))); \
do { GC_TRACE_SET_COLOR(ref, GC_BLACK); GC_INFO_SET_BLACK(GC_INFO(ref)); } while (0) } while (0)
#define GC_REF_SET_PURPLE(ref) \ #define GC_REF_SET_BLACK(ref) do { \
do { GC_TRACE_SET_COLOR(ref, GC_PURPLE); GC_INFO_SET_PURPLE(GC_INFO(ref)); } while (0) GC_TYPE_INFO(ref) &= ~(GC_COLOR << GC_INFO_SHIFT); \
} while (0)
#define GC_REF_SET_PURPLE(ref) do { \
GC_TYPE_INFO(ref) |= (GC_COLOR << GC_INFO_SHIFT); \
} while (0)
#if ZEND_GC_DEBUG > 1 #if ZEND_GC_DEBUG > 1
static const char *gc_color_name(uint32_t color) { static const char *gc_color_name(uint32_t color) {
@ -402,7 +404,7 @@ ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref)
} }
GC_TRACE_SET_COLOR(ref, GC_PURPLE); GC_TRACE_SET_COLOR(ref, GC_PURPLE);
GC_INFO(ref) = (newRoot - GC_G(buf)) | GC_PURPLE; GC_REF_SET_INFO(ref, (newRoot - GC_G(buf)) | GC_PURPLE);
newRoot->ref = ref; newRoot->ref = ref;
newRoot->next = GC_G(roots).next; newRoot->next = GC_G(roots).next;
@ -453,7 +455,7 @@ ZEND_API void ZEND_FASTCALL gc_remove_from_buffer(zend_refcounted *ref)
if (GC_REF_GET_COLOR(ref) != GC_BLACK) { if (GC_REF_GET_COLOR(ref) != GC_BLACK) {
GC_TRACE_SET_COLOR(ref, GC_PURPLE); GC_TRACE_SET_COLOR(ref, GC_PURPLE);
} }
GC_INFO(ref) = 0; GC_REF_SET_INFO(ref, 0);
/* updete next root that is going to be freed */ /* updete next root that is going to be freed */
if (GC_G(next_to_free) == root) { if (GC_G(next_to_free) == root) {
@ -797,7 +799,7 @@ static void gc_add_garbage(zend_refcounted *ref)
GC_G(unused) = buf->prev; GC_G(unused) = buf->prev;
#if 1 #if 1
/* optimization: color is already GC_BLACK (0) */ /* optimization: color is already GC_BLACK (0) */
GC_INFO(ref) = buf - GC_G(buf); GC_REF_SET_INFO(ref, buf - GC_G(buf));
#else #else
GC_REF_SET_ADDRESS(ref, buf - GC_G(buf)); GC_REF_SET_ADDRESS(ref, buf - GC_G(buf));
#endif #endif
@ -806,7 +808,7 @@ static void gc_add_garbage(zend_refcounted *ref)
GC_G(first_unused)++; GC_G(first_unused)++;
#if 1 #if 1
/* optimization: color is already GC_BLACK (0) */ /* optimization: color is already GC_BLACK (0) */
GC_INFO(ref) = buf - GC_G(buf); GC_REF_SET_INFO(ref, buf - GC_G(buf));
#else #else
GC_REF_SET_ADDRESS(ref, buf - GC_G(buf)); GC_REF_SET_ADDRESS(ref, buf - GC_G(buf));
#endif #endif
@ -824,7 +826,7 @@ static void gc_add_garbage(zend_refcounted *ref)
buf = GC_G(additional_buffer)->buf + GC_G(additional_buffer)->used; buf = GC_G(additional_buffer)->buf + GC_G(additional_buffer)->used;
#if 1 #if 1
/* optimization: color is already GC_BLACK (0) */ /* optimization: color is already GC_BLACK (0) */
GC_INFO(ref) = GC_ROOT_BUFFER_MAX_ENTRIES + GC_G(additional_buffer)->used; GC_REF_SET_INFO(ref, GC_ROOT_BUFFER_MAX_ENTRIES + GC_G(additional_buffer)->used);
#else #else
GC_REF_SET_ADDRESS(ref, GC_ROOT_BUFFER_MAX_ENTRIES) + GC_G(additional_buffer)->used; GC_REF_SET_ADDRESS(ref, GC_ROOT_BUFFER_MAX_ENTRIES) + GC_G(additional_buffer)->used;
#endif #endif
@ -990,7 +992,7 @@ static int gc_collect_roots(uint32_t *flags)
} else { } else {
gc_remove_from_additional_roots(current); gc_remove_from_additional_roots(current);
} }
GC_INFO(current->ref) = 0; /* reset GC_ADDRESS() and keep GC_BLACK */ GC_REF_SET_INFO(current->ref, 0); /* reset GC_ADDRESS() and keep GC_BLACK */
} }
current = next; current = next;
} }
@ -1042,7 +1044,7 @@ tail_call:
} else { } else {
gc_remove_from_additional_roots(root); gc_remove_from_additional_roots(root);
} }
GC_INFO(ref) = 0; GC_REF_SET_INFO(ref, 0);
root = NULL; root = NULL;
} else { } else {
GC_REMOVE_FROM_BUFFER(ref); GC_REMOVE_FROM_BUFFER(ref);
@ -1210,7 +1212,7 @@ ZEND_API int zend_gc_collect_cycles(void)
if (!(OBJ_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) { if (!(OBJ_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) {
GC_TRACE_REF(obj, "calling destructor"); GC_TRACE_REF(obj, "calling destructor");
OBJ_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(obj, IS_OBJ_DESTRUCTOR_CALLED);
if (obj->handlers->dtor_obj if (obj->handlers->dtor_obj
&& (obj->handlers->dtor_obj != zend_objects_destroy_object && (obj->handlers->dtor_obj != zend_objects_destroy_object
|| obj->ce->destructor)) { || obj->ce->destructor)) {
@ -1246,9 +1248,10 @@ ZEND_API int zend_gc_collect_cycles(void)
zend_object *obj = (zend_object*)p; zend_object *obj = (zend_object*)p;
EG(objects_store).object_buckets[obj->handle] = SET_OBJ_INVALID(obj); EG(objects_store).object_buckets[obj->handle] = SET_OBJ_INVALID(obj);
GC_TYPE(obj) = IS_NULL; GC_TYPE_INFO(obj) = IS_NULL |
(GC_TYPE_INFO(obj) & ~GC_TYPE_MASK);
if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
OBJ_FLAGS(obj) |= IS_OBJ_FREE_CALLED; GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED);
if (obj->handlers->free_obj) { if (obj->handlers->free_obj) {
GC_ADDREF(obj); GC_ADDREF(obj);
obj->handlers->free_obj(obj); obj->handlers->free_obj(obj);
@ -1261,7 +1264,8 @@ ZEND_API int zend_gc_collect_cycles(void)
} else if (GC_TYPE(p) == IS_ARRAY) { } else if (GC_TYPE(p) == IS_ARRAY) {
zend_array *arr = (zend_array*)p; zend_array *arr = (zend_array*)p;
GC_TYPE(arr) = IS_NULL; GC_TYPE_INFO(arr) = IS_NULL |
(GC_TYPE_INFO(arr) & ~GC_TYPE_MASK);
/* GC may destroy arrays with rc>1. This is valid and safe. */ /* GC may destroy arrays with rc>1. This is valid and safe. */
HT_ALLOW_COW_VIOLATION(arr); HT_ALLOW_COW_VIOLATION(arr);

View File

@ -51,7 +51,7 @@ END_EXTERN_C()
static zend_always_inline void gc_check_possible_root(zend_refcounted *ref) static zend_always_inline void gc_check_possible_root(zend_refcounted *ref)
{ {
if (GC_TYPE(ref) == IS_REFERENCE) { if (GC_TYPE_INFO(ref) == IS_REFERENCE) {
zval *zv = &((zend_reference*)ref)->val; zval *zv = &((zend_reference*)ref)->val;
if (!Z_REFCOUNTED_P(zv)) { if (!Z_REFCOUNTED_P(zv)) {

View File

@ -49,7 +49,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_call_destructors(zend_objects_sto
zend_object *obj = objects->object_buckets[i]; zend_object *obj = objects->object_buckets[i];
if (IS_OBJ_VALID(obj)) { if (IS_OBJ_VALID(obj)) {
if (!(OBJ_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) { if (!(OBJ_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) {
OBJ_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(obj, IS_OBJ_DESTRUCTOR_CALLED);
if (obj->handlers->dtor_obj if (obj->handlers->dtor_obj
&& (obj->handlers->dtor_obj != zend_objects_destroy_object && (obj->handlers->dtor_obj != zend_objects_destroy_object
@ -74,7 +74,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_mark_destructed(zend_objects_stor
zend_object *obj = *obj_ptr; zend_object *obj = *obj_ptr;
if (IS_OBJ_VALID(obj)) { if (IS_OBJ_VALID(obj)) {
OBJ_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(obj, IS_OBJ_DESTRUCTOR_CALLED);
} }
obj_ptr++; obj_ptr++;
} while (obj_ptr != end); } while (obj_ptr != end);
@ -99,7 +99,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_
obj = *obj_ptr; obj = *obj_ptr;
if (IS_OBJ_VALID(obj)) { if (IS_OBJ_VALID(obj)) {
if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
OBJ_FLAGS(obj) |= IS_OBJ_FREE_CALLED; GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED);
if (obj->handlers->free_obj && obj->handlers->free_obj != zend_object_std_dtor) { if (obj->handlers->free_obj && obj->handlers->free_obj != zend_object_std_dtor) {
GC_ADDREF(obj); GC_ADDREF(obj);
obj->handlers->free_obj(obj); obj->handlers->free_obj(obj);
@ -114,7 +114,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_
obj = *obj_ptr; obj = *obj_ptr;
if (IS_OBJ_VALID(obj)) { if (IS_OBJ_VALID(obj)) {
if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
OBJ_FLAGS(obj) |= IS_OBJ_FREE_CALLED; GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED);
if (obj->handlers->free_obj) { if (obj->handlers->free_obj) {
GC_ADDREF(obj); GC_ADDREF(obj);
obj->handlers->free_obj(obj); obj->handlers->free_obj(obj);
@ -165,7 +165,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ *
ZEND_ASSERT(GC_REFCOUNT(object) == 0); ZEND_ASSERT(GC_REFCOUNT(object) == 0);
if (!(OBJ_FLAGS(object) & IS_OBJ_DESTRUCTOR_CALLED)) { if (!(OBJ_FLAGS(object) & IS_OBJ_DESTRUCTOR_CALLED)) {
OBJ_FLAGS(object) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(object, IS_OBJ_DESTRUCTOR_CALLED);
if (object->handlers->dtor_obj if (object->handlers->dtor_obj
&& (object->handlers->dtor_obj != zend_objects_destroy_object && (object->handlers->dtor_obj != zend_objects_destroy_object
@ -182,7 +182,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ *
EG(objects_store).object_buckets[handle] = SET_OBJ_INVALID(object); EG(objects_store).object_buckets[handle] = SET_OBJ_INVALID(object);
if (!(OBJ_FLAGS(object) & IS_OBJ_FREE_CALLED)) { if (!(OBJ_FLAGS(object) & IS_OBJ_FREE_CALLED)) {
OBJ_FLAGS(object) |= IS_OBJ_FREE_CALLED; GC_ADD_FLAGS(object, IS_OBJ_FREE_CALLED);
if (object->handlers->free_obj) { if (object->handlers->free_obj) {
GC_ADDREF(object); GC_ADDREF(object);
object->handlers->free_obj(object); object->handlers->free_obj(object);

View File

@ -62,7 +62,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object);
/* Called when the ctor was terminated by an exception */ /* Called when the ctor was terminated by an exception */
static zend_always_inline void zend_object_store_ctor_failed(zend_object *obj) static zend_always_inline void zend_object_store_ctor_failed(zend_object *obj)
{ {
OBJ_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(obj, IS_OBJ_DESTRUCTOR_CALLED);
} }
#define ZEND_OBJECTS_STORE_HANDLERS 0, zend_object_std_dtor, zend_objects_destroy_object, zend_objects_clone_obj #define ZEND_OBJECTS_STORE_HANDLERS 0, zend_object_std_dtor, zend_objects_destroy_object, zend_objects_clone_obj

View File

@ -166,7 +166,7 @@ static zend_always_inline zend_string *zend_add_interned_string(zend_string *str
zval val; zval val;
GC_SET_REFCOUNT(str, 1); GC_SET_REFCOUNT(str, 1);
GC_FLAGS(str) |= IS_STR_INTERNED | flags; GC_ADD_FLAGS(str, IS_STR_INTERNED | flags);
ZVAL_INTERNED_STR(&val, str); ZVAL_INTERNED_STR(&val, str);

View File

@ -446,10 +446,35 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define GC_ADDREF_EX(p, rc) zend_gc_addref_ex(&(p)->gc, rc) #define GC_ADDREF_EX(p, rc) zend_gc_addref_ex(&(p)->gc, rc)
#define GC_DELREF_EX(p, rc) zend_gc_delref_ex(&(p)->gc, rc) #define GC_DELREF_EX(p, rc) zend_gc_delref_ex(&(p)->gc, rc)
#define GC_TYPE(p) (p)->gc.u.v.type #define GC_TYPE_MASK 0x000000ff
#define GC_FLAGS(p) (p)->gc.u.v.flags #define GC_FLAGS_MASK 0x0000ff00
#define GC_INFO(p) (p)->gc.u.v.gc_info #define GC_INFO_MASK 0xffff0000
#define GC_FLAGS_SHIFT 8
#define GC_INFO_SHIFT 16
static zend_always_inline zend_uchar zval_gc_type(uint32_t gc_type_info) {
return (gc_type_info & GC_TYPE_MASK);
}
static zend_always_inline zend_uchar zval_gc_flags(uint32_t gc_type_info) {
return (gc_type_info >> GC_FLAGS_SHIFT) & (GC_FLAGS_MASK >> GC_FLAGS_SHIFT);
}
static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
return (gc_type_info >> GC_INFO_SHIFT);
}
#define GC_TYPE_INFO(p) (p)->gc.u.type_info #define GC_TYPE_INFO(p) (p)->gc.u.type_info
#define GC_TYPE(p) zval_gc_type(GC_TYPE_INFO(p))
#define GC_FLAGS(p) zval_gc_flags(GC_TYPE_INFO(p))
#define GC_INFO(p) zval_gc_info(GC_TYPE_INFO(p))
#define GC_ADD_FLAGS(p, flags) do { \
GC_TYPE_INFO(p) |= (flags) << GC_FLAGS_SHIFT; \
} while (0)
#define GC_DEL_FLAGS(p, flags) do { \
GC_TYPE_INFO(p) &= ~((flags) << GC_FLAGS_SHIFT); \
} while (0)
#define Z_GC_TYPE(zval) GC_TYPE(Z_COUNTED(zval)) #define Z_GC_TYPE(zval) GC_TYPE(Z_COUNTED(zval))
#define Z_GC_TYPE_P(zval_p) Z_GC_TYPE(*(zval_p)) #define Z_GC_TYPE_P(zval_p) Z_GC_TYPE(*(zval_p))
@ -462,10 +487,6 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define Z_GC_TYPE_INFO(zval) GC_TYPE_INFO(Z_COUNTED(zval)) #define Z_GC_TYPE_INFO(zval) GC_TYPE_INFO(Z_COUNTED(zval))
#define Z_GC_TYPE_INFO_P(zval_p) Z_GC_TYPE_INFO(*(zval_p)) #define Z_GC_TYPE_INFO_P(zval_p) Z_GC_TYPE_INFO(*(zval_p))
#define GC_FLAGS_SHIFT 8
#define GC_INFO_SHIFT 16
#define GC_INFO_MASK 0xffff0000
/* zval.value->gc.u.v.flags (common flags) */ /* zval.value->gc.u.v.flags (common flags) */
#define GC_COLLECTABLE (1<<0) #define GC_COLLECTABLE (1<<0)
#define GC_PROTECTED (1<<1) /* used for recursion detection */ #define GC_PROTECTED (1<<1) /* used for recursion detection */
@ -517,11 +538,11 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
(GC_FLAGS(p) & GC_PROTECTED) (GC_FLAGS(p) & GC_PROTECTED)
#define GC_PROTECT_RECURSION(p) do { \ #define GC_PROTECT_RECURSION(p) do { \
GC_FLAGS(p) |= GC_PROTECTED; \ GC_ADD_FLAGS(p, GC_PROTECTED); \
} while (0) } while (0)
#define GC_UNPROTECT_RECURSION(p) do { \ #define GC_UNPROTECT_RECURSION(p) do { \
GC_FLAGS(p) &= ~GC_PROTECTED; \ GC_DEL_FLAGS(p, GC_PROTECTED); \
} while (0) } while (0)
#define Z_IS_RECURSIVE(zval) GC_IS_RECURSIVE(Z_COUNTED(zval)) #define Z_IS_RECURSIVE(zval) GC_IS_RECURSIVE(Z_COUNTED(zval))
@ -914,7 +935,7 @@ extern ZEND_API zend_bool zend_rc_debug;
} \ } \
} while (0) } while (0)
# define GC_MAKE_PERSISTENT_LOCAL(p) do { \ # define GC_MAKE_PERSISTENT_LOCAL(p) do { \
GC_FLAGS(p) |= GC_PERSISTENT_LOCAL; \ GC_ADD_FLAGS(p, GC_PERSISTENT_LOCAL); \
} while (0) } while (0)
#else #else
# define ZEND_RC_MOD_CHECK(p) \ # define ZEND_RC_MOD_CHECK(p) \

View File

@ -480,13 +480,7 @@ zend_string *accel_new_interned_string(zend_string *str)
STRTAB_COLLISION(s) = *hash_slot; STRTAB_COLLISION(s) = *hash_slot;
*hash_slot = STRTAB_STR_TO_POS(&ZCSG(interned_strings), s); *hash_slot = STRTAB_STR_TO_POS(&ZCSG(interned_strings), s);
GC_SET_REFCOUNT(s, 1); GC_SET_REFCOUNT(s, 1);
#if 1
/* optimized single assignment */
GC_TYPE_INFO(s) = IS_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << GC_FLAGS_SHIFT); GC_TYPE_INFO(s) = IS_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << GC_FLAGS_SHIFT);
#else
GC_TYPE(s) = IS_STRING;
GC_FLAGS(s) = IS_STR_INTERNED | IS_STR_PERMANENT;
#endif
ZSTR_H(s) = h; ZSTR_H(s) = h;
ZSTR_LEN(s) = ZSTR_LEN(str); ZSTR_LEN(s) = ZSTR_LEN(str);
memcpy(ZSTR_VAL(s), ZSTR_VAL(str), ZSTR_LEN(s) + 1); memcpy(ZSTR_VAL(s), ZSTR_VAL(str), ZSTR_LEN(s) + 1);

View File

@ -118,8 +118,8 @@ static int zend_file_cache_flock(int fd, int type)
ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \ ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
/* script->corrupted shows if the script in SHM or not */ \ /* script->corrupted shows if the script in SHM or not */ \
if (EXPECTED(script->corrupted)) { \ if (EXPECTED(script->corrupted)) { \
GC_FLAGS(ptr) |= IS_STR_INTERNED; \ GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \
GC_FLAGS(ptr) &= ~IS_STR_PERMANENT; \ GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \
} \ } \
(ptr) = (void*)((char*)(ptr) - (char*)script->mem); \ (ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
} \ } \
@ -134,10 +134,10 @@ static int zend_file_cache_flock(int fd, int type)
(ptr) = (void*)((char*)buf + (size_t)(ptr)); \ (ptr) = (void*)((char*)buf + (size_t)(ptr)); \
/* script->corrupted shows if the script in SHM or not */ \ /* script->corrupted shows if the script in SHM or not */ \
if (EXPECTED(!script->corrupted)) { \ if (EXPECTED(!script->corrupted)) { \
GC_FLAGS(ptr) |= IS_STR_INTERNED | IS_STR_PERMANENT; \ GC_ADD_FLAGS(ptr, IS_STR_INTERNED | IS_STR_PERMANENT); \
} else { \ } else { \
GC_FLAGS(ptr) |= IS_STR_INTERNED; \ GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \
GC_FLAGS(ptr) &= ~IS_STR_PERMANENT; \ GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \
} \ } \
} \ } \
} \ } \
@ -241,8 +241,8 @@ static void *zend_file_cache_unserialize_interned(zend_string *str, int in_shm)
} }
} else { } else {
ret = str; ret = str;
GC_FLAGS(ret) |= IS_STR_INTERNED; GC_ADD_FLAGS(ret, IS_STR_INTERNED);
GC_FLAGS(ret) &= ~IS_STR_PERMANENT; GC_DEL_FLAGS(ret, IS_STR_PERMANENT);
} }
return ret; return ret;
} }

View File

@ -36,13 +36,15 @@
#ifdef HAVE_OPCACHE_FILE_CACHE #ifdef HAVE_OPCACHE_FILE_CACHE
#define zend_set_str_gc_flags(str) do { \ #define zend_set_str_gc_flags(str) do { \
if (ZCG(accel_directives).file_cache_only) { \ if (ZCG(accel_directives).file_cache_only) { \
GC_FLAGS(str) = IS_STR_INTERNED; \ GC_TYPE_INFO(str) = IS_STRING | (IS_STR_INTERNED << GC_FLAGS_SHIFT); \
} else { \ } else { \
GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT; \ GC_TYPE_INFO(str) = IS_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << GC_FLAGS_SHIFT); \
} \ } \
} while (0) } while (0)
#else #else
#define zend_set_str_gc_flags(str) GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT #define zend_set_str_gc_flags(str) do {\
GC_TYPE_INFO(str) = IS_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << GC_FLAGS_SHIFT); \
} while (0)
#endif #endif
#define zend_accel_store_string(str) do { \ #define zend_accel_store_string(str) do { \
@ -301,7 +303,7 @@ static void zend_persist_zval(zval *z)
/* make immutable array */ /* make immutable array */
Z_TYPE_FLAGS_P(z) = 0; Z_TYPE_FLAGS_P(z) = 0;
GC_SET_REFCOUNT(Z_COUNTED_P(z), 2); GC_SET_REFCOUNT(Z_COUNTED_P(z), 2);
GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE; GC_ADD_FLAGS(Z_COUNTED_P(z), IS_ARRAY_IMMUTABLE);
HT_FLAGS(Z_ARRVAL_P(z)) |= HASH_FLAG_STATIC_KEYS; HT_FLAGS(Z_ARRVAL_P(z)) |= HASH_FLAG_STATIC_KEYS;
} }
} }

View File

@ -223,13 +223,13 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
BG(serialize_lock)++; BG(serialize_lock)++;
if (call_user_function_ex(CG(function_table), zv, &wakeup_name, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) { if (call_user_function_ex(CG(function_table), zv, &wakeup_name, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) {
wakeup_failed = 1; wakeup_failed = 1;
OBJ_FLAGS(Z_OBJ_P(zv)) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(Z_OBJ_P(zv), IS_OBJ_DESTRUCTOR_CALLED);
} }
BG(serialize_lock)--; BG(serialize_lock)--;
zval_ptr_dtor(&retval); zval_ptr_dtor(&retval);
} else { } else {
OBJ_FLAGS(Z_OBJ_P(zv)) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(Z_OBJ_P(zv), IS_OBJ_DESTRUCTOR_CALLED);
} }
} }
@ -603,7 +603,7 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) { if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
if (has_wakeup) { if (has_wakeup) {
ZVAL_DEREF(rval); ZVAL_DEREF(rval);
OBJ_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(Z_OBJ_P(rval), IS_OBJ_DESTRUCTOR_CALLED);
} }
return 0; return 0;
} }

View File

@ -221,13 +221,13 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
BG(serialize_lock)++; BG(serialize_lock)++;
if (call_user_function_ex(CG(function_table), zv, &wakeup_name, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) { if (call_user_function_ex(CG(function_table), zv, &wakeup_name, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) {
wakeup_failed = 1; wakeup_failed = 1;
OBJ_FLAGS(Z_OBJ_P(zv)) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(Z_OBJ_P(zv), IS_OBJ_DESTRUCTOR_CALLED);
} }
BG(serialize_lock)--; BG(serialize_lock)--;
zval_ptr_dtor(&retval); zval_ptr_dtor(&retval);
} else { } else {
OBJ_FLAGS(Z_OBJ_P(zv)) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(Z_OBJ_P(zv), IS_OBJ_DESTRUCTOR_CALLED);
} }
} }
@ -607,7 +607,7 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) { if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
if (has_wakeup) { if (has_wakeup) {
ZVAL_DEREF(rval); ZVAL_DEREF(rval);
OBJ_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED; GC_ADD_FLAGS(Z_OBJ_P(rval), IS_OBJ_DESTRUCTOR_CALLED);
} }
return 0; return 0;
} }