Skip to content

Commit

Permalink
fix #64
Browse files Browse the repository at this point in the history
  • Loading branch information
krakjoe committed May 18, 2024
1 parent 6923741 commit 67413b1
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 5 deletions.
17 changes: 17 additions & 0 deletions src/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -692,9 692,16 @@ static zend_always_inline zend_bool php_parallel_check_object(zend_object *objec
*end = property object->ce->default_properties_count;

while (property < end) {
if ((Z_TYPE_P(property) == IS_OBJECT) &&
(Z_OBJ_P(property) == object)) {
property ;
continue;
}

if (!php_parallel_check_zval(property, error)) {
return 0;
}

property ;
}
}
Expand All @@ -703,6 710,11 @@ static zend_always_inline zend_bool php_parallel_check_object(zend_object *objec
zval *property;

ZEND_HASH_FOREACH_VAL(object->properties, property) {
if ((Z_TYPE_P(property) == IS_OBJECT) &&
(Z_OBJ_P(property) == object)) {
continue;
}

if (!php_parallel_check_zval(property, error)) {
return 0;
}
Expand Down Expand Up @@ -747,6 759,11 @@ zend_bool php_parallel_check_zval(zval *zv, zval **error) { /* {{{ */
zval *el;

ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zv), el) {
if ((Z_TYPE_P(el) == IS_ARRAY) &&
(Z_ARRVAL_P(el) == Z_ARRVAL_P(zv))) {
continue;
}

if (!php_parallel_check_zval(el, error)) {
if (error) {
*error = el;
Expand Down
130 changes: 125 additions & 5 deletions src/copy.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 26,7 @@
TSRM_TLS struct {
HashTable scope;
zval unavailable;
php_parallel_copy_context_t *context;
} php_parallel_copy_globals;

static struct {
Expand Down Expand Up @@ -173,9 174,25 @@ static zend_always_inline HashTable* php_parallel_copy_hash_persistent_inline(
HashTable *source,
zend_string* (*php_parallel_copy_string_func)(zend_string*),
void* (*php_parallel_copy_memory_func)(void *source, zend_long size)) {
HashTable *ht = php_parallel_copy_memory_func(source, sizeof(HashTable));
HashTable *ht;
uint32_t idx;

php_parallel_copy_context_t *context, *restore;

context = php_parallel_copy_context_start(
PHP_PARALLEL_COPY_DIRECTION_PERSISTENT,
&restore);

if ((ht = php_parallel_copy_context_find(context, source))) {
GC_ADDREF(ht);
php_parallel_copy_context_end(context, restore);
return ht;
} else {
ht = php_parallel_copy_memory_func(source, sizeof(HashTable));
php_parallel_copy_context_insert(
context, source, ht);
}

GC_SET_REFCOUNT(ht, 2);
GC_SET_PERSISTENT_TYPE(ht, GC_ARRAY);
GC_ADD_FLAGS(ht, IS_ARRAY_IMMUTABLE);
Expand All @@ -188,6 205,7 @@ static zend_always_inline HashTable* php_parallel_copy_hash_persistent_inline(
ht->nNextFreeElement = 0;
ht->nTableMask = HT_MIN_MASK;
HT_SET_DATA_ADDR(ht, &php_parallel_copy_uninitialized_bucket);
php_parallel_copy_context_end(context, restore);
return ht;
}

Expand All @@ -211,6 229,7 @@ static zend_always_inline HashTable* php_parallel_copy_hash_persistent_inline(
}
}
ht->nNextFreeElement = ht->nNumUsed;
php_parallel_copy_context_end(context, restore);
return ht;
}
#endif
Expand Down Expand Up @@ -240,12 259,29 @@ static zend_always_inline HashTable* php_parallel_copy_hash_persistent_inline(
php_parallel_copy_memory_func);
}
}

php_parallel_copy_context_end(context, restore);
return ht;
}

static zend_always_inline HashTable* php_parallel_copy_hash_thread(HashTable *source) {
HashTable *ht = php_parallel_copy_mem(source, sizeof(HashTable), 0);
HashTable *ht;

php_parallel_copy_context_t *context, *restore;

context = php_parallel_copy_context_start(
PHP_PARALLEL_COPY_DIRECTION_THREAD,
&restore);

if ((ht = php_parallel_copy_context_find(context, source))) {
GC_ADDREF(ht);
php_parallel_copy_context_end(
context, restore);
return ht;
} else {
ht = php_parallel_copy_mem(source, sizeof(HashTable), 0);
php_parallel_copy_context_insert(
context, source, ht);
}

GC_SET_REFCOUNT(ht, 1);
GC_DEL_FLAGS(ht, IS_ARRAY_IMMUTABLE);
Expand All @@ -256,6 292,7 @@ static zend_always_inline HashTable* php_parallel_copy_hash_thread(HashTable *so

if (ht->nNumUsed == 0) {
HT_SET_DATA_ADDR(ht, &php_parallel_copy_uninitialized_bucket);
php_parallel_copy_context_end(context, restore);
return ht;
}

Expand Down Expand Up @@ -311,6 348,7 @@ static zend_always_inline HashTable* php_parallel_copy_hash_thread(HashTable *so
}
}

php_parallel_copy_context_end(context, restore);
return ht;
}

Expand Down Expand Up @@ -689,9 727,23 @@ static zend_always_inline zend_object* php_parallel_copy_object_persistent(zend_
ce = source->ce;
}

dest = php_parallel_copy_mem(
php_parallel_copy_context_t *context, *restore;

context = php_parallel_copy_context_start(
PHP_PARALLEL_COPY_DIRECTION_PERSISTENT,
&restore);

if ((dest = php_parallel_copy_context_find(context, source))) {
GC_ADDREF(dest);
php_parallel_copy_context_end(context, restore);
return dest;
} else {
dest = php_parallel_copy_mem(
source,
sizeof(zend_object) zend_object_properties_size(ce), 1);
php_parallel_copy_context_insert(
context, source, dest);
}

GC_SET_REFCOUNT(dest, 1);
GC_ADD_FLAGS(dest, GC_IMMUTABLE);
Expand All @@ -718,6 770,7 @@ static zend_always_inline zend_object* php_parallel_copy_object_persistent(zend_
php_parallel_copy_hash_ctor(source->properties, 1);
}

php_parallel_copy_context_end(context, restore);
return dest;
}

Expand All @@ -731,9 784,23 @@ static zend_always_inline zend_object* php_parallel_copy_object_thread(zend_obje
ce = php_parallel_copy_scope(source->ce);
}

dest = php_parallel_copy_mem(
php_parallel_copy_context_t *context, *restore;

context = php_parallel_copy_context_start(
PHP_PARALLEL_COPY_DIRECTION_THREAD,
&restore);

if ((dest = php_parallel_copy_context_find(context, source))) {
GC_ADDREF(dest);
php_parallel_copy_context_end(context, restore);
return dest;
} else {
dest = php_parallel_copy_mem(
source,
sizeof(zend_object) zend_object_properties_size(ce), 0);
php_parallel_copy_context_insert(
context, source, dest);
}

if (ce == php_parallel_copy_object_unavailable_ce) {
dest->ce = ce;
Expand Down Expand Up @@ -761,6 828,7 @@ static zend_always_inline zend_object* php_parallel_copy_object_thread(zend_obje
php_parallel_copy_hash_ctor(source->properties, 0);
}

php_parallel_copy_context_end(context, restore);
return dest;
}

Expand Down Expand Up @@ -805,6 873,10 @@ static zend_always_inline void php_parallel_copy_object_dtor(zend_object *source
return;
}

if (GC_DELREF(source)) {
return;
}

if (source->ce->default_properties_count) {
zval *property = source->properties_table,
*end = property source->ce->default_properties_count;
Expand Down Expand Up @@ -908,6 980,52 @@ zend_function* php_parallel_copy_function(const zend_function *function, zend_bo
return (zend_function*) function;
}

php_parallel_copy_context_t* php_parallel_copy_context_start(
php_parallel_copy_direction_t direction,
php_parallel_copy_context_t **previous) {

if (PCG(context) &&
PCG(context)->direction == direction) {
php_parallel_atomic_addref(
&PCG(context)->refcount);
return *previous = PCG(context);
}

*previous = PCG(context);

PCG(context) =
(php_parallel_copy_context_t*)
pemalloc(sizeof(php_parallel_copy_context_t), 1);
zend_hash_init(
&PCG(context)->copied, 32, NULL, NULL, 1);
PCG(context)->refcount = 1;
PCG(context)->direction = direction;

return PCG(context);
}

void* php_parallel_copy_context_find(php_parallel_copy_context_t *context, void *address) {
return zend_hash_index_find_ptr(&context->copied, (zend_ulong) address);
}

void php_parallel_copy_context_insert(php_parallel_copy_context_t *context, void *address, void *assigned) {
zend_hash_index_update_ptr(
&context->copied, (zend_ulong) address, assigned);
}

void php_parallel_copy_context_end(
php_parallel_copy_context_t *context,
php_parallel_copy_context_t *previous) {

if (php_parallel_atomic_delref(&context->refcount) == 0) {
zend_hash_destroy(
&context->copied);
pefree(context, 1);
}

PCG(context) = previous;
}

PHP_RINIT_FUNCTION(PARALLEL_COPY)
{
zend_hash_init(&PCG(scope), 32, NULL, NULL, 0);
Expand All @@ -917,6 1035,8 @@ PHP_RINIT_FUNCTION(PARALLEL_COPY)

object_init_ex(&PCG(unavailable), php_parallel_copy_object_unavailable_ce);

PCG(context) = NULL;

return SUCCESS;
}

Expand Down
20 changes: 20 additions & 0 deletions src/copy.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 69,26 @@ void php_parallel_copy_zval_dtor(zval *zv);

zend_class_entry* php_parallel_copy_scope(zend_class_entry *);

typedef enum _php_parallel_copy_direction_t {
PHP_PARALLEL_COPY_DIRECTION_PERSISTENT,
PHP_PARALLEL_COPY_DIRECTION_THREAD,
} php_parallel_copy_direction_t;

typedef struct _php_parallel_copy_context_t {
php_parallel_copy_direction_t direction;
HashTable copied;
uint32_t refcount;
} php_parallel_copy_context_t;

php_parallel_copy_context_t* php_parallel_copy_context_start(
php_parallel_copy_direction_t direction,
php_parallel_copy_context_t **previous);
void* php_parallel_copy_context_find(php_parallel_copy_context_t *context, void *address);
void php_parallel_copy_context_insert(php_parallel_copy_context_t *context, void *address, void *assigned);
void php_parallel_copy_context_end(
php_parallel_copy_context_t *context,
php_parallel_copy_context_t *previous);

PHP_RINIT_FUNCTION(PARALLEL_COPY);
PHP_RSHUTDOWN_FUNCTION(PARALLEL_COPY);

Expand Down
15 changes: 15 additions & 0 deletions src/scheduler.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 136,11 @@ static zend_always_inline void php_parallel_scheduler_add(
zval *slot = ZEND_CALL_ARG(frame, 1);
zval *param;
uint32_t argc = 0;
php_parallel_copy_context_t *context, *restore;

context = php_parallel_copy_context_start(
PHP_PARALLEL_COPY_DIRECTION_PERSISTENT,
&restore);

ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(argv), param) {
PARALLEL_ZVAL_COPY(slot, param, 1);
Expand All @@ -144,6 149,8 @@ static zend_always_inline void php_parallel_scheduler_add(
} ZEND_HASH_FOREACH_END();

ZEND_CALL_NUM_ARGS(frame) = argc;

php_parallel_copy_context_end(context, restore);
} else {
ZEND_CALL_NUM_ARGS(frame) = 0;
}
Expand Down Expand Up @@ -286,11 293,19 @@ static zend_always_inline zend_bool php_parallel_scheduler_pop(php_parallel_runt
*end = slot ZEND_CALL_NUM_ARGS(head->frame);
zval *param = ZEND_CALL_ARG(el->frame, 1);

php_parallel_copy_context_t *context, *restore;

context = php_parallel_copy_context_start(
PHP_PARALLEL_COPY_DIRECTION_THREAD,
&restore);

while (slot < end) {
PARALLEL_ZVAL_COPY(param, slot, 0);
slot ;
param ;
}

php_parallel_copy_context_end(context, restore);
}

zend_init_func_execute_data(
Expand Down

0 comments on commit 67413b1

Please sign in to comment.