-/*
- +----------------------------------------------------------------------+
- | APC |
- +----------------------------------------------------------------------+
- | Copyright (c) 2008 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt. |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
- | Rasmus Lerdorf <rasmus@php.net> |
- | Arun C. Murthy <arunc@yahoo-inc.com> |
- | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
- +----------------------------------------------------------------------+
-
- This software was contributed to PHP by Community Connect Inc. in 2002
- and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
- Future revisions and derivatives of this source code must acknowledge
- Community Connect Inc. as the original contributor of this module by
- leaving this note intact in the source code.
-
- All other licensing and usage conditions are those of the PHP Group.
-
- */
-
-/* $Id: apc_compile.c,v 3.87.2.8 2008/05/11 18:57:00 rasmus Exp $ */
-
-#include "apc_compile.h"
-#include "apc_globals.h"
-#include "apc_zend.h"
-
-#ifndef Z_REFCOUNT_P
-#define Z_REFCOUNT_P(pz) (pz)->refcount
-#define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz))
-#endif
-
-#ifndef Z_SET_REFCOUNT_P
-#define Z_SET_REFCOUNT_P(pz, rc) (pz)->refcount = rc
-#define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc)
-#endif
-
-#ifndef Z_ADDREF_P
-#define Z_ADDREF_P(pz) (pz)->refcount++
-#define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz))
-#endif
-
-#ifndef Z_DELREF_P
-#define Z_DELREF_P(pz) (pz)->refcount--
-#define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz))
-#endif
-
-#ifndef Z_ISREF_P
-#define Z_ISREF_P(pz) (pz)->is_ref
-#define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz))
-#endif
-
-#ifndef Z_SET_ISREF_P
-#define Z_SET_ISREF_P(pz) (pz)->is_ref = 1
-#define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz))
-#endif
-
-#ifndef Z_UNSET_ISREF_P
-#define Z_UNSET_ISREF_P(pz) (pz)->is_ref = 0
-#define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz))
-#endif
-
-#ifndef Z_SET_ISREF_TO_P
-#define Z_SET_ISREF_TO_P(pz, isref) (pz)->is_ref = isref
-#define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref)
-#endif
-
-typedef void* (*ht_copy_fun_t)(void*, void*, apc_malloc_t, apc_free_t);
-typedef void (*ht_free_fun_t)(void*, apc_free_t);
-typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
-
-#ifdef ZEND_ENGINE_2
-typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
-#endif
-
-#define CHECK(p) { if ((p) == NULL) return NULL; }
-
-/* {{{ internal function declarations */
-
-static int is_derived_class(zend_op_array* op_array, const char* key, int key_size);
-
-static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_malloc_t);
-
-/*
- * The "copy" functions perform deep-copies on a particular data structure
- * (passed as the second argument). They also optionally allocate space for
- * the destination data structure if the first argument is null.
- */
-static zval** my_copy_zval_ptr(zval**, const zval**, apc_malloc_t, apc_free_t);
-static zval* my_copy_zval(zval*, const zval*, apc_malloc_t, apc_free_t);
-static znode* my_copy_znode(znode*, znode*, apc_malloc_t, apc_free_t);
-static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_malloc_t, apc_free_t);
-static zend_function* my_copy_function(zend_function*, zend_function*, apc_malloc_t, apc_free_t);
-static zend_function_entry* my_copy_function_entry(zend_function_entry*, const zend_function_entry*, apc_malloc_t, apc_free_t);
-static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_malloc_t, apc_free_t);
-static HashTable* my_copy_hashtable_ex(HashTable*, HashTable*, ht_copy_fun_t, ht_free_fun_t, int, apc_malloc_t, apc_free_t, ht_check_copy_fun_t, ...);
-#define my_copy_hashtable( dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate) \
- my_copy_hashtable_ex(dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate, NULL)
-static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate);
-#ifdef ZEND_ENGINE_2
-static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate);
-static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, const zend_arg_info*, uint, apc_malloc_t, apc_free_t);
-static zend_arg_info* my_copy_arg_info(zend_arg_info*, const zend_arg_info*, apc_malloc_t, apc_free_t);
-#endif
-/*
- * The "destroy" functions free the memory associated with a particular data
- * structure but do not free the pointer to the data structure.
- *
- * my_destroy_zval() returns SUCCESS or FAILURE, FAILURE means that
- * the zval* has other references elsewhere
- */
-static int my_destroy_zval(zval*, apc_free_t);
-static void my_destroy_zval_ptr(zval**, apc_free_t);
-static void my_destroy_zend_op(zend_op*, apc_free_t);
-static void my_destroy_znode(znode*, apc_free_t);
-static void my_destroy_function(zend_function*, apc_free_t);
-static void my_destroy_function_entry(zend_function_entry*, apc_free_t);
-static void my_destroy_class_entry(zend_class_entry*, apc_free_t);
-static void my_destroy_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
-static void my_destroy_op_array(zend_op_array*, apc_free_t);
-#ifdef ZEND_ENGINE_2
-static void my_destroy_property_info(zend_property_info*, apc_free_t);
-static void my_destroy_arg_info_array(zend_arg_info* src, uint, apc_free_t);
-static void my_destroy_arg_info(zend_arg_info*, apc_free_t);
-#endif
-
-/*
- * The "free" functions work exactly like their "destroy" counterparts (see
- * above) but also free the pointer to the data structure.
- */
-static void my_free_zval_ptr(zval**, apc_free_t);
-static void my_free_function(zend_function*, apc_free_t);
-static void my_free_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
-#ifdef ZEND_ENGINE_2
-static void my_free_property_info(zend_property_info* src, apc_free_t);
-static void my_free_arg_info_array(zend_arg_info*, uint, apc_free_t);
-static void my_free_arg_info(zend_arg_info*, apc_free_t);
-#endif
-
-/*
- * The "fixup" functions need for ZEND_ENGINE_2
- */
-#ifdef ZEND_ENGINE_2
-static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
-static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
-/* my_fixup_function_for_execution is the same as my_fixup_function
- * but named differently for clarity
- */
-#define my_fixup_function_for_execution my_fixup_function
-
-#ifdef ZEND_ENGINE_2_2
-static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
-#define my_fixup_property_info_for_execution my_fixup_property_info
-#endif
-
-#endif
-
-/*
- * These functions return "1" if the member/function is
- * defined/overridden in the 'current' class and not inherited.
- */
-static int my_check_copy_function(Bucket* src, va_list args);
-static int my_check_copy_default_property(Bucket* p, va_list args);
-#ifdef ZEND_ENGINE_2
-static int my_check_copy_property_info(Bucket* src, va_list args);
-static int my_check_copy_static_member(Bucket* src, va_list args);
-#endif
-
-/* }}} */
-
-/* {{{ check_op_array_integrity */
-#if 0
-static void check_op_array_integrity(zend_op_array* src)
-{
- int i, j;
-
- /* These sorts of checks really aren't particularly effective, but they
- * can provide a welcome sanity check when debugging. Just don't enable
- * for production use! */
-
- assert(src->refcount != NULL);
- assert(src->opcodes != NULL);
- assert(src->last > 0);
-
- for (i = 0; i < src->last; i++) {
- zend_op* op = &src->opcodes[i];
- znode* nodes[] = { &op->result, &op->op1, &op->op2 };
- for (j = 0; j < 3; j++) {
- assert(nodes[j]->op_type == IS_CONST ||
- nodes[j]->op_type == IS_VAR ||
- nodes[j]->op_type == IS_TMP_VAR ||
- nodes[j]->op_type == IS_UNUSED);
-
- if (nodes[j]->op_type == IS_CONST) {
- int type = nodes[j]->u.constant.type;
- assert(type == IS_RESOURCE ||
- type == IS_BOOL ||
- type == IS_LONG ||
- type == IS_DOUBLE ||
- type == IS_NULL ||
- type == IS_CONSTANT ||
- type == IS_STRING ||
- type == FLAG_IS_BC ||
- type == IS_ARRAY ||
- type == IS_CONSTANT_ARRAY ||
- type == IS_OBJECT);
- }
- }
- }
-}
-#endif
-/* }}} */
-
-/* {{{ is_derived_class */
-static int is_derived_class(zend_op_array* op_array, const char* key, int key_size)
-{
- int i;
-
- /*
- * Scan the op_array for execution-time class declarations of derived
- * classes. If we find one whose key matches our current class key, we
- * know the current class is a derived class.
- *
- * This check is exceedingly inefficient (fortunately it only has to occur
- * once, when the source file is first compiled and cached), but the
- * compiler should save this information for us -- definitely a candidate
- * for a Zend Engine patch.
- *
- * XXX checking for derived classes provides a minimal (albeit measurable)
- * speed up. It may not be worth the added complexity -- considere
- * removing this optimization.
- */
-
- for (i = 0; i < op_array->last; i++) {
- zend_op* op = &op_array->opcodes[i];
-
-#ifdef ZEND_ENGINE_2
- if (op->opcode == ZEND_DECLARE_CLASS &&
- op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
-#else
- if (op->opcode == ZEND_DECLARE_FUNCTION_OR_CLASS &&
- op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
-#endif
- {
- if (op->op1.u.constant.value.str.len == key_size &&
- !memcmp(op->op1.u.constant.value.str.val, key, key_size))
- {
- return 1;
- }
- }
- }
-
- return 0;
-}
-/* }}} */
-
-/* {{{ my_bitwise_copy_function */
-static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate)
-{
- assert(src != NULL);
-
- if (!dst) {
- CHECK(dst = (zend_function*) allocate(sizeof(src[0])));
- }
-
- /* We only need to do a bitwise copy */
- memcpy(dst, src, sizeof(src[0]));
-
- return dst;
-}
-/* }}} */
-
-/* {{{ my_copy_zval_ptr */
-static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- int local_dst_alloc = 0;
- zval* dst_new;
-
- assert(src != NULL);
-
- if (!dst) {
- CHECK(dst = (zval**) allocate(sizeof(zval*)));
- local_dst_alloc = 1;
- }
-
-#ifdef ZEND_ENGINE_2_3
- if(!(dst[0] = (zval*) allocate(sizeof(zval_gc_info)))) {
- if(local_dst_alloc) deallocate(dst);
- return NULL;
- }
-
- if(allocate == apc_php_malloc) {
- GC_ZVAL_INIT(dst[0]);
- }
-#else
- if(!(dst[0] = (zval*) allocate(sizeof(zval)))) {
- if(local_dst_alloc) deallocate(dst);
- return NULL;
- }
-#endif
- if(!(dst_new = my_copy_zval(*dst, *src, allocate, deallocate))) {
- if(local_dst_alloc) deallocate(dst);
- return NULL;
- }
- if(dst_new != *dst) {
- deallocate(*dst);
- *dst = dst_new;
- }
-
- Z_SET_REFCOUNT_PP(dst, Z_REFCOUNT_PP((zval**)src));
- Z_SET_ISREF_TO_PP(dst, Z_ISREF_PP((zval**)src));
-
- return dst;
-}
-/* }}} */
-
-/* {{{ my_copy_zval */
-static zval* my_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- zval **tmp;
- TSRMLS_FETCH();
-
- assert(dst != NULL);
- assert(src != NULL);
-
- memcpy(dst, src, sizeof(src[0]));
-
- switch (src->type & ~IS_CONSTANT_INDEX) {
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- case IS_DOUBLE:
- case IS_NULL:
- break;
-
- case IS_CONSTANT:
- case IS_STRING:
-#ifndef ZEND_ENGINE_2
- case FLAG_IS_BC:
-#endif
- if (src->value.str.val) {
- CHECK(dst->value.str.val = apc_xmemcpy(src->value.str.val,
- src->value.str.len+1,
- allocate));
- }
- break;
-
- case IS_ARRAY:
-
- if(APCG(copied_zvals)) {
- if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
- Z_ADDREF_PP(tmp);
- return *tmp;
- }
-
- zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
- }
- /* fall through */
-
- case IS_CONSTANT_ARRAY:
-
- CHECK(dst->value.ht =
- my_copy_hashtable(NULL,
- src->value.ht,
- (ht_copy_fun_t) my_copy_zval_ptr,
- (ht_free_fun_t) my_free_zval_ptr,
- 1,
- allocate, deallocate));
- break;
-
- case IS_OBJECT:
-#ifndef ZEND_ENGINE_2
- CHECK(dst->value.obj.ce =
- my_copy_class_entry(NULL, src->value.obj.ce, allocate, deallocate));
-
- if(!(dst->value.obj.properties = my_copy_hashtable(NULL,
- src->value.obj.properties,
- (ht_copy_fun_t) my_copy_zval_ptr,
- (ht_free_fun_t) my_free_zval_ptr,
- 1,
- allocate, deallocate))) {
- my_destroy_class_entry(dst->value.obj.ce, deallocate);
- return NULL;
- }
- break;
-#else
- dst->type = IS_NULL;
-#endif
- break;
-
- default:
- assert(0);
- }
-
- return dst;
-}
-/* }}} */
-
-/* {{{ my_copy_znode */
-static znode* my_copy_znode(znode* dst, znode* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- assert(dst != NULL);
- assert(src != NULL);
-
- memcpy(dst, src, sizeof(src[0]));
-
-#ifdef IS_CV
- assert(dst ->op_type == IS_CONST ||
- dst ->op_type == IS_VAR ||
- dst ->op_type == IS_CV ||
- dst ->op_type == IS_TMP_VAR ||
- dst ->op_type == IS_UNUSED);
-#else
- assert(dst ->op_type == IS_CONST ||
- dst ->op_type == IS_VAR ||
- dst ->op_type == IS_TMP_VAR ||
- dst ->op_type == IS_UNUSED);
-#endif
-
- if (src->op_type == IS_CONST) {
- if(!my_copy_zval(&dst->u.constant, &src->u.constant, allocate, deallocate)) {
- return NULL;
- }
- }
-
- return dst;
-}
-/* }}} */
-
-/* {{{ my_copy_zend_op */
-static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- assert(dst != NULL);
- assert(src != NULL);
-
- memcpy(dst, src, sizeof(src[0]));
-
- if( my_copy_znode(&dst->result, &src->result, allocate, deallocate) == NULL
- || my_copy_znode(&dst->op1, &src->op1, allocate, deallocate) == NULL
- || my_copy_znode(&dst->op2, &src->op2, allocate, deallocate) == NULL)
- {
- return NULL;
- }
-
- return dst;
-}
-/* }}} */
-
-/* {{{ my_copy_function */
-static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- int local_dst_alloc = 0;
- TSRMLS_FETCH();
-
- assert(src != NULL);
-
- if(!dst) local_dst_alloc = 1;
- CHECK(dst = my_bitwise_copy_function(dst, src, allocate));
-
- switch (src->type) {
- case ZEND_INTERNAL_FUNCTION:
- case ZEND_OVERLOADED_FUNCTION:
- /* shallow copy because op_array is internal */
- dst->op_array = src->op_array;
- break;
-
- case ZEND_USER_FUNCTION:
- case ZEND_EVAL_CODE:
- if(!apc_copy_op_array(&dst->op_array,
- &src->op_array,
- allocate, deallocate TSRMLS_CC)) {
- if(local_dst_alloc) deallocate(dst);
- return NULL;
- }
- break;
-
- default:
- assert(0);
- }
-#ifdef ZEND_ENGINE_2
- /*
- * op_array bitwise copying overwrites what ever you modified
- * before apc_copy_op_array - which is why this code is outside
- * my_bitwise_copy_function.
- */
-
- /* zend_do_inheritance will re-look this up, because the pointers
- * in prototype are from a function table of another class. It just
- * helps if that one is from EG(class_table).
- */
- dst->common.prototype = NULL;
-
- /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
- * have to carry around a prototype. Thankfully zend_do_inheritance
- * sets this properly as well
- */
- dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
-#endif
-
-
- return dst;
-}
-/* }}} */
-
-/* {{{ my_copy_function_entry */
-static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, const zend_function_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- int local_dst_alloc = 0;
- assert(src != NULL);
-
- if (!dst) {
- CHECK(dst = (zend_function_entry*) allocate(sizeof(src[0])));
- local_dst_alloc = 1;
- }
-
- /* Start with a bitwise copy */
- memcpy(dst, src, sizeof(src[0]));
-
- dst->fname = NULL;
-#ifdef ZEND_ENGINE_2
- dst->arg_info = NULL;
-#else
- dst->func_arg_types = NULL;
-#endif
-
- if (src->fname) {
- if(!(dst->fname = apc_xstrdup(src->fname, allocate))) {
- goto cleanup;
- }
- }
-
-#ifdef ZEND_ENGINE_2
- if (src->arg_info) {
- if(!(dst->arg_info = my_copy_arg_info_array(NULL,
- src->arg_info,
- src->num_args,
- allocate,
- deallocate))) {
- goto cleanup;
- }
- }
-#else
- if (src->func_arg_types) {
- if(!(dst->func_arg_types = apc_xmemcpy(src->func_arg_types,
- src->func_arg_types[0]+1,
- allocate))) {
- goto cleanup;
- }
- }
-#endif
-
- return dst;
-
-cleanup:
- if(dst->fname) deallocate((char*)dst->fname);
- if(local_dst_alloc) deallocate(dst);
- return NULL;
-}
-/* }}} */
-
-#ifdef ZEND_ENGINE_2
-/* {{{ my_copy_property_info */
-static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- int local_dst_alloc = 0;
-
- assert(src != NULL);
-
- if (!dst) {
- CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
- local_dst_alloc = 1;
- }
-
- /* Start with a bitwise copy */
- memcpy(dst, src, sizeof(*src));
-
- dst->name = NULL;
-#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
- dst->doc_comment = NULL;
-#endif
-
- if (src->name) {
- /* private members are stored inside property_info as a mangled
- * string of the form:
- * \0<classname>\0<membername>\0
- */
- if(!(dst->name =
- apc_xmemcpy(src->name, src->name_length+1, allocate))) {
- goto cleanup;
- }
- }
-
-#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
- if (src->doc_comment) {
- if( !(dst->doc_comment =
- apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
- goto cleanup;
- }
- }
-#endif
-
- return dst;
-
-cleanup:
- if(dst->name) deallocate(dst->name);
-#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
- if(dst->doc_comment) deallocate(dst->doc_comment);
-#endif
- if(local_dst_alloc) deallocate(dst);
- return NULL;
-}
-/* }}} */
-
-/* {{{ my_copy_property_info_for_execution */
-static zend_property_info* my_copy_property_info_for_execution(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- int local_dst_alloc = 0;
-
- assert(src != NULL);
-
- if (!dst) {
- CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
- local_dst_alloc = 1;
- }
-
- /* We need only a shallow copy */
- memcpy(dst, src, sizeof(*src));
-
- return dst;
-}
-/* }}} */
-
-/* {{{ my_copy_arg_info_array */
-static zend_arg_info* my_copy_arg_info_array(zend_arg_info* dst, const zend_arg_info* src, uint num_args, apc_malloc_t allocate, apc_free_t deallocate)
-{
- int local_dst_alloc = 0;
- int i = 0;
-
-
- if (!dst) {
- CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)*num_args));
- local_dst_alloc = 1;
- }
-
- /* Start with a bitwise copy */
- memcpy(dst, src, sizeof(*src)*num_args);
-
- for(i=0; i < num_args; i++) {
- if(!(my_copy_arg_info( &dst[i], &src[i], allocate, deallocate))) {
- if(i) my_destroy_arg_info_array(dst, i-1, deallocate);
- if(local_dst_alloc) deallocate(dst);
- return NULL;
- }
- }
-
- return dst;
-}
-/* }}} */
-
-/* {{{ my_copy_arg_info */
-static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, const zend_arg_info* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- int local_dst_alloc = 0;
-
- assert(src != NULL);
-
- if (!dst) {
- CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)));
- local_dst_alloc = 1;
- }
-
- /* Start with a bitwise copy */
- memcpy(dst, src, sizeof(*src));
-
- dst->name = NULL;
- dst->class_name = NULL;
-
- if (src->name) {
- if(!(dst->name =
- apc_xmemcpy(src->name, src->name_len+1, allocate))) {
- goto cleanup;
- }
- }
-
- if (src->class_name) {
- if(!(dst->class_name =
- apc_xmemcpy(src->class_name, src->class_name_len+1, allocate))) {
- goto cleanup;
- }
- }
-
- return dst;
-
-cleanup:
- if(dst->name) deallocate((char*)dst->name);
- if(dst->class_name) deallocate((char*)dst->class_name);
- if(local_dst_alloc) deallocate(dst);
- return NULL;
-}
-/* }}} */
-#endif
-
-/* {{{ my_copy_class_entry */
-static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- int local_dst_alloc = 0;
- int i = 0;
-
- assert(src != NULL);
-
- if (!dst) {
- CHECK(dst = (zend_class_entry*) allocate(sizeof(*src)));
- local_dst_alloc = 1;
- }
-
- /* Start with a bitwise copy */
- memcpy(dst, src, sizeof(*src));
-
- dst->name = NULL;
- dst->builtin_functions = NULL;
- memset(&dst->function_table, 0, sizeof(dst->function_table));
- memset(&dst->default_properties, 0, sizeof(dst->default_properties));
-#ifndef ZEND_ENGINE_2
- dst->refcount = NULL;
-#else
- dst->static_members = NULL;
- dst->doc_comment = NULL;
- dst->filename = NULL;
- memset(&dst->properties_info, 0, sizeof(dst->properties_info));
- memset(&dst->constants_table, 0, sizeof(dst->constants_table));
- memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
-#endif
-
- if (src->name) {
- if(!(dst->name = apc_xstrdup(src->name, allocate))) {
- goto cleanup;
- }
- }
-
-#ifndef ZEND_ENGINE_2
- if(!(dst->refcount = apc_xmemcpy(src->refcount,
- sizeof(src->refcount[0]),
- allocate))) {
- goto cleanup;
- }
-#endif
-
- if(!(my_copy_hashtable_ex(&dst->function_table,
- &src->function_table,
- (ht_copy_fun_t) my_copy_function,
- (ht_free_fun_t) my_free_function,
- 0,
- allocate, deallocate,
- (ht_check_copy_fun_t) my_check_copy_function,
- src))) {
- goto cleanup;
- }
-
-#ifdef ZEND_ENGINE_2
-
- /* the interfaces are populated at runtime using ADD_INTERFACE */
- dst->interfaces = NULL;
-
- /* the current count includes inherited interfaces as well,
- the real dynamic ones are the first <n> which are zero'd
- out in zend_do_end_class_declaration */
- for(i = 0 ; i < src->num_interfaces ; i++) {
- if(src->interfaces[i])
- {
- dst->num_interfaces = i;
- break;
- }
- }
-
- /* these will either be set inside my_fixup_hashtable or
- * they will be copied out from parent inside zend_do_inheritance
- */
- dst->constructor = NULL;
- dst->destructor = NULL;
- dst->clone = NULL;
- dst->__get = NULL;
- dst->__set = NULL;
- dst->__unset = NULL;
- dst->__isset = NULL;
- dst->__call = NULL;
-#ifdef ZEND_ENGINE_2_2
- dst->__tostring = NULL;
-#endif
-
- /* unset function proxies */
- dst->serialize_func = NULL;
- dst->unserialize_func = NULL;
-
- my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
-#endif
-
- if(!(my_copy_hashtable_ex(&dst->default_properties,
- &src->default_properties,
- (ht_copy_fun_t) my_copy_zval_ptr,
- (ht_free_fun_t) my_free_zval_ptr,
- 1,
- allocate,deallocate,
- (ht_check_copy_fun_t) my_check_copy_default_property,
- src))) {
- goto cleanup;
- }
-
-#ifdef ZEND_ENGINE_2
-
- if(!(my_copy_hashtable_ex(&dst->properties_info,
- &src->properties_info,
- (ht_copy_fun_t) my_copy_property_info,
- (ht_free_fun_t) my_free_property_info,
- 0,
- allocate, deallocate,
- (ht_check_copy_fun_t) my_check_copy_property_info,
- src))) {
- goto cleanup;
- }
-
-#ifdef ZEND_ENGINE_2_2
- /* php5.2 introduced a scope attribute for property info */
- my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
-#endif
-
- if(!my_copy_hashtable_ex(&dst->default_static_members,
- &src->default_static_members,
- (ht_copy_fun_t) my_copy_zval_ptr,
- (ht_free_fun_t) my_free_zval_ptr,
- 1,
- allocate, deallocate,
- (ht_check_copy_fun_t) my_check_copy_static_member,
- src,
- &src->default_static_members)) {
- goto cleanup;
- }
- if(src->static_members != &src->default_static_members)
- {
- if(!(dst->static_members = my_copy_hashtable_ex(NULL,
- src->static_members,
- (ht_copy_fun_t) my_copy_zval_ptr,
- (ht_free_fun_t) my_free_zval_ptr,
- 1,
- allocate, deallocate,
- (ht_check_copy_fun_t) my_check_copy_static_member,
- src,
- src->static_members))) {
- goto cleanup;
- }
- }
- else
- {
- dst->static_members = &dst->default_static_members;
- }
-
- if(!(my_copy_hashtable(&dst->constants_table,
- &src->constants_table,
- (ht_copy_fun_t) my_copy_zval_ptr,
- (ht_free_fun_t) my_free_zval_ptr,
- 1,
- allocate, deallocate))) {
- goto cleanup;
- }
-
- if (src->doc_comment) {
- if(!(dst->doc_comment =
- apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
- goto cleanup;
- }
- }
-#endif
-
- if (src->builtin_functions) {
- int i, n;
-
- for (n = 0; src->type == ZEND_INTERNAL_CLASS && src->builtin_functions[n].fname != NULL; n++) {}
-
- if(!(dst->builtin_functions =
- (zend_function_entry*)
- allocate((n + 1) * sizeof(zend_function_entry)))) {
- goto cleanup;
- }
-
-
- for (i = 0; i < n; i++) {
- if(!my_copy_function_entry((zend_function_entry*)(&dst->builtin_functions[i]),
- &src->builtin_functions[i],
- allocate, deallocate)) {
- int ii;
-
- for(ii=i-1; ii>=0; ii--) my_destroy_function_entry((zend_function_entry*)(&dst->builtin_functions[ii]), deallocate);
- goto cleanup;
- }
- }
- *(char**)&(dst->builtin_functions[n].fname) = NULL;
- }
-
-#ifdef ZEND_ENGINE_2
- if (src->filename) {
- if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
- goto cleanup;
- }
- }
-#endif
-
- return dst;
-
-
-cleanup:
- if(dst->name) deallocate(dst->name);
-#ifdef ZEND_ENGINE_2
- if(dst->doc_comment) deallocate(dst->doc_comment);
- if(dst->filename) deallocate(dst->filename);
-#else
- if(dst->refcount) deallocate(dst->refcount);
-#endif
-
- if(dst->builtin_functions) deallocate((zend_function_entry*)dst->builtin_functions);
- if(dst->function_table.arBuckets) my_destroy_hashtable(&dst->function_table, (ht_free_fun_t) my_free_function, deallocate);
- if(dst->default_properties.arBuckets) my_destroy_hashtable(&dst->default_properties, (ht_free_fun_t) my_free_zval_ptr, deallocate);
-
-#ifdef ZEND_ENGINE_2
- if(dst->properties_info.arBuckets) my_destroy_hashtable(&dst->properties_info, (ht_free_fun_t) my_free_property_info, deallocate);
- if(dst->default_static_members.arBuckets)
- {
- my_destroy_hashtable(&dst->default_static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
- }
- if(dst->static_members && dst->static_members != &(dst->default_static_members))
- {
- my_destroy_hashtable(dst->static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
- deallocate(dst->static_members);
- }
- if(dst->constants_table.arBuckets) my_destroy_hashtable(&dst->constants_table, (ht_free_fun_t) my_free_zval_ptr, deallocate);
-#endif
- if(local_dst_alloc) deallocate(dst);
-
- return NULL;
-}
-/* }}} */
-
-/* {{{ my_copy_hashtable */
-static HashTable* my_copy_hashtable_ex(HashTable* dst,
- HashTable* src,
- ht_copy_fun_t copy_fn,
- ht_free_fun_t free_fn,
- int holds_ptrs,
- apc_malloc_t allocate,
- apc_free_t deallocate,
- ht_check_copy_fun_t check_fn,
- ...)
-{
- Bucket* curr = NULL;
- Bucket* prev = NULL;
- Bucket* newp = NULL;
- int first = 1;
- int local_dst_alloc = 0;
- int index = 0;
-
- assert(src != NULL);
-
- if (!dst) {
- CHECK(dst = (HashTable*) allocate(sizeof(src[0])));
- local_dst_alloc = 1;
- }
-
- memcpy(dst, src, sizeof(src[0]));
-
- /* allocate buckets for the new hashtable */
- if(!(dst->arBuckets = allocate(dst->nTableSize * sizeof(Bucket*)))) {
- if(local_dst_alloc) deallocate(dst);
- return NULL;
- }
-
- memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
- dst->pInternalPointer = NULL;
- dst->pListHead = NULL;
-
- for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
- int n = curr->h % dst->nTableSize;
-
- if(check_fn) {
- va_list args;
- va_start(args, check_fn);
-
- /* Call the check_fn to see if the current bucket
- * needs to be copied out
- */
- if(!check_fn(curr, args)) {
- dst->nNumOfElements--;
- continue;
- }
-
- va_end(args);
- }
-
- /* create a copy of the bucket 'curr' */
- if(!(newp =
- (Bucket*) apc_xmemcpy(curr,
- sizeof(Bucket) + curr->nKeyLength - 1,
- allocate))) {
- goto cleanup;
- }
-
- /* insert 'newp' into the linked list at its hashed index */
- if (dst->arBuckets[n]) {
- newp->pNext = dst->arBuckets[n];
- newp->pLast = NULL;
- newp->pNext->pLast = newp;
- }
- else {
- newp->pNext = newp->pLast = NULL;
- }
-
- dst->arBuckets[n] = newp;
-
- /* copy the bucket data using our 'copy_fn' callback function */
- if(!(newp->pData = copy_fn(NULL, curr->pData, allocate, deallocate))) {
- goto cleanup;
- }
-
- if (holds_ptrs) {
- memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
- }
- else {
- newp->pDataPtr = NULL;
- }
-
- /* insert 'newp' into the table-thread linked list */
- newp->pListLast = prev;
- newp->pListNext = NULL;
-
- if (prev) {
- prev->pListNext = newp;
- }
-
- if (first) {
- dst->pListHead = newp;
- first = 0;
- }
-
- prev = newp;
- }
-
- dst->pListTail = newp;
-
- return dst;
-
- cleanup:
- for(index = 0; index < dst->nTableSize; index++)
- {
- curr = dst->arBuckets[index];
- while(curr != NULL)
- {
- Bucket * tmp = curr;
- if(curr->pData && free_fn)
- {
- free_fn(curr->pData, deallocate);
- }
- curr = curr->pNext;
- deallocate(tmp);
- }
- }
- deallocate(dst->arBuckets);
- if(local_dst_alloc) deallocate(dst);
- else dst->arBuckets = NULL;
-
- return NULL;
-}
-/* }}} */
-
-/* {{{ my_copy_static_variables */
-static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- if (src->static_variables == NULL) {
- return NULL;
- }
-
- return my_copy_hashtable(NULL,
- src->static_variables,
- (ht_copy_fun_t) my_copy_zval_ptr,
- (ht_free_fun_t) my_free_zval_ptr,
- 1,
- allocate, deallocate);
-}
-/* }}} */
-
-/* {{{ apc_copy_zval */
-zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- int local_dst_alloc = 0;
- assert(src != NULL);
-
- if (!dst) {
-#ifdef ZEND_ENGINE_2_3
- CHECK(dst = (zval*) allocate(sizeof(zval_gc_info)));
-
- if(allocate == apc_php_malloc) {
- GC_ZVAL_INIT(dst);
- }
-#else
- CHECK(dst = (zval*) allocate(sizeof(zval)));
-#endif
- local_dst_alloc = 1;
- }
-
- dst = my_copy_zval(dst, src, allocate, deallocate);
- if(!dst) {
- if(local_dst_alloc) deallocate(dst);
- return NULL;
- }
- return dst;
-}
-/* }}} */
-
-#ifdef ZEND_ENGINE_2
-/* {{{ apc_fixup_op_array_jumps */
-static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
-{
- int i;
-
- for (i=0; i < dst->last; ++i) {
- zend_op *zo = &(dst->opcodes[i]);
- /*convert opline number to jump address*/
- switch (zo->opcode) {
- case ZEND_JMP:
- /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
- zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
- break;
- case ZEND_JMPZ:
- case ZEND_JMPNZ:
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
- break;
- default:
- break;
- }
- }
-}
-/* }}} */
-#endif
-
-/* {{{ apc_copy_op_array */
-zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
-{
- int i;
- int local_dst_alloc = 0;
- apc_fileinfo_t fileinfo;
- char canon_path[MAXPATHLEN];
- char *fullpath = NULL;
-#ifdef ZEND_ENGINE_2
- apc_opflags_t * flags = NULL;
-#endif
-
- assert(src != NULL);
-
- if (!dst) {
- CHECK(dst = (zend_op_array*) allocate(sizeof(src[0])));
- local_dst_alloc = 1;
- }
-
- if(APCG(apc_optimize_function)) {
- APCG(apc_optimize_function)(src TSRMLS_CC);
- }
-
- /* start with a bitwise copy of the array */
- memcpy(dst, src, sizeof(src[0]));
-
- dst->function_name = NULL;
- dst->filename = NULL;
- dst->refcount = NULL;
- dst->opcodes = NULL;
- dst->brk_cont_array = NULL;
- dst->static_variables = NULL;
-#ifdef ZEND_ENGINE_2
- dst->try_catch_array = NULL;
- dst->arg_info = NULL;
- dst->doc_comment = NULL;
-#else
- dst->arg_types = NULL;
-#endif
-#ifdef ZEND_ENGINE_2_1
- dst->vars = NULL;
-#endif
-
- /* copy the arg types array (if set) */
-#ifdef ZEND_ENGINE_2
- if (src->arg_info) {
- if(!(dst->arg_info = my_copy_arg_info_array(NULL,
- src->arg_info,
- src->num_args,
- allocate,
- deallocate))) {
- goto cleanup;
- }
- }
-#else
- if (src->arg_types) {
- if(!(dst->arg_types = apc_xmemcpy(src->arg_types,
- sizeof(src->arg_types[0]) * (src->arg_types[0]+1),
- allocate))) {
- goto cleanup;
- }
- }
-#endif
-
- if (src->function_name) {
- if(!(dst->function_name = apc_xstrdup(src->function_name, allocate))) {
- goto cleanup;
- }
- }
- if (src->filename) {
- if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
- goto cleanup;
- }
- }
-
- if(!(dst->refcount = apc_xmemcpy(src->refcount,
- sizeof(src->refcount[0]),
- allocate))) {
- goto cleanup;
- }
-
- /* deep-copy the opcodes */
- if(!(dst->opcodes = (zend_op*) allocate(sizeof(zend_op) * src->last))) {
- goto cleanup;
- }
-
-#ifdef ZEND_ENGINE_2
- if(APCG(reserved_offset) != -1) {
- /* Insanity alert: the void* pointer is cast into an apc_opflags_t
- * struct. apc_zend_init() checks to ensure that it fits in a void* */
- flags = (apc_opflags_t*) & (dst->reserved[APCG(reserved_offset)]);
- memset(flags, 0, sizeof(apc_opflags_t));
- /* assert(sizeof(apc_opflags_t) < sizeof(dst->reserved)); */
- }
-#endif
-
- for (i = 0; i < src->last; i++) {
-#ifdef ZEND_ENGINE_2
- zend_op *zo = &(src->opcodes[i]);
- /* a lot of files are merely constant arrays with no jumps */
- switch (zo->opcode) {
- case ZEND_JMP:
- case ZEND_JMPZ:
- case ZEND_JMPNZ:
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- if(flags != NULL) {
- flags->has_jumps = 1;
- }
- break;
-#ifdef ZEND_ENGINE_2
- /* auto_globals_jit was not in php-4.3.* */
- case ZEND_FETCH_R:
- case ZEND_FETCH_W:
- case ZEND_FETCH_IS:
- case ZEND_FETCH_FUNC_ARG:
- if(PG(auto_globals_jit) && flags != NULL)
- {
- /* The fetch is only required if auto_globals_jit=1 */
- if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
- zo->op1.op_type == IS_CONST &&
- zo->op1.u.constant.type == IS_STRING) {
- znode * varname = &zo->op1;
- if (varname->u.constant.value.str.val[0] == '_') {
-#define SET_IF_AUTOGLOBAL(member) \
- if(!strcmp(varname->u.constant.value.str.val, #member)) \
- flags->member = 1 /* no ';' here */
- SET_IF_AUTOGLOBAL(_GET);
- else SET_IF_AUTOGLOBAL(_POST);
- else SET_IF_AUTOGLOBAL(_COOKIE);
- else SET_IF_AUTOGLOBAL(_SERVER);
- else SET_IF_AUTOGLOBAL(_ENV);
- else SET_IF_AUTOGLOBAL(_FILES);
- else SET_IF_AUTOGLOBAL(_REQUEST);
- else if(zend_is_auto_global(
- varname->u.constant.value.str.val,
- varname->u.constant.value.str.len
- TSRMLS_CC))
- {
- flags->unknown_global = 1;
- }
- }
- }
- }
- break;
-#endif
- case ZEND_RECV_INIT:
- if(zo->op2.op_type == IS_CONST &&
- zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
- if(flags != NULL) {
- flags->deep_copy = 1;
- }
- }
- break;
- default:
- if((zo->op1.op_type == IS_CONST &&
- zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
- (zo->op2.op_type == IS_CONST &&
- zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) {
- if(flags != NULL) {
- flags->deep_copy = 1;
- }
- }
- break;
- }
-#endif
- if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, allocate, deallocate))) {
- int ii;
- for(ii = i-1; ii>=0; ii--) {
- my_destroy_zend_op(dst->opcodes+ii, deallocate);
- }
- goto cleanup;
- }
-#ifdef ZEND_ENGINE_2
-/* This code breaks apc's rule#1 - cache what you compile */
- if(APCG(fpstat)==0) {
- if((zo->opcode == ZEND_INCLUDE_OR_EVAL) &&
- (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
- /* constant includes */
- if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),Z_STRLEN_P(&zo->op1.u.constant))) {
- if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), &fileinfo) == 0) {
- if((fullpath = realpath(fileinfo.fullpath, canon_path))) {
- /* everything has to go through a realpath() */
- zend_op *dzo = &(dst->opcodes[i]);
- deallocate(dzo->op1.u.constant.value.str.val);
- dzo->op1.u.constant.value.str.len = strlen(fullpath);
- dzo->op1.u.constant.value.str.val = apc_xstrdup(fullpath, allocate);
- }
- }
- }
- }
- }
-#endif
- }
-
-#ifdef ZEND_ENGINE_2
- if(flags == NULL || flags->has_jumps) {
- apc_fixup_op_array_jumps(dst,src);
- }
-#endif
-
- /* copy the break-continue array */
- if (src->brk_cont_array) {
- if(!(dst->brk_cont_array =
- apc_xmemcpy(src->brk_cont_array,
- sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
- allocate))) {
- goto cleanup_opcodes;
- }
- }
-
- /* copy the table of static variables */
- if (src->static_variables) {
- if(!(dst->static_variables = my_copy_static_variables(src, allocate, deallocate))) {
- goto cleanup_opcodes;
- }
- }
-
-#ifdef ZEND_ENGINE_2
- if (src->try_catch_array) {
- if(!(dst->try_catch_array =
- apc_xmemcpy(src->try_catch_array,
- sizeof(src->try_catch_array[0]) * src->last_try_catch,
- allocate))) {
- goto cleanup_opcodes;
- }
- }
-#endif
-
-#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
- if (src->vars) {
- if(!(dst->vars = apc_xmemcpy(src->vars,
- sizeof(src->vars[0]) * src->last_var,
- allocate))) {
- goto cleanup_opcodes;
- }
-
- for(i = 0; i < src->last_var; i++) dst->vars[i].name = NULL;
-
- for(i = 0; i < src->last_var; i++) {
- if(!(dst->vars[i].name = apc_xmemcpy(src->vars[i].name,
- src->vars[i].name_len + 1,
- allocate))) {
- dst->last_var = i;
- goto cleanup_opcodes;
- }
- }
- }
-#endif
-
-#ifdef ZEND_ENGINE_2
- if (src->doc_comment) {
- if (!(dst->doc_comment
- = apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
- goto cleanup_opcodes;
- }
- }
-#endif
-
- return dst;
-
-cleanup_opcodes:
- if(dst->opcodes) {
- for(i=0; i < src->last; i++) my_destroy_zend_op(dst->opcodes+i, deallocate);
- }
-cleanup:
- if(dst->function_name) deallocate(dst->function_name);
- if(dst->refcount) deallocate(dst->refcount);
- if(dst->filename) deallocate(dst->filename);
-#ifdef ZEND_ENGINE_2
- if(dst->arg_info) my_free_arg_info_array(dst->arg_info, dst->num_args, deallocate);
- if(dst->try_catch_array) deallocate(dst->try_catch_array);
- if(dst->doc_comment) deallocate(dst->doc_comment);
-#else
- if(dst->arg_types) deallocate(dst->arg_types);
-#endif
- if(dst->opcodes) deallocate(dst->opcodes);
- if(dst->brk_cont_array) deallocate(dst->brk_cont_array);
- if(dst->static_variables) my_free_hashtable(dst->static_variables, (ht_free_fun_t)my_free_zval_ptr, (apc_free_t)deallocate);
-#ifdef ZEND_ENGINE_2_1
- if (dst->vars) {
- for(i=0; i < dst->last_var; i++) {
- if(dst->vars[i].name) deallocate(dst->vars[i].name);
- }
- deallocate(dst->vars);
- }
-#endif
- if(local_dst_alloc) deallocate(dst);
- return NULL;
-}
-/* }}} */
-
-/* {{{ apc_copy_new_functions */
-apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
-{
- apc_function_t* array;
- int new_count; /* number of new functions in table */
- int i;
-
- new_count = zend_hash_num_elements(CG(function_table)) - old_count;
- assert(new_count >= 0);
-
- CHECK(array =
- (apc_function_t*)
- allocate(sizeof(apc_function_t) * (new_count+1)));
-
- if (new_count == 0) {
- array[0].function = NULL;
- return array;
- }
-
- /* Skip the first `old_count` functions in the table */
- zend_hash_internal_pointer_reset(CG(function_table));
- for (i = 0; i < old_count; i++) {
- zend_hash_move_forward(CG(function_table));
- }
-
- /* Add the next `new_count` functions to our array */
- for (i = 0; i < new_count; i++) {
- char* key;
- uint key_size;
- zend_function* fun;
-
- zend_hash_get_current_key_ex(CG(function_table),
- &key,
- &key_size,
- NULL,
- 0,
- NULL);
-
- zend_hash_get_current_data(CG(function_table), (void**) &fun);
-
- if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
- int ii;
- for(ii=i-1; ii>=0; ii--) {
- deallocate(array[ii].name);
- my_free_function(array[ii].function, deallocate);
- }
- deallocate(array);
- return NULL;
- }
- array[i].name_len = (int) key_size-1;
- if(!(array[i].function = my_copy_function(NULL, fun, allocate, deallocate))) {
- int ii;
- deallocate(array[i].name);
- for(ii=i-1; ii>=0; ii--) {
- deallocate(array[ii].name);
- my_free_function(array[ii].function, deallocate);
- }
- deallocate(array);
- return NULL;
- }
- zend_hash_move_forward(CG(function_table));
- }
-
- array[i].function = NULL;
- return array;
-}
-/* }}} */
-
-/* {{{ apc_copy_new_classes */
-apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
-{
- apc_class_t* array;
- int new_count; /* number of new classes in table */
- int i;
-
- new_count = zend_hash_num_elements(CG(class_table)) - old_count;
- assert(new_count >= 0);
-
- CHECK(array =
- (apc_class_t*)
- allocate(sizeof(apc_class_t)*(new_count+1)));
-
- if (new_count == 0) {
- array[0].class_entry = NULL;
- return array;
- }
-
- /* Skip the first `old_count` classes in the table */
- zend_hash_internal_pointer_reset(CG(class_table));
- for (i = 0; i < old_count; i++) {
- zend_hash_move_forward(CG(class_table));
- }
-
- /* Add the next `new_count` classes to our array */
- for (i = 0; i < new_count; i++) {
- char* key;
- uint key_size;
- zend_class_entry* elem = NULL;
-
- array[i].class_entry = NULL;
-
- zend_hash_get_current_key_ex(CG(class_table),
- &key,
- &key_size,
- NULL,
- 0,
- NULL);
-
- zend_hash_get_current_data(CG(class_table), (void**) &elem);
-
-
-#ifdef ZEND_ENGINE_2
- elem = *((zend_class_entry**)elem);
-#endif
-
- if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
- int ii;
-
- for(ii=i-1; ii>=0; ii--) {
- deallocate(array[ii].name);
- my_destroy_class_entry(array[ii].class_entry, deallocate);
- deallocate(array[ii].class_entry);
- }
- deallocate(array);
- return NULL;
- }
- array[i].name_len = (int) key_size-1;
- if(!(array[i].class_entry = my_copy_class_entry(NULL, elem, allocate, deallocate))) {
- int ii;
-
- deallocate(array[i].name);
- for(ii=i-1; ii>=0; ii--) {
- deallocate(array[ii].name);
- my_destroy_class_entry(array[ii].class_entry, deallocate);
- deallocate(array[ii].class_entry);
- }
- deallocate(array);
- return NULL;
- }
-
- /*
- * If the class has a pointer to its parent class, save the parent
- * name so that we can enable compile-time inheritance when we reload
- * the child class; otherwise, set the parent name to null and scan
- * the op_array to determine if this class inherits from some base
- * class at execution-time.
- */
-
- if (elem->parent) {
- if(!(array[i].parent_name =
- apc_xstrdup(elem->parent->name, allocate))) {
- int ii;
-
- for(ii=i; ii>=0; ii--) {
- deallocate(array[ii].name);
- my_destroy_class_entry(array[ii].class_entry, deallocate);
- deallocate(array[ii].class_entry);
- if(ii==i) continue;
- if(array[ii].parent_name) deallocate(array[ii].parent_name);
- }
- deallocate(array);
- return NULL;
- }
- array[i].is_derived = 1;
- }
- else {
- array[i].parent_name = NULL;
- array[i].is_derived = is_derived_class(op_array, key, key_size);
- }
-
- zend_hash_move_forward(CG(class_table));
- }
-
- array[i].class_entry = NULL;
- return array;
-}
-/* }}} */
-
-/* {{{ my_destroy_zval_ptr */
-static void my_destroy_zval_ptr(zval** src, apc_free_t deallocate)
-{
- assert(src != NULL);
- if(my_destroy_zval(src[0], deallocate) == SUCCESS) {
- deallocate(src[0]);
- }
-}
-/* }}} */
-
-/* {{{ my_destroy_zval */
-static int my_destroy_zval(zval* src, apc_free_t deallocate)
-{
- zval **tmp;
- TSRMLS_FETCH();
-
- switch (src->type & ~IS_CONSTANT_INDEX) {
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- case IS_DOUBLE:
- case IS_NULL:
- break;
-
- case IS_CONSTANT:
- case IS_STRING:
-#ifndef ZEND_ENGINE_2
- case FLAG_IS_BC:
-#endif
- deallocate(src->value.str.val);
- break;
-
- case IS_ARRAY:
-
- /* Maintain a list of zvals we've copied to properly handle recursive structures */
- if(APCG(copied_zvals)) {
- if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
- Z_DELREF_PP(tmp);
- return FAILURE;
- }
- zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&src, sizeof(zval*), NULL);
- }
- /* fall through */
-
- case IS_CONSTANT_ARRAY:
- my_free_hashtable(src->value.ht,
- (ht_free_fun_t) my_free_zval_ptr,
- deallocate);
- break;
-
- case IS_OBJECT:
-#ifndef ZEND_ENGINE_2
- my_destroy_class_entry(src->value.obj.ce, deallocate);
- deallocate(src->value.obj.ce);
- my_free_hashtable(src->value.obj.properties,
- (ht_free_fun_t) my_free_zval_ptr,
- deallocate);
-#endif
- break;
-
- default:
- assert(0);
- }
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ my_destroy_znode */
-static void my_destroy_znode(znode* src, apc_free_t deallocate)
-{
- if (src->op_type == IS_CONST) {
- my_destroy_zval(&src->u.constant, deallocate);
- }
-}
-/* }}} */
-
-/* {{{ my_destroy_zend_op */
-static void my_destroy_zend_op(zend_op* src, apc_free_t deallocate)
-{
- my_destroy_znode(&src->result, deallocate);
- my_destroy_znode(&src->op1, deallocate);
- my_destroy_znode(&src->op2, deallocate);
-}
-/* }}} */
-
-/* {{{ my_destroy_function */
-static void my_destroy_function(zend_function* src, apc_free_t deallocate)
-{
- assert(src != NULL);
-
- switch (src->type) {
- case ZEND_INTERNAL_FUNCTION:
- case ZEND_OVERLOADED_FUNCTION:
- break;
-
- case ZEND_USER_FUNCTION:
- case ZEND_EVAL_CODE:
- my_destroy_op_array(&src->op_array, deallocate);
- break;
-
- default:
- assert(0);
- }
-}
-/* }}} */
-
-/* {{{ my_destroy_function_entry */
-static void my_destroy_function_entry(zend_function_entry* src, apc_free_t deallocate)
-{
- assert(src != NULL);
-
- deallocate((char*)src->fname);
-#ifdef ZEND_ENGINE_2
- if (src->arg_info) {
- my_free_arg_info_array((zend_arg_info*)src->arg_info, src->num_args, deallocate);
- }
-#else
- if (src->func_arg_types) {
- deallocate(src->func_arg_types);
- }
-#endif
-}
-/* }}} */
-
-#ifdef ZEND_ENGINE_2
-/* {{{ my_destroy_property_info*/
-static void my_destroy_property_info(zend_property_info* src, apc_free_t deallocate)
-{
- assert(src != NULL);
-
- deallocate(src->name);
-#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
- if(src->doc_comment) deallocate(src->doc_comment);
-#endif
-}
-/* }}} */
-
-/* {{{ my_destroy_arg_info_array */
-static void my_destroy_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
-{
- int i = 0;
-
- assert(src != NULL);
-
- for(i=0; i < num_args; i++) {
- my_destroy_arg_info(&src[i], deallocate);
- }
-}
-/* }}} */
-
-/* {{{ my_destroy_arg_info */
-static void my_destroy_arg_info(zend_arg_info* src, apc_free_t deallocate)
-{
- assert(src != NULL);
-
- deallocate((char*)src->name);
- deallocate((char*)src->class_name);
-}
-/* }}} */
-#endif
-
-/* {{{ my_destroy_class_entry */
-static void my_destroy_class_entry(zend_class_entry* src, apc_free_t deallocate)
-{
- uint i;
-
- assert(src != NULL);
-
- deallocate(src->name);
-#ifndef ZEND_ENGINE_2
- deallocate(src->refcount);
-#else
- if(src->doc_comment) deallocate(src->doc_comment);
- if(src->filename) deallocate(src->filename);
-#endif
-
- my_destroy_hashtable(&src->function_table,
- (ht_free_fun_t) my_free_function,
- deallocate);
-
- my_destroy_hashtable(&src->default_properties,
- (ht_free_fun_t) my_free_zval_ptr,
- deallocate);
-
-#ifdef ZEND_ENGINE_2
- my_destroy_hashtable(&src->properties_info,
- (ht_free_fun_t) my_free_property_info,
- deallocate);
- if(src->static_members)
- {
- my_destroy_hashtable(src->static_members,
- (ht_free_fun_t) my_free_zval_ptr,
- deallocate);
- if(src->static_members != &(src->default_static_members))
- {
- deallocate(src->static_members);
- }
- }
-
- my_destroy_hashtable(&src->constants_table,
- (ht_free_fun_t) my_free_zval_ptr,
- deallocate);
-#endif
-
- if (src->builtin_functions) {
- for (i = 0; src->builtin_functions[i].fname != NULL; i++) {
- my_destroy_function_entry((zend_function_entry*)(&src->builtin_functions[i]), deallocate);
- }
- deallocate((zend_function_entry*)src->builtin_functions);
- }
-}
-/* }}} */
-
-/* {{{ my_destroy_hashtable */
-static void my_destroy_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
-{
- int i;
-
- assert(src != NULL);
-
- for (i = 0; i < src->nTableSize; i++) {
- Bucket* p = src->arBuckets[i];
- while (p != NULL) {
- Bucket* q = p;
- p = p->pNext;
- free_fn(q->pData, deallocate);
- deallocate(q);
- }
- }
-
- deallocate(src->arBuckets);
-}
-/* }}} */
-
-/* {{{ my_destroy_op_array */
-static void my_destroy_op_array(zend_op_array* src, apc_free_t deallocate)
-{
- int i;
-
- assert(src != NULL);
-
-#ifdef ZEND_ENGINE_2
- if (src->arg_info) {
- my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
- }
-#else
- if (src->arg_types) {
- deallocate(src->arg_types);
- }
-#endif
-
- deallocate(src->function_name);
- deallocate(src->filename);
- deallocate(src->refcount);
-
- for (i = 0; i < src->last; i++) {
- my_destroy_zend_op(src->opcodes + i, deallocate);
- }
- deallocate(src->opcodes);
-
- if (src->brk_cont_array) {
- deallocate(src->brk_cont_array);
- }
-
- if (src->static_variables) {
- my_free_hashtable(src->static_variables,
- (ht_free_fun_t) my_free_zval_ptr,
- deallocate);
- }
-
-#ifdef ZEND_ENGINE_2_1
- if (src->vars) {
- for(i=0; i < src->last_var; i++) {
- if(src->vars[i].name) deallocate(src->vars[i].name);
- }
- deallocate(src->vars);
- }
-#endif
-#ifdef ZEND_ENGINE_2
- if(src->try_catch_array) {
- deallocate(src->try_catch_array);
- }
- if (src->doc_comment) {
- deallocate(src->doc_comment);
- }
-#endif
-}
-/* }}} */
-
-/* {{{ my_free_zval_ptr */
-static void my_free_zval_ptr(zval** src, apc_free_t deallocate)
-{
- my_destroy_zval_ptr(src, deallocate);
- deallocate(src);
-}
-/* }}} */
-
-#ifdef ZEND_ENGINE_2
-/* {{{ my_free_property_info */
-static void my_free_property_info(zend_property_info* src, apc_free_t deallocate)
-{
- my_destroy_property_info(src, deallocate);
- deallocate(src);
-}
-/* }}} */
-
-/* {{{ my_free_arg_info_array */
-static void my_free_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
-{
- my_destroy_arg_info_array(src, num_args, deallocate);
- deallocate(src);
-}
-/* }}} */
-
-/* {{{ my_free_arg_info */
-static void my_free_arg_info(zend_arg_info* src, apc_free_t deallocate)
-{
- my_destroy_arg_info(src, deallocate);
- deallocate(src);
-}
-/* }}} */
-#endif
-
-/* {{{ my_free_function */
-static void my_free_function(zend_function* src, apc_free_t deallocate)
-{
- my_destroy_function(src, deallocate);
- deallocate(src);
-}
-/* }}} */
-
-/* {{{ my_free_hashtable */
-static void my_free_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
-{
- my_destroy_hashtable(src, free_fn, deallocate);
- deallocate(src);
-}
-/* }}} */
-
-/* {{{ apc_free_op_array */
-void apc_free_op_array(zend_op_array* src, apc_free_t deallocate)
-{
- if (src != NULL) {
- my_destroy_op_array(src, deallocate);
- deallocate(src);
- }
-}
-/* }}} */
-
-/* {{{ apc_free_functions */
-void apc_free_functions(apc_function_t* src, apc_free_t deallocate)
-{
- int i;
-
- if (src != NULL) {
- for (i = 0; src[i].function != NULL; i++) {
- deallocate(src[i].name);
- my_destroy_function(src[i].function, deallocate);
- deallocate(src[i].function);
- }
- deallocate(src);
- }
-}
-/* }}} */
-
-/* {{{ apc_free_classes */
-void apc_free_classes(apc_class_t* src, apc_free_t deallocate)
-{
- int i;
-
- if (src != NULL) {
- for (i = 0; src[i].class_entry != NULL; i++) {
- deallocate(src[i].name);
- deallocate(src[i].parent_name);
- my_destroy_class_entry(src[i].class_entry, deallocate);
- deallocate(src[i].class_entry);
- }
- deallocate(src);
- }
-}
-/* }}} */
-
-/* {{{ apc_free_zval */
-void apc_free_zval(zval* src, apc_free_t deallocate)
-{
- if (src != NULL) {
- if(my_destroy_zval(src, deallocate) == SUCCESS) {
- deallocate(src);
- }
- }
-}
-/* }}} */
-
-
-/* Used only by my_prepare_op_array_for_execution */
-#define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION() \
- /* The fetch is only required if auto_globals_jit=1 */ \
- if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL && \
- zo->op1.op_type == IS_CONST && \
- zo->op1.u.constant.type == IS_STRING && \
- zo->op1.u.constant.value.str.val[0] == '_') { \
- \
- znode* varname = &zo->op1; \
- (void)zend_is_auto_global(varname->u.constant.value.str.val, \
- varname->u.constant.value.str.len \
- TSRMLS_CC); \
- } \
-
-/* {{{ my_prepare_op_array_for_execution */
-static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
-{
- /* combine my_fetch_global_vars and my_copy_data_exceptions.
- * - Pre-fetch superglobals which would've been pre-fetched in parse phase.
- * - If the opcode stream contain mutable data, ensure a copy.
- * - Fixup array jumps in the same loop.
- */
- int i=src->last;
- zend_op *zo;
- zend_op *dzo;
-#ifdef ZEND_ENGINE_2
- apc_opflags_t * flags = APCG(reserved_offset) != -1 ?
- (apc_opflags_t*) & (src->reserved[APCG(reserved_offset)]) : NULL;
- int needcopy = flags ? flags->deep_copy : 1;
- /* auto_globals_jit was not in php4 */
- int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
-
-#define FETCH_AUTOGLOBAL(member) do { \
- if(flags && flags->member == 1) { \
- zend_is_auto_global(#member,\
- (sizeof(#member) - 1)\
- TSRMLS_CC);\
- } \
-}while(0);
-
- FETCH_AUTOGLOBAL(_GET);
- FETCH_AUTOGLOBAL(_POST);
- FETCH_AUTOGLOBAL(_COOKIE);
- FETCH_AUTOGLOBAL(_SERVER);
- FETCH_AUTOGLOBAL(_ENV);
- FETCH_AUTOGLOBAL(_FILES);
- FETCH_AUTOGLOBAL(_REQUEST);
-
-#else
- int needcopy = 0;
- int do_prepare_fetch_global = 0;
- int j = 0;
-
- for(j = 0; j < src->last; j++) {
- zo = &src->opcodes[j];
-
- if( ((zo->op1.op_type == IS_CONST &&
- zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
- ((zo->op2.op_type == IS_CONST &&
- zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
- needcopy = 1;
- }
- }
-#endif
-
- if(needcopy) {
-
- dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes,
- sizeof(zend_op) * src->last,
- apc_php_malloc);
- zo = src->opcodes;
- dzo = dst->opcodes;
- while(i > 0) {
-
- if( ((zo->op1.op_type == IS_CONST &&
- zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
- ((zo->op2.op_type == IS_CONST &&
- zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
-
- if(!(my_copy_zend_op(dzo, zo, apc_php_malloc, apc_php_free))) {
- assert(0); /* emalloc failed or a bad constant array */
- }
- }
-
-#ifdef ZEND_ENGINE_2
- switch(zo->opcode) {
- case ZEND_JMP:
- dzo->op1.u.jmp_addr = dst->opcodes +
- (zo->op1.u.jmp_addr - src->opcodes);
- break;
- case ZEND_JMPZ:
- case ZEND_JMPNZ:
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- dzo->op2.u.jmp_addr = dst->opcodes +
- (zo->op2.u.jmp_addr - src->opcodes);
- break;
- case ZEND_FETCH_R:
- case ZEND_FETCH_W:
- case ZEND_FETCH_IS:
- case ZEND_FETCH_FUNC_ARG:
- if(do_prepare_fetch_global)
- {
- APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
- }
- break;
- default:
- break;
- }
-#endif
- i--;
- zo++;
- dzo++;
- }
-#ifdef ZEND_ENGINE_2
- } else { /* !needcopy */
- /* The fetch is only required if auto_globals_jit=1 */
- if(do_prepare_fetch_global)
- {
- zo = src->opcodes;
- while(i > 0) {
-
- if(zo->opcode == ZEND_FETCH_R ||
- zo->opcode == ZEND_FETCH_W ||
- zo->opcode == ZEND_FETCH_IS ||
- zo->opcode == ZEND_FETCH_FUNC_ARG
- ) {
- APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
- }
-
- i--;
- zo++;
- }
- }
-#endif
- }
- return 1;
-}
-/* }}} */
-
-/* {{{ apc_copy_op_array_for_execution */
-zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
-{
- if(dst == NULL) {
- dst = (zend_op_array*) emalloc(sizeof(src[0]));
- }
- memcpy(dst, src, sizeof(src[0]));
- dst->static_variables = my_copy_static_variables(src, apc_php_malloc, apc_php_free);
-
- dst->refcount = apc_xmemcpy(src->refcount,
- sizeof(src->refcount[0]),
- apc_php_malloc);
-
- my_prepare_op_array_for_execution(dst,src TSRMLS_CC);
-
- return dst;
-}
-/* }}} */
-
-/* {{{ apc_copy_function_for_execution */
-zend_function* apc_copy_function_for_execution(zend_function* src)
-{
- zend_function* dst;
- TSRMLS_FETCH();
-
- dst = (zend_function*) emalloc(sizeof(src[0]));
- memcpy(dst, src, sizeof(src[0]));
- apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array) TSRMLS_CC);
- return dst;
-}
-/* }}} */
-
-/* {{{ apc_copy_function_for_execution_ex */
-zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
-{
- if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
- return apc_copy_function_for_execution(src);
-}
-/* }}} */
-
-/* {{{ apc_copy_class_entry_for_execution */
-zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived)
-{
- zend_class_entry* dst = (zend_class_entry*) emalloc(sizeof(src[0]));
- memcpy(dst, src, sizeof(src[0]));
-
-#ifdef ZEND_ENGINE_2
- if(src->num_interfaces)
- {
- /* These are slots to be populated later by ADD_INTERFACE insns */
- dst->interfaces = apc_php_malloc(
- sizeof(zend_class_entry*) * src->num_interfaces);
- memset(dst->interfaces, 0,
- sizeof(zend_class_entry*) * src->num_interfaces);
- }
- else
- {
- /* assert(dst->interfaces == NULL); */
- }
-#endif
-
-#ifndef ZEND_ENGINE_2
- dst->refcount = apc_xmemcpy(src->refcount,
- sizeof(src->refcount[0]),
- apc_php_malloc);
-#endif
-
- /* Deep-copy the class properties, because they will be modified */
-
- my_copy_hashtable(&dst->default_properties,
- &src->default_properties,
- (ht_copy_fun_t) my_copy_zval_ptr,
- (ht_free_fun_t) my_free_zval_ptr,
- 1,
- apc_php_malloc, apc_php_free);
-
- /* For derived classes, we must also copy the function hashtable (although
- * we can merely bitwise copy the functions it contains) */
-
- my_copy_hashtable(&dst->function_table,
- &src->function_table,
- (ht_copy_fun_t) apc_copy_function_for_execution_ex,
- NULL,
- 0,
- apc_php_malloc, apc_php_free);
-#ifdef ZEND_ENGINE_2
- my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
-
- /* zend_do_inheritance merges properties_info.
- * Need only shallow copying as it doesn't hold the pointers.
- */
- my_copy_hashtable(&dst->properties_info,
- &src->properties_info,
- (ht_copy_fun_t) my_copy_property_info_for_execution,
- NULL,
- 0,
- apc_php_malloc, apc_php_free);
-
-#ifdef ZEND_ENGINE_2_2
- /* php5.2 introduced a scope attribute for property info */
- my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
-#endif
-
- /* if inheritance results in a hash_del, it might result in
- * a pefree() of the pointers here. Deep copying required.
- */
-
- my_copy_hashtable(&dst->constants_table,
- &src->constants_table,
- (ht_copy_fun_t) my_copy_zval_ptr,
- NULL,
- 1,
- apc_php_malloc, apc_php_free);
-
- my_copy_hashtable(&dst->default_static_members,
- &src->default_static_members,
- (ht_copy_fun_t) my_copy_zval_ptr,
- (ht_free_fun_t) my_free_zval_ptr,
- 1,
- apc_php_malloc, apc_php_free);
-
- if(src->static_members != &(src->default_static_members))
- {
- dst->static_members = my_copy_hashtable(NULL,
- src->static_members,
- (ht_copy_fun_t) my_copy_zval_ptr,
- (ht_free_fun_t) my_free_zval_ptr,
- 1,
- apc_php_malloc, apc_php_free);
- }
- else
- {
- dst->static_members = &(dst->default_static_members);
- }
-
-#endif
-
- return dst;
-}
-/* }}} */
-
-/* {{{ apc_free_class_entry_after_execution */
-void apc_free_class_entry_after_execution(zend_class_entry* src)
-{
-#ifdef ZEND_ENGINE_2
- if(src->num_interfaces > 0 && src->interfaces) {
- apc_php_free(src->interfaces);
- src->interfaces = NULL;
- src->num_interfaces = 0;
- }
- /* my_destroy_hashtable() does not play nice with refcounts */
-
- zend_hash_clean(&src->default_static_members);
- if(src->static_members != &(src->default_static_members))
- {
- zend_hash_destroy(src->static_members);
- apc_php_free(src->static_members);
- src->static_members = NULL;
- }
- else
- {
- src->static_members = NULL;
- }
- zend_hash_clean(&src->default_properties);
- zend_hash_clean(&src->constants_table);
-#endif
-
- /* TODO: more cleanup */
-}
-/* }}} */
-
-#ifdef ZEND_ENGINE_2
-
-/* {{{ my_fixup_function */
-static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
-{
- zend_function* zf = p->pData;
-
- #define SET_IF_SAME_NAME(member) \
- do { \
- if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
- dst->member = zf; \
- } \
- } \
- while(0)
-
- if(zf->common.scope == src)
- {
-
- /* Fixing up the default functions for objects here since
- * we need to compare with the newly allocated functions
- *
- * caveat: a sub-class method can have the same name as the
- * parent's constructor and create problems.
- */
-
- if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
- else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
- else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
- else
- {
- SET_IF_SAME_NAME(__get);
- SET_IF_SAME_NAME(__set);
- SET_IF_SAME_NAME(__unset);
- SET_IF_SAME_NAME(__isset);
- SET_IF_SAME_NAME(__call);
-#ifdef ZEND_ENGINE_2_2
- SET_IF_SAME_NAME(__tostring);
-#endif
- }
- zf->common.scope = dst;
- }
- else
- {
- /* no other function should reach here */
- assert(0);
- }
-
- #undef SET_IF_SAME_NAME
-}
-/* }}} */
-
-#ifdef ZEND_ENGINE_2_2
-/* {{{ my_fixup_property_info */
-static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
-{
- zend_property_info* property_info = (zend_property_info*)p->pData;
-
- if(property_info->ce == src)
- {
- property_info->ce = dst;
- }
- else
- {
- assert(0); /* should never happen */
- }
-}
-/* }}} */
-#endif
-
-/* {{{ my_fixup_hashtable */
-static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
-{
- Bucket *p;
-
- uint i;
-
- for (i = 0; i < ht->nTableSize; i++) {
- if(!ht->arBuckets) break;
- p = ht->arBuckets[i];
- while (p != NULL) {
- fixup(p, src, dst);
- p = p->pNext;
- }
- }
-}
-/* }}} */
-
-#endif
-
-/* {{{ my_check_copy_function */
-static int my_check_copy_function(Bucket* p, va_list args)
-{
- zend_class_entry* src = va_arg(args, zend_class_entry*);
- zend_function* zf = (zend_function*)p->pData;
-#ifndef ZEND_ENGINE_2
- zend_class_entry* parent = src->parent;
- zend_function* parent_fn = NULL;
-#endif
-
-#ifdef ZEND_ENGINE_2
- return (zf->common.scope == src);
-#else
- if (parent &&
- zend_hash_quick_find(&parent->function_table, p->arKey,
- p->nKeyLength, p->h, (void **) &parent_fn)==SUCCESS) {
-
- if((parent_fn && zf) &&
- (parent_fn->op_array.refcount == zf->op_array.refcount))
- {
- return 0;
- }
- }
- return 1;
-#endif
-}
-/* }}} */
-
-/* {{{ my_check_copy_default_property */
-static int my_check_copy_default_property(Bucket* p, va_list args)
-{
- zend_class_entry* src = va_arg(args, zend_class_entry*);
- zend_class_entry* parent = src->parent;
- zval ** child_prop = (zval**)p->pData;
- zval ** parent_prop = NULL;
-
- if (parent &&
- zend_hash_quick_find(&parent->default_properties, p->arKey,
- p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
-
- if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
- {
- return 0;
- }
- }
-
- /* possibly not in the parent */
- return 1;
-}
-/* }}} */
-
-#ifdef ZEND_ENGINE_2
-
-/* {{{ my_check_copy_property_info */
-static int my_check_copy_property_info(Bucket* p, va_list args)
-{
- zend_class_entry* src = va_arg(args, zend_class_entry*);
- zend_class_entry* parent = src->parent;
- zend_property_info* child_info = (zend_property_info*)p->pData;
- zend_property_info* parent_info = NULL;
-
-#ifdef ZEND_ENGINE_2_2
- /* so much easier */
- return (child_info->ce == src);
-#endif
-
- if (parent &&
- zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength,
- p->h, (void **) &parent_info)==SUCCESS) {
- if(parent_info->flags & ZEND_ACC_PRIVATE)
- {
- return 1;
- }
- if((parent_info->flags & ZEND_ACC_PPP_MASK) !=
- (child_info->flags & ZEND_ACC_PPP_MASK))
- {
- /* TODO: figure out whether ACC_CHANGED is more appropriate
- * here */
- return 1;
- }
- return 0;
- }
-
- /* property doesn't exist in parent, copy into cached child */
- return 1;
-}
-/* }}} */
-
-/* {{{ my_check_copy_static_member */
-static int my_check_copy_static_member(Bucket* p, va_list args)
-{
- zend_class_entry* src = va_arg(args, zend_class_entry*);
- HashTable * ht = va_arg(args, HashTable*);
- zend_class_entry* parent = src->parent;
- HashTable * parent_ht = NULL;
- char * member_name;
- char * class_name = NULL;
-
- zend_property_info *parent_info = NULL;
- zend_property_info *child_info = NULL;
- zval ** parent_prop = NULL;
- zval ** child_prop = (zval**)(p->pData);
-
- if(!parent) {
- return 1;
- }
-
- /* these do not need free'ing */
-#ifdef ZEND_ENGINE_2_2
- zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
-#else
- zend_unmangle_property_name(p->arKey, &class_name, &member_name);
-#endif
-
- /* please refer do_inherit_property_access_check in zend_compile.c
- * to understand why we lookup in properties_info.
- */
- if((zend_hash_find(&parent->properties_info, member_name,
- strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
- &&
- (zend_hash_find(&src->properties_info, member_name,
- strlen(member_name)+1, (void**)&child_info) == SUCCESS))
- {
- if(child_info->flags & ZEND_ACC_STATIC &&
- (parent_info->flags & ZEND_ACC_PROTECTED &&
- child_info->flags & ZEND_ACC_PUBLIC))
- {
- /* Do not copy into static_members. zend_do_inheritance
- * will automatically insert a NULL value.
- * TODO: decrement refcount or fixup when copying out for exec ?
- */
- return 0;
- }
- if(ht == &(src->default_static_members))
- {
- parent_ht = &parent->default_static_members;
- }
- else
- {
- parent_ht = parent->static_members;
- }
-
- if(zend_hash_quick_find(parent_ht, p->arKey,
- p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
- {
- /* they point to the same zval */
- if(*parent_prop == *child_prop)
- {
- return 0;
- }
- }
- }
-
- return 1;
-}
-/* }}} */
-#endif
-
-/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
- * register a optimizer callback function, returns the previous callback
- */
-apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
- apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
- APCG(apc_optimize_function) = optimizer;
- return old_optimizer;
-}
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
- * vim<600: expandtab sw=4 ts=4 sts=4
- */