Skip to content

Commit e10e151

Browse files
committed
Merged zend_array and HashTable into the single data structure.
Now each HashTable is also zend_array, so it's refcounted and may be a subject for Copy on Write zend_array_dup() was changed to allocate and return HashTable, instead of taking preallocated HashTable as argument.
1 parent bc630ad commit e10e151

40 files changed

+244
-261
lines changed

Zend/zend.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,9 @@ static zend_bool php_auto_globals_create_globals(zend_string *name) /* {{{ */
550550
zval globals;
551551

552552
ZVAL_ARR(&globals, &EG(symbol_table));
553+
Z_TYPE_INFO_P(&globals) = IS_ARRAY | (IS_TYPE_SYMBOLTABLE << Z_TYPE_FLAGS_SHIFT);
553554
ZVAL_NEW_REF(&globals, &globals);
554-
zend_hash_update(&EG(symbol_table).ht, name, &globals);
555+
zend_hash_update(&EG(symbol_table), name, &globals);
555556
return 0;
556557
}
557558
/* }}} */
@@ -1129,8 +1130,7 @@ static void zend_error_va_list(int type, const char *format, va_list args)
11291130
if (!symbol_table) {
11301131
ZVAL_NULL(&params[4]);
11311132
} else {
1132-
ZVAL_NEW_ARR(&params[4]);
1133-
zend_array_dup(Z_ARRVAL(params[4]), &symbol_table->ht);
1133+
ZVAL_ARR(&params[4], zend_array_dup(symbol_table));
11341134
}
11351135

11361136
ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));

Zend/zend_builtin_functions.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -1140,8 +1140,7 @@ ZEND_FUNCTION(get_object_vars)
11401140

11411141
if (!zobj->ce->default_properties_count && properties == zobj->properties) {
11421142
/* fast copy */
1143-
ZVAL_NEW_ARR(return_value);
1144-
zend_array_dup(Z_ARRVAL_P(return_value), properties);
1143+
ZVAL_ARR(return_value, zend_array_dup(properties));
11451144
} else {
11461145
array_init_size(return_value, zend_hash_num_elements(properties));
11471146

@@ -1883,8 +1882,7 @@ ZEND_FUNCTION(get_defined_vars)
18831882
{
18841883
zend_array *symbol_table = zend_rebuild_symbol_table();
18851884

1886-
ZVAL_NEW_ARR(return_value);
1887-
zend_array_dup(Z_ARRVAL_P(return_value), &symbol_table->ht);
1885+
ZVAL_ARR(return_value, zend_array_dup(symbol_table));
18881886
}
18891887
/* }}} */
18901888

Zend/zend_closures.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,7 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{
349349
if (closure->debug_info->u.v.nApplyCount == 0) {
350350
if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) {
351351
HashTable *static_variables = closure->func.op_array.static_variables;
352-
ZVAL_NEW_ARR(&val);
353-
zend_array_dup(Z_ARRVAL(val), static_variables);
352+
ZVAL_ARR(&val, zend_array_dup(static_variables));
354353
zend_hash_str_update(closure->debug_info, "static", sizeof("static")-1, &val);
355354
}
356355

Zend/zend_compile.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -865,10 +865,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
865865

866866
(*op_array->refcount)++;
867867
if (op_array->static_variables) {
868-
HashTable *static_variables = op_array->static_variables;
869-
870-
ALLOC_HASHTABLE(op_array->static_variables);
871-
zend_array_dup(op_array->static_variables, static_variables);
868+
op_array->static_variables = zend_array_dup(op_array->static_variables);
872869
}
873870
op_array->run_time_cache = NULL;
874871
} else if (function->type == ZEND_INTERNAL_FUNCTION) {

Zend/zend_execute.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,7 @@ static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_d
11621162

11631163
if (EXPECTED(fetch_type == ZEND_FETCH_GLOBAL_LOCK) ||
11641164
EXPECTED(fetch_type == ZEND_FETCH_GLOBAL)) {
1165-
ht = &EG(symbol_table).ht;
1165+
ht = &EG(symbol_table);
11661166
} else if (EXPECTED(fetch_type == ZEND_FETCH_STATIC)) {
11671167
ZEND_ASSERT(EX(func)->op_array.static_variables != NULL);
11681168
ht = EX(func)->op_array.static_variables;
@@ -1171,7 +1171,7 @@ static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_d
11711171
if (!EX(symbol_table)) {
11721172
zend_rebuild_symbol_table();
11731173
}
1174-
ht = &EX(symbol_table)->ht;
1174+
ht = EX(symbol_table);
11751175
}
11761176
return ht;
11771177
}
@@ -1687,12 +1687,12 @@ ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_val
16871687
ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table) /* {{{ */
16881688
{
16891689
if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
1690-
zend_array_destroy(&symbol_table->ht);
1690+
zend_array_destroy(symbol_table);
16911691
efree_size(symbol_table, sizeof(zend_array));
16921692
} else {
16931693
/* clean before putting into the cache, since clean
16941694
could call dtors, which could use cached hash */
1695-
zend_symtable_clean(&symbol_table->ht);
1695+
zend_symtable_clean(symbol_table);
16961696
*(++EG(symtable_cache_ptr)) = symbol_table;
16971697
}
16981698
}

Zend/zend_execute_API.c

+17-22
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,7 @@ void init_executor(void) /* {{{ */
152152

153153
zend_vm_stack_init();
154154

155-
zend_hash_init(&EG(symbol_table).ht, 64, NULL, ZVAL_PTR_DTOR, 0);
156-
GC_REFCOUNT(&EG(symbol_table)) = 1;
157-
GC_TYPE_INFO(&EG(symbol_table)) = IS_ARRAY;
155+
zend_hash_init(&EG(symbol_table), 64, NULL, ZVAL_PTR_DTOR, 0);
158156
EG(valid_symbol_table) = 1;
159157

160158
zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator);
@@ -218,14 +216,14 @@ static void zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */
218216
void shutdown_destructors(void) /* {{{ */
219217
{
220218
if (CG(unclean_shutdown)) {
221-
EG(symbol_table).ht.pDestructor = zend_unclean_zval_ptr_dtor;
219+
EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
222220
}
223221
zend_try {
224222
uint32_t symbols;
225223
do {
226-
symbols = zend_hash_num_elements(&EG(symbol_table).ht);
227-
zend_hash_reverse_apply(&EG(symbol_table).ht, (apply_func_t) zval_call_destructor);
228-
} while (symbols != zend_hash_num_elements(&EG(symbol_table).ht));
224+
symbols = zend_hash_num_elements(&EG(symbol_table));
225+
zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor);
226+
} while (symbols != zend_hash_num_elements(&EG(symbol_table)));
229227
zend_objects_store_call_destructors(&EG(objects_store));
230228
} zend_catch {
231229
/* if we couldn't destruct cleanly, mark all objects as destructed anyway */
@@ -259,9 +257,9 @@ void shutdown_executor(void) /* {{{ */
259257
zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);
260258

261259
if (CG(unclean_shutdown)) {
262-
EG(symbol_table).ht.pDestructor = zend_unclean_zval_ptr_dtor;
260+
EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
263261
}
264-
zend_hash_graceful_reverse_destroy(&EG(symbol_table).ht);
262+
zend_hash_graceful_reverse_destroy(&EG(symbol_table));
265263
} zend_end_try();
266264
EG(valid_symbol_table) = 0;
267265

@@ -349,7 +347,7 @@ void shutdown_executor(void) /* {{{ */
349347
}
350348

351349
while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
352-
zend_hash_destroy(&(*EG(symtable_cache_ptr))->ht);
350+
zend_hash_destroy(*EG(symtable_cache_ptr));
353351
FREE_HASHTABLE(*EG(symtable_cache_ptr));
354352
EG(symtable_cache_ptr)--;
355353
}
@@ -1417,7 +1415,7 @@ void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */
14171415

14181416
ZEND_API int zend_delete_global_variable(zend_string *name) /* {{{ */
14191417
{
1420-
return zend_hash_del_ind(&EG(symbol_table).ht, name);
1418+
return zend_hash_del_ind(&EG(symbol_table), name);
14211419
}
14221420
/* }}} */
14231421

@@ -1444,17 +1442,14 @@ ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */
14441442
symbol_table = ex->symbol_table = *(EG(symtable_cache_ptr)--);
14451443
} else {
14461444
symbol_table = ex->symbol_table = emalloc(sizeof(zend_array));
1447-
GC_REFCOUNT(symbol_table) = 0;
1448-
GC_TYPE_INFO(symbol_table) = IS_ARRAY;
1449-
zend_hash_init(&symbol_table->ht, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0);
1445+
zend_hash_init(symbol_table, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0);
14501446
/*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
14511447
}
14521448
for (i = 0; i < ex->func->op_array.last_var; i++) {
14531449
zval zv;
14541450

14551451
ZVAL_INDIRECT(&zv, ZEND_CALL_VAR_NUM(ex, i));
1456-
zend_hash_add_new(&symbol_table->ht,
1457-
ex->func->op_array.vars[i], &zv);
1452+
zend_hash_add_new(symbol_table, ex->func->op_array.vars[i], &zv);
14581453
}
14591454
return symbol_table;
14601455
}
@@ -1464,7 +1459,7 @@ ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ *
14641459
{
14651460
int i;
14661461
zend_op_array *op_array = &execute_data->func->op_array;
1467-
HashTable *ht = &execute_data->symbol_table->ht;
1462+
HashTable *ht = execute_data->symbol_table;
14681463

14691464
/* copy real values from symbol table into CV slots and create
14701465
INDIRECT references to CV in symbol table */
@@ -1492,7 +1487,7 @@ ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ *
14921487
{
14931488
int i;
14941489
zend_op_array *op_array = &execute_data->func->op_array;
1495-
HashTable *ht = &execute_data->symbol_table->ht;
1490+
HashTable *ht = execute_data->symbol_table;
14961491

14971492
/* copy real values from CV slots into symbol table */
14981493
for (i = 0; i < op_array->last_var; i++) {
@@ -1531,11 +1526,11 @@ ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force) /* {{
15311526
if (force) {
15321527
zend_array *symbol_table = zend_rebuild_symbol_table();
15331528
if (symbol_table) {
1534-
return zend_hash_update(&symbol_table->ht, name, value) ? SUCCESS : FAILURE;;
1529+
return zend_hash_update(symbol_table, name, value) ? SUCCESS : FAILURE;;
15351530
}
15361531
}
15371532
} else {
1538-
return (zend_hash_update_ind(&execute_data->symbol_table->ht, name, value) != NULL) ? SUCCESS : FAILURE;
1533+
return (zend_hash_update_ind(execute_data->symbol_table, name, value) != NULL) ? SUCCESS : FAILURE;
15391534
}
15401535
}
15411536
return FAILURE;
@@ -1569,11 +1564,11 @@ ZEND_API int zend_set_local_var_str(const char *name, size_t len, zval *value, i
15691564
if (force) {
15701565
zend_array *symbol_table = zend_rebuild_symbol_table();
15711566
if (symbol_table) {
1572-
return zend_hash_str_update(&symbol_table->ht, name, len, value) ? SUCCESS : FAILURE;;
1567+
return zend_hash_str_update(symbol_table, name, len, value) ? SUCCESS : FAILURE;;
15731568
}
15741569
}
15751570
} else {
1576-
return (zend_hash_str_update_ind(&execute_data->symbol_table->ht, name, len, value) != NULL) ? SUCCESS : FAILURE;
1571+
return (zend_hash_str_update_ind(execute_data->symbol_table, name, len, value) != NULL) ? SUCCESS : FAILURE;
15771572
}
15781573
}
15791574
return FAILURE;

Zend/zend_gc.c

+16-33
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,7 @@ static void gc_scan_black(zend_refcounted *ref)
231231
for (i = 0; i < n; i++) {
232232
if (Z_REFCOUNTED(table[i])) {
233233
ref = Z_COUNTED(table[i]);
234-
if (GC_TYPE(ref) != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
235-
GC_REFCOUNT(ref)++;
236-
}
234+
GC_REFCOUNT(ref)++;
237235
if (GC_GET_COLOR(GC_INFO(ref)) != GC_BLACK) {
238236
if (!props && i == n - 1) {
239237
goto tail_call;
@@ -250,14 +248,12 @@ static void gc_scan_black(zend_refcounted *ref)
250248
}
251249
} else if (GC_TYPE(ref) == IS_ARRAY) {
252250
if ((zend_array*)ref != &EG(symbol_table)) {
253-
ht = &((zend_array*)ref)->ht;
251+
ht = (zend_array*)ref;
254252
}
255253
} else if (GC_TYPE(ref) == IS_REFERENCE) {
256254
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
257255
ref = Z_COUNTED(((zend_reference*)ref)->val);
258-
if (GC_TYPE(ref) != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
259-
GC_REFCOUNT(ref)++;
260-
}
256+
GC_REFCOUNT(ref)++;
261257
if (GC_GET_COLOR(GC_INFO(ref)) != GC_BLACK) {
262258
goto tail_call;
263259
}
@@ -269,9 +265,7 @@ static void gc_scan_black(zend_refcounted *ref)
269265
p = ht->arData + idx;
270266
if (!Z_REFCOUNTED(p->val)) continue;
271267
ref = Z_COUNTED(p->val);
272-
if (GC_TYPE(ref) != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
273-
GC_REFCOUNT(ref)++;
274-
}
268+
GC_REFCOUNT(ref)++;
275269
if (GC_GET_COLOR(GC_INFO(ref)) != GC_BLACK) {
276270
if (idx == ht->nNumUsed-1) {
277271
goto tail_call;
@@ -312,9 +306,7 @@ static void gc_mark_grey(zend_refcounted *ref)
312306
for (i = 0; i < n; i++) {
313307
if (Z_REFCOUNTED(table[i])) {
314308
ref = Z_COUNTED(table[i]);
315-
if (GC_TYPE(ref) != IS_ARRAY || ((zend_array*)ref) != &EG(symbol_table)) {
316-
GC_REFCOUNT(ref)--;
317-
}
309+
GC_REFCOUNT(ref)--;
318310
if (!props && i == n - 1) {
319311
goto tail_call;
320312
} else {
@@ -331,7 +323,7 @@ static void gc_mark_grey(zend_refcounted *ref)
331323
if (((zend_array*)ref) == &EG(symbol_table)) {
332324
GC_SET_BLACK(GC_INFO(ref));
333325
} else {
334-
ht = &((zend_array*)ref)->ht;
326+
ht = (zend_array*)ref;
335327
}
336328
} else if (GC_TYPE(ref) == IS_REFERENCE) {
337329
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
@@ -341,9 +333,7 @@ static void gc_mark_grey(zend_refcounted *ref)
341333
return;
342334
}
343335
ref = Z_COUNTED(((zend_reference*)ref)->val);
344-
if (GC_TYPE(ref) != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
345-
GC_REFCOUNT(ref)--;
346-
}
336+
GC_REFCOUNT(ref)--;
347337
goto tail_call;
348338
}
349339
return;
@@ -358,9 +348,7 @@ static void gc_mark_grey(zend_refcounted *ref)
358348
continue;
359349
}
360350
ref = Z_COUNTED(p->val);
361-
if (GC_TYPE(ref) != IS_ARRAY || ((zend_array*)ref) != &EG(symbol_table)) {
362-
GC_REFCOUNT(ref)--;
363-
}
351+
GC_REFCOUNT(ref)--;
364352
if (idx == ht->nNumUsed-1) {
365353
goto tail_call;
366354
} else {
@@ -428,7 +416,7 @@ static void gc_scan(zend_refcounted *ref)
428416
if ((zend_array*)ref == &EG(symbol_table)) {
429417
GC_SET_BLACK(GC_INFO(ref));
430418
} else {
431-
ht = &((zend_array*)ref)->ht;
419+
ht = (zend_array*)ref;
432420
}
433421
} else if (GC_TYPE(ref) == IS_REFERENCE) {
434422
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
@@ -529,9 +517,7 @@ static int gc_collect_white(zend_refcounted *ref)
529517
for (i = 0; i < n; i++) {
530518
if (Z_REFCOUNTED(table[i])) {
531519
ref = Z_COUNTED(table[i]);
532-
if (GC_TYPE(ref) != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
533-
GC_REFCOUNT(ref)++;
534-
}
520+
GC_REFCOUNT(ref)++;
535521
if (!props && i == n - 1) {
536522
goto tail_call;
537523
} else {
@@ -548,13 +534,11 @@ static int gc_collect_white(zend_refcounted *ref)
548534
ht = props;
549535
}
550536
} else if (GC_TYPE(ref) == IS_ARRAY) {
551-
ht = &((zend_array*)ref)->ht;
537+
ht = (zend_array*)ref;
552538
} else if (GC_TYPE(ref) == IS_REFERENCE) {
553539
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
554540
ref = Z_COUNTED(((zend_reference*)ref)->val);
555-
if (GC_TYPE(ref) != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
556-
GC_REFCOUNT(ref)++;
557-
}
541+
GC_REFCOUNT(ref)++;
558542
goto tail_call;
559543
}
560544
return count;
@@ -571,9 +555,7 @@ static int gc_collect_white(zend_refcounted *ref)
571555
continue;
572556
}
573557
ref = Z_COUNTED(p->val);
574-
if (GC_TYPE(ref) != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
575-
GC_REFCOUNT(ref)++;
576-
}
558+
GC_REFCOUNT(ref)++;
577559
if (idx == ht->nNumUsed-1) {
578560
goto tail_call;
579561
} else {
@@ -681,7 +663,7 @@ static void gc_remove_nested_data_from_buffer(zend_refcounted *ref)
681663
ht = props;
682664
}
683665
} else if (GC_TYPE(ref) == IS_ARRAY) {
684-
ht = &((zend_array*)ref)->ht;
666+
ht = (zend_array*)ref;
685667
} else if (GC_TYPE(ref) == IS_REFERENCE) {
686668
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
687669
ref = Z_COUNTED(((zend_reference*)ref)->val);
@@ -802,8 +784,9 @@ ZEND_API int zend_gc_collect_cycles(void)
802784
} else if (GC_TYPE(p) == IS_ARRAY) {
803785
zend_array *arr = (zend_array*)p;
804786

787+
GC_REFCOUNT(arr) = 0;
805788
GC_TYPE(arr) = IS_NULL;
806-
zend_hash_destroy(&arr->ht);
789+
zend_hash_destroy(arr);
807790
}
808791
current = GC_G(next_to_free);
809792
}

0 commit comments

Comments
 (0)