Skip to content
4 changes: 0 additions & 4 deletions Zend/zend.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,6 @@ void (*zend_on_timeout)(int seconds);
static void (*zend_message_dispatcher_p)(zend_long message, const void *data);
static zval *(*zend_get_configuration_directive_p)(zend_string *name);

#if ZEND_RC_DEBUG
ZEND_API bool zend_rc_debug = 0;
#endif

static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */
{
if (!new_value) {
Expand Down
1 change: 1 addition & 0 deletions Zend/zend.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "zend_smart_str_public.h"
#include "zend_smart_string_public.h"
#include "zend_signal.h"
#include "zend_type_code.h"

#define zend_sprintf sprintf

Expand Down
1 change: 1 addition & 0 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "zend_ini.h"
#include "zend_enum.h"
#include "zend_observer.h"
#include "zend_rc_debug.h"

#include <stdarg.h>

Expand Down
3 changes: 2 additions & 1 deletion Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@
#ifndef ZEND_API_H
#define ZEND_API_H

#include "zend_char.h"
#include "zend_modules.h"
#include "zend_list.h"
#include "zend_operators.h"
#include "zend_variables.h"
#include "zend_execute.h"
#include "zend_type_info.h"

#include "zend_type_code.h"

BEGIN_EXTERN_C()

Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
#ifndef ZEND_ALLOC_H
#define ZEND_ALLOC_H

#include "zend_portability.h"
#include "zend_result.h"

#include <stdio.h>

#include "../TSRM/TSRM.h"
#include "zend.h"

#ifndef ZEND_MM_ALIGNMENT
# error "ZEND_MM_ALIGNMENT was not defined during configure"
Expand Down
22 changes: 22 additions & 0 deletions Zend/zend_char.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/

#ifndef ZEND_CHAR_H
#define ZEND_CHAR_H

typedef unsigned char zend_uchar;

#endif /* ZEND_CHAR_H */
1 change: 1 addition & 0 deletions Zend/zend_execute.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "zend_compile.h"
#include "zend_hash.h"
#include "zend_operators.h"
#include "zend_type_code.h"
#include "zend_variables.h"

#include <stdint.h>
Expand Down
1 change: 1 addition & 0 deletions Zend/zend_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "zend.h"
#include "zend_sort.h"
#include "zend_type_code.h"

#define HASH_KEY_IS_STRING 1
#define HASH_KEY_IS_LONG 2
Expand Down
42 changes: 42 additions & 0 deletions Zend/zend_rc_debug.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/

#include "zend_rc_debug.h"

#if ZEND_RC_DEBUG

#include "zend_types.h"

ZEND_API bool zend_rc_debug = false;

ZEND_API void ZEND_RC_MOD_CHECK(const zend_refcounted_h *p)
{
if (!zend_rc_debug) {
return;
}

uint8_t type = zval_gc_type(p->u.type_info);

/* Skip checks for OBJECT/NULL type to avoid interpreting the flag incorrectly. */
if (type != IS_OBJECT && type != IS_NULL) {
ZEND_ASSERT(!(zval_gc_flags(p->u.type_info) & GC_IMMUTABLE));

/* The GC_PERSISTENT flag is reused for IS_OBJ_WEAKLY_REFERENCED on objects. */
ZEND_ASSERT((zval_gc_flags(p->u.type_info) & (GC_PERSISTENT|GC_PERSISTENT_LOCAL)) != GC_PERSISTENT);
}
}

#endif
52 changes: 52 additions & 0 deletions Zend/zend_rc_debug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/

#ifndef ZEND_RC_DEBUG_H
#define ZEND_RC_DEBUG_H

#ifndef ZEND_RC_DEBUG
# define ZEND_RC_DEBUG 0
#endif

#if ZEND_RC_DEBUG

#ifdef PHP_WIN32
# include "zend_config.w32.h"
#else
# include "zend_config.h"
#endif

#include <stdbool.h>
#include <stdint.h>

#include "zend_portability.h"

typedef struct _zend_refcounted_h zend_refcounted_h;

extern ZEND_API bool zend_rc_debug;

BEGIN_EXTERN_C()

ZEND_API void ZEND_RC_MOD_CHECK(const zend_refcounted_h *p);

END_EXTERN_C()

#else
# define ZEND_RC_MOD_CHECK(p) \
do { } while (0)
#endif

#endif /* ZEND_RC_DEBUG_H */
137 changes: 137 additions & 0 deletions Zend/zend_refcounted.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/

#ifndef ZEND_REFCOUNTED_H
#define ZEND_REFCOUNTED_H

#include "zend_portability.h"
#include "zend_rc_debug.h"
#include "zend_type_code.h"

#include <stdint.h>

#define GC_TYPE_MASK 0x0000000f
#define GC_FLAGS_MASK 0x000003f0
#define GC_INFO_MASK 0xfffffc00
#define GC_FLAGS_SHIFT 0
#define GC_INFO_SHIFT 10

/* zval_gc_flags(zval.value->gc.u.type_info) (common flags) */
#define GC_NOT_COLLECTABLE (1<<4)
#define GC_PROTECTED (1<<5) /* used for recursion detection */
#define GC_IMMUTABLE (1<<6) /* can't be changed in place */
#define GC_PERSISTENT (1<<7) /* allocated using malloc */
#define GC_PERSISTENT_LOCAL (1<<8) /* persistent, but thread-local */

#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 GC_REFCOUNT(p) zend_gc_refcount(&(p)->gc)
#define GC_SET_REFCOUNT(p, rc) zend_gc_set_refcount(&(p)->gc, rc)
#define GC_ADDREF(p) zend_gc_addref(&(p)->gc)
#define GC_DELREF(p) zend_gc_delref(&(p)->gc)
#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_TRY_ADDREF(p) zend_gc_try_addref(&(p)->gc)
#define GC_TRY_DELREF(p) zend_gc_try_delref(&(p)->gc)

#define GC_NULL (IS_NULL | (GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT))
#define GC_STRING (IS_STRING | (GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT))
#define GC_ARRAY IS_ARRAY
#define GC_OBJECT IS_OBJECT
#define GC_RESOURCE (IS_RESOURCE | (GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT))
#define GC_REFERENCE (IS_REFERENCE | (GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT))
#define GC_CONSTANT_AST (IS_CONSTANT_AST | (GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT))

typedef struct _zend_refcounted_h {
uint32_t refcount; /* reference counter 32-bit */
union {
uint32_t type_info;
} u;
} zend_refcounted_h;

typedef struct _zend_refcounted {
zend_refcounted_h gc;
} zend_refcounted;

static zend_always_inline uint8_t zval_gc_type(uint32_t gc_type_info) {
return (gc_type_info & GC_TYPE_MASK);
}

static zend_always_inline uint32_t 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);
}

static zend_always_inline uint32_t zend_gc_refcount(const zend_refcounted_h *p) {
return p->refcount;
}

static zend_always_inline uint32_t zend_gc_set_refcount(zend_refcounted_h *p, uint32_t rc) {
p->refcount = rc;
return p->refcount;
}

static zend_always_inline uint32_t zend_gc_addref(zend_refcounted_h *p) {
ZEND_RC_MOD_CHECK(p);
return ++(p->refcount);
}

static zend_always_inline void zend_gc_try_addref(zend_refcounted_h *p) {
if (!(p->u.type_info & GC_IMMUTABLE)) {
ZEND_RC_MOD_CHECK(p);
++p->refcount;
}
}

static zend_always_inline void zend_gc_try_delref(zend_refcounted_h *p) {
if (!(p->u.type_info & GC_IMMUTABLE)) {
ZEND_RC_MOD_CHECK(p);
--p->refcount;
}
}

static zend_always_inline uint32_t zend_gc_delref(zend_refcounted_h *p) {
ZEND_ASSERT(p->refcount > 0);
ZEND_RC_MOD_CHECK(p);
return --(p->refcount);
}

static zend_always_inline uint32_t zend_gc_addref_ex(zend_refcounted_h *p, uint32_t rc) {
ZEND_RC_MOD_CHECK(p);
p->refcount += rc;
return p->refcount;
}

static zend_always_inline uint32_t zend_gc_delref_ex(zend_refcounted_h *p, uint32_t rc) {
ZEND_RC_MOD_CHECK(p);
p->refcount -= rc;
return p->refcount;
}

#endif /* ZEND_REFCOUNTED_H */
2 changes: 2 additions & 0 deletions Zend/zend_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
+----------------------------------------------------------------------+
*/

#include "zend_string.h"
#include "zend.h"
#include "zend_globals.h"
#include "zend_rc_debug.h"

#ifdef HAVE_VALGRIND
# include "valgrind/callgrind.h"
Expand Down
21 changes: 20 additions & 1 deletion Zend/zend_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,26 @@
#ifndef ZEND_STRING_H
#define ZEND_STRING_H

#include "zend.h"
#include "zend_alloc.h"
#include "zend_char.h"
#include "zend_portability.h"
#include "zend_refcounted.h"

/* string flags (zval.value->gc.u.flags) */
#define IS_STR_CLASS_NAME_MAP_PTR GC_PROTECTED /* refcount is a map_ptr offset of class_entry */
#define IS_STR_INTERNED GC_IMMUTABLE /* interned string */
#define IS_STR_PERSISTENT GC_PERSISTENT /* allocated using malloc */
#define IS_STR_PERMANENT (1<<8) /* relives request boundary */
#define IS_STR_VALID_UTF8 (1<<9) /* valid UTF-8 according to PCRE */

typedef struct _zend_string zend_string;

struct _zend_string {
zend_refcounted_h gc;
zend_ulong h; /* hash value */
size_t len;
char val[1];
};

BEGIN_EXTERN_C()

Expand Down
Loading