Skip to content

Commit

Permalink
Reinitializing memory manager when serializing objects in session
Browse files Browse the repository at this point in the history
  • Loading branch information
phalcon committed Mar 25, 2014
1 parent 7114d8d commit 2a80399
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 179 deletions.
53 changes: 53 additions & 0 deletions ext/kernel/fcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,59 @@ static const unsigned char tolower_map[256] = {
};
#endif

#ifndef PHALCON_RELEASE
void phalcon_fcall_cache_dtor(void *pData)
{
phalcon_fcall_cache_entry **entry = (phalcon_fcall_cache_entry**)pData;
free(*entry);
}
#endif

int phalcon_cleanup_fcache(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
{
phalcon_fcall_cache_entry **entry = (phalcon_fcall_cache_entry**)pDest;
zend_class_entry *scope;
uint len = hash_key->nKeyLength;

assert(hash_key->arKey != NULL);
assert(hash_key->nKeyLength > 2 * sizeof(zend_class_entry**));

memcpy(&scope, &hash_key->arKey[len - 2 * sizeof(zend_class_entry**)], sizeof(zend_class_entry*));

/*
#ifndef PHALCON_RELEASE
{
zend_class_entry *cls;
memcpy(&cls, &hash_key->arKey[len - sizeof(zend_class_entry**)], sizeof(zend_class_entry*));
fprintf(stderr, "func: %s, cls: %s, scope: %s [%u]\n", (*entry)->f->common.function_name, (cls ? cls->name : "N/A"), (scope ? scope->name : "N/A"), (uint)(*entry)->times);
}
#endif
*/

#ifndef PHALCON_RELEASE
if ((*entry)->f->type != ZEND_INTERNAL_FUNCTION || (scope && scope->type != ZEND_INTERNAL_CLASS)) {
return ZEND_HASH_APPLY_REMOVE;
}
#else
if ((*entry)->type != ZEND_INTERNAL_FUNCTION || (scope && scope->type != ZEND_INTERNAL_CLASS)) {
return ZEND_HASH_APPLY_REMOVE;
}
#endif

#if PHP_VERSION_ID >= 50400
if (scope && scope->type == ZEND_INTERNAL_CLASS && scope->info.internal.module->type != MODULE_PERSISTENT) {
return ZEND_HASH_APPLY_REMOVE;
}
#else
if (scope && scope->type == ZEND_INTERNAL_CLASS && scope->module->type != MODULE_PERSISTENT) {
return ZEND_HASH_APPLY_REMOVE;
}
#endif

return ZEND_HASH_APPLY_KEEP;
}

int phalcon_has_constructor_ce(const zend_class_entry *ce)
{
while (ce) {
Expand Down
6 changes: 6 additions & 0 deletions ext/kernel/fcall.h
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,12 @@ PHALCON_ATTR_WARN_UNUSED_RESULT static inline int phalcon_call_user_func_array(z
return (EG(exception)) ? FAILURE : status;
}

#ifndef PHALCON_RELEASE
void phalcon_fcall_cache_dtor(void *pData);
#endif

int phalcon_cleanup_fcache(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);

/**
* @brief Checks if the class defines a constructor
* @param ce Class entry
Expand Down
2 changes: 2 additions & 0 deletions ext/kernel/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
*/
void php_phalcon_init_globals(zend_phalcon_globals *phalcon_globals TSRMLS_DC) {

phalcon_globals->initialized = 0;

/* Memory options */
phalcon_globals->active_memory = NULL;

Expand Down
129 changes: 127 additions & 2 deletions ext/kernel/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "kernel/fcall.h"
#include "kernel/backtrace.h"
#include "kernel/framework/orm.h"

/*
* Memory Frames/Virtual Symbol Scopes
Expand All @@ -42,6 +43,119 @@
* Not all methods must grow/restore the phalcon_memory_entry.
*/

void phalcon_initialize_memory(zend_phalcon_globals *phalcon_globals_ptr TSRMLS_DC)
{
phalcon_memory_entry *start;
size_t i;

start = (phalcon_memory_entry *) pecalloc(PHALCON_NUM_PREALLOCATED_FRAMES, sizeof(phalcon_memory_entry), 1);
/* pecalloc() will take care of these members for every frame
start->pointer = 0;
start->hash_pointer = 0;
start->prev = NULL;
start->next = NULL;
*/
for (i = 0; i < PHALCON_NUM_PREALLOCATED_FRAMES; ++i) {
start[i].addresses = pecalloc(24, sizeof(zval*), 1);
start[i].capacity = 24;
start[i].hash_addresses = pecalloc(8, sizeof(zval*), 1);
start[i].hash_capacity = 8;

#ifndef PHALCON_RELEASE
start[i].permanent = 1;
#endif
}

start[0].next = &start[1];
start[PHALCON_NUM_PREALLOCATED_FRAMES - 1].prev = &start[PHALCON_NUM_PREALLOCATED_FRAMES - 2];

for (i = 1; i < PHALCON_NUM_PREALLOCATED_FRAMES - 1; ++i) {
start[i].next = &start[i + 1];
start[i].prev = &start[i - 1];
}

phalcon_globals_ptr->start_memory = start;
phalcon_globals_ptr->end_memory = start + PHALCON_NUM_PREALLOCATED_FRAMES;

phalcon_globals_ptr->fcache = pemalloc(sizeof(HashTable), 1);
#ifndef PHALCON_RELEASE
zend_hash_init(phalcon_globals_ptr->fcache, 128, NULL, phalcon_fcall_cache_dtor, 1);
#else
zend_hash_init(phalcon_globals_ptr->fcache, 128, NULL, NULL, 1);
#endif

/* 'Allocator sizeof operand mismatch' warning can be safely ignored */
ALLOC_INIT_ZVAL(phalcon_globals_ptr->z_null);
Z_SET_REFCOUNT_P(phalcon_globals_ptr->z_null, 2);

/* 'Allocator sizeof operand mismatch' warning can be safely ignored */
ALLOC_INIT_ZVAL(phalcon_globals_ptr->z_false);
Z_SET_REFCOUNT_P(phalcon_globals_ptr->z_false, 2);
ZVAL_FALSE(phalcon_globals_ptr->z_false);

/* 'Allocator sizeof operand mismatch' warning can be safely ignored */
ALLOC_INIT_ZVAL(phalcon_globals_ptr->z_true);
Z_SET_REFCOUNT_P(phalcon_globals_ptr->z_true, 2);
ZVAL_TRUE(phalcon_globals_ptr->z_true);

/* 'Allocator sizeof operand mismatch' warning can be safely ignored */
ALLOC_INIT_ZVAL(phalcon_globals_ptr->z_zero);
Z_SET_REFCOUNT_P(phalcon_globals_ptr->z_zero, 2);
ZVAL_LONG(phalcon_globals_ptr->z_zero, 0);

/* 'Allocator sizeof operand mismatch' warning can be safely ignored */
ALLOC_INIT_ZVAL(phalcon_globals_ptr->z_one);
Z_SET_REFCOUNT_P(phalcon_globals_ptr->z_one, 2);
ZVAL_LONG(phalcon_globals_ptr->z_one, 1);

phalcon_globals_ptr->initialized = 1;
}

void phalcon_deinitialize_memory(TSRMLS_D)
{
size_t i;
zend_phalcon_globals *phalcon_globals_ptr = PHALCON_VGLOBAL;

if (phalcon_globals_ptr->initialized != 1) {
phalcon_globals_ptr->initialized = 0;
return;
}

if (phalcon_globals_ptr->start_memory != NULL) {
phalcon_clean_restore_stack(TSRMLS_C);
}

phalcon_orm_destroy_cache(TSRMLS_C);

zend_hash_apply_with_arguments(phalcon_globals_ptr->fcache TSRMLS_CC, phalcon_cleanup_fcache, 0);

#ifndef PHALCON_RELEASE
assert(phalcon_globals_ptr->start_memory != NULL);
#endif

for (i = 0; i < PHALCON_NUM_PREALLOCATED_FRAMES; ++i) {
pefree(phalcon_globals_ptr->start_memory[i].hash_addresses, 1);
pefree(phalcon_globals_ptr->start_memory[i].addresses, 1);
}

pefree(phalcon_globals_ptr->start_memory, 1);
phalcon_globals_ptr->start_memory = NULL;

zend_hash_destroy(phalcon_globals_ptr->fcache);
pefree(phalcon_globals_ptr->fcache, 1);
phalcon_globals_ptr->fcache = NULL;

for (i = 0; i < 2; i++) {
zval_ptr_dtor(&phalcon_globals_ptr->z_null);
zval_ptr_dtor(&phalcon_globals_ptr->z_false);
zval_ptr_dtor(&phalcon_globals_ptr->z_true);
zval_ptr_dtor(&phalcon_globals_ptr->z_zero);
zval_ptr_dtor(&phalcon_globals_ptr->z_one);
}

phalcon_globals_ptr->initialized = 0;
}

static phalcon_memory_entry* phalcon_memory_grow_stack_common(zend_phalcon_globals *g)
{
assert(g->start_memory != NULL);
Expand Down Expand Up @@ -304,16 +418,27 @@ int phalcon_memory_restore_stack(const char *func TSRMLS_DC)
*/
void phalcon_memory_grow_stack(const char *func TSRMLS_DC)
{
phalcon_memory_entry *entry = phalcon_memory_grow_stack_common(PHALCON_VGLOBAL);
zend_phalcon_globals *g = PHALCON_VGLOBAL;
if (g->start_memory == NULL) {
phalcon_initialize_memory(g TSRMLS_CC);
}
phalcon_memory_entry *entry = phalcon_memory_grow_stack_common(g);
entry->func = func;
}

#else

/**
* Adds a memory frame in the current executed method
*/
void phalcon_memory_grow_stack(TSRMLS_D)
{
phalcon_memory_grow_stack_common(PHALCON_VGLOBAL);
zend_phalcon_globals *g = PHALCON_VGLOBAL;
if (g->start_memory == NULL) {
zend_error(E_ERROR, "Cannot use the memory manager when the request is shutting down");
return;
}
phalcon_memory_grow_stack_common(g);
}

/**
Expand Down
3 changes: 3 additions & 0 deletions ext/kernel/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include "php_phalcon.h"
#include "kernel/main.h"

void phalcon_initialize_memory(zend_phalcon_globals *phalcon_globals_ptr TSRMLS_DC);
void phalcon_deinitialize_memory(TSRMLS_D);

/* Memory Frames */
#ifndef PHALCON_RELEASE
void phalcon_dump_memory_frame(phalcon_memory_entry *active_memory TSRMLS_DC);
Expand Down
Loading

0 comments on commit 2a80399

Please sign in to comment.