• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

krakjoe / parallel / 29339248987

14 Jul 2026 02:04PM UTC coverage: 95.347% (+0.3%) from 95.095%
29339248987

Pull #387

github

web-flow
Merge b1448f8d0 into 0aece3ef3
Pull Request #387: Link task functions in destination runtimes

134 of 141 new or added lines in 2 files covered. (95.04%)

45 existing lines in 2 files now uncovered.

2992 of 3138 relevant lines covered (95.35%)

5694.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.34
/src/cache.c
1
/*
2
  +----------------------------------------------------------------------+
3
  | parallel                                                             |
4
  +----------------------------------------------------------------------+
5
  | Copyright (c) Joe Watkins 2019-2024                                  |
6
  +----------------------------------------------------------------------+
7
  | This source file is subject to version 3.01 of the PHP license,      |
8
  | that is bundled with this package in the file LICENSE, and is        |
9
  | available through the world-wide-web at the following url:           |
10
  | http://www.php.net/license/3_01.txt                                  |
11
  | If you did not receive a copy of the PHP license and are unable to   |
12
  | obtain it through the world-wide-web, please send a note to          |
13
  | license@php.net so we can mail you a copy immediately.               |
14
  +----------------------------------------------------------------------+
15
  | Author: krakjoe                                                      |
16
  +----------------------------------------------------------------------+
17
 */
18
#ifndef HAVE_PARALLEL_CACHE
19
#define HAVE_PARALLEL_CACHE
20

21
#include "parallel.h"
22

23
static struct {
24
        pthread_mutex_t mutex;
25
        HashTable       functions;
26
        HashTable       identities;
27
#if PHP_VERSION_ID < 80200
28
        HashTable statics;
29
#endif
30
        struct {
31
                size_t size;
32
                size_t used;
33
                void  *mem;
34
                void  *block;
35
        } memory;
36
} php_parallel_cache_globals = {PTHREAD_MUTEX_INITIALIZER};
37

38
#define PCG(e) php_parallel_cache_globals.e
39
#define PCM(e) PCG(memory).e
40

41
#define PARALLEL_CACHE_CHUNK PARALLEL_PLATFORM_ALIGNED((1024 * 1024) * 8)
42
#define PARALLEL_CACHE_FILE_HASH_OFFSET 1469598103934665603ULL
43
#define PARALLEL_CACHE_FILE_HASH_PRIME 1099511628211ULL
44

45
#if PHP_VERSION_ID < 80200
46
#define PARALLEL_CACHE_STATICS_PARAM , bool statics
47
#define PARALLEL_CACHE_STATICS_ARG(value) , value
48
#else
49
#define PARALLEL_CACHE_STATICS_PARAM
50
#define PARALLEL_CACHE_STATICS_ARG(value)
51
#endif
52

53
typedef struct _php_parallel_cache_entry_t {
54
        zend_op_array *function;
55
#if PHP_VERSION_ID >= 80400
56
        uint64_t source;
57
#endif
58
} php_parallel_cache_entry_t;
59

60
typedef struct _php_parallel_cache_identity_t {
61
        const zend_op *opcodes;
62
        zend_string   *filename;
63
        zif_handler    handler;
64
        uint32_t       line_start;
65
        uint32_t       line_end;
66
        uint8_t        type;
67
} php_parallel_cache_identity_t;
68

69
/* {{{ */
70
static zend_always_inline void *php_parallel_cache_alloc(size_t size)
9,675✔
71
{
72
        void  *mem;
9,675✔
73
        size_t aligned = PARALLEL_PLATFORM_ALIGNED(size);
9,675✔
74

75
        ZEND_ASSERT(size < PARALLEL_CACHE_CHUNK);
9,675✔
76

77
        if ((PCM(used) + aligned) >= PCM(size)) {
9,675✔
UNCOV
78
                PCM(size) = PARALLEL_PLATFORM_ALIGNED(PCM(size) + PARALLEL_CACHE_CHUNK);
×
UNCOV
79
                PCM(mem) = (void *)realloc(PCM(mem), PCM(size));
×
80

UNCOV
81
                if (!PCM(mem)) {
×
82
                        /* out of memory */
83
                        return NULL;
84
                }
85

UNCOV
86
                PCM(block) = (void *)(((char *)PCM(mem)) + PCM(used));
×
87
        }
88

89
        mem = PCM(block);
9,675✔
90
        PCM(block) = (void *)(((char *)PCM(block)) + aligned);
9,675✔
91
        PCM(used) += aligned;
9,675✔
92

93
        return mem;
9,675✔
94
}
95

96
static zend_always_inline void *php_parallel_cache_copy_mem(void *source, zend_long size)
4,574✔
97
{
98
        void *destination = php_parallel_cache_alloc(size);
126✔
99

100
        memcpy(destination, source, size);
4,448✔
101

102
        return destination;
4,574✔
103
} /* }}} */
104

105
#if PHP_VERSION_ID >= 80400
106
static zend_always_inline uint64_t php_parallel_cache_file_hash(const zend_op_array *source)
1,144✔
107
{ /* {{{ */
108
        FILE    *file;
1,144✔
109
        uint64_t hash = PARALLEL_CACHE_FILE_HASH_OFFSET;
1,144✔
110
        char     buffer[4096];
1,144✔
111
        size_t   read;
1,144✔
112

113
        if (!source->filename) {
1,144✔
114
                return 0;
115
        }
116

117
        file = VCWD_FOPEN(ZSTR_VAL(source->filename), "rb");
1,144✔
118
        if (!file) {
1,144✔
119
                return 0;
120
        }
121

122
        while ((read = fread(buffer, 1, sizeof(buffer), file)) > 0) {
2,288✔
123
                char *it = buffer, *end = buffer + read;
1,144✔
124

125
                while (it < end) {
603,812✔
126
                        hash ^= (unsigned char)*it++;
602,668✔
127
                        hash *= PARALLEL_CACHE_FILE_HASH_PRIME;
602,668✔
128
                }
129
        }
130

131
        fclose(file);
1,144✔
132

133
        return hash;
1,144✔
134
} /* }}} */
135
#endif
136

137
#if PHP_VERSION_ID < 80200
138
static zend_always_inline HashTable *php_parallel_cache_statics(HashTable *statics)
24✔
139
{ /* {{{ */
140
        HashTable *cached = zend_hash_index_find_ptr(&PCG(statics), (zend_ulong)statics);
48✔
141

142
        if (cached) {
143
                return cached;
144
        }
145

146
        cached = php_parallel_copy_hash_persistent(statics, php_parallel_copy_string_interned, php_parallel_cache_copy_mem,
24✔
147
                                                   PHP_PARALLEL_COPY_STORAGE_CACHE_POOL);
148

149
        return zend_hash_index_update_ptr(&PCG(statics), (zend_ulong)statics, cached);
24✔
150
} /* }}} */
151
#endif
152

153
static zend_always_inline void php_parallel_cache_identities(const zend_function *source, const zend_function *cached)
2,832✔
154
{ /* {{{ */
155
        const zend_op *source_opline = source->op_array.opcodes;
2,832✔
156
        const zend_op *cached_opline = cached->op_array.opcodes;
2,832✔
157
        const zend_op *end = source_opline + source->op_array.last;
2,832✔
158

159
        while (source_opline < end) {
20,014✔
160
                if (source_opline->opcode == ZEND_INIT_FCALL) {
17,182✔
161
                        zend_function *function = zend_fetch_function(Z_STR_P(RT_CONSTANT(source_opline, source_opline->op2)));
913✔
162

163
                        if (function) {
913✔
164
                                php_parallel_cache_identity_t *identity = php_parallel_cache_alloc(sizeof(*identity));
913✔
165

166
                                memset(identity, 0, sizeof(*identity));
913✔
167
                                identity->type = function->type;
913✔
168

169
                                if (ZEND_USER_CODE(function->type)) {
913✔
170
                                        identity->opcodes = function->op_array.opcodes;
165✔
171
                                        identity->filename = function->op_array.filename
330✔
172
                                                                 ? php_parallel_copy_string_interned(function->op_array.filename)
165✔
173
                                                                 : NULL;
165✔
174
                                        identity->line_start = function->op_array.line_start;
165✔
175
                                        identity->line_end = function->op_array.line_end;
165✔
176
                                } else {
177
                                        identity->handler = function->internal_function.handler;
748✔
178
                                }
179

180
                                zend_hash_index_update_ptr(&PCG(identities), (zend_ulong)cached_opline, identity);
913✔
181
                        }
182
                }
183

184
                source_opline++;
17,182✔
185
                cached_opline++;
17,182✔
186
        }
187
} /* }}} */
188

189
bool php_parallel_cache_function_matches(const zend_op *opline, const zend_function *function,
724✔
190
                                         php_parallel_cache_function_source_t *source)
191
{ /* {{{ */
192
        php_parallel_cache_identity_t *identity;
724✔
193
        bool                           matches = false;
724✔
194

195
        pthread_mutex_lock(&PCG(mutex));
724✔
196
        identity = zend_hash_index_find_ptr(&PCG(identities), (zend_ulong)opline);
724✔
197
        pthread_mutex_unlock(&PCG(mutex));
724✔
198

199
        if (!identity) {
724✔
200
                return false;
201
        }
202

203
        source->filename = identity->filename;
724✔
204
        source->line = identity->line_start;
724✔
205

206
        if (ZEND_USER_CODE(identity->type)) {
724✔
207
                matches =
42✔
208
                    ZEND_USER_CODE(function->type) && (identity->opcodes == function->op_array.opcodes ||
42✔
209
                                                       (identity->filename && function->op_array.filename &&
42✔
210
                                                        zend_string_equals(identity->filename, function->op_array.filename) &&
84✔
211
                                                        identity->line_start == function->op_array.line_start &&
24✔
212
                                                        identity->line_end == function->op_array.line_end));
213
        } else {
214
                matches = function->type == identity->type && function->internal_function.handler == identity->handler;
682✔
215
        }
216

217
        return matches;
218
} /* }}} */
219

220
static zend_always_inline void php_parallel_cache_type(zend_type *type)
376✔
221
{ /* {{{ */
222
        zend_type *single;
376✔
223

224
        if (!ZEND_TYPE_IS_SET(*type)) {
376✔
225
                return;
226
        }
227

228
        if (ZEND_TYPE_HAS_LIST(*type)) {
260✔
229
                zend_type_list *list = ZEND_TYPE_LIST(*type);
6✔
230

231
                list = php_parallel_cache_copy_mem(list, ZEND_TYPE_LIST_SIZE(list->num_types));
6✔
232

233
                if (ZEND_TYPE_USES_ARENA(*type)) {
6✔
234
                        ZEND_TYPE_FULL_MASK(*type) &= ~_ZEND_TYPE_ARENA_BIT;
5✔
235
                }
236

237
                ZEND_TYPE_SET_PTR(*type, list);
6✔
238
        }
239

240
        ZEND_TYPE_FOREACH(*type, single)
260✔
241
        {
242
                if (ZEND_TYPE_HAS_NAME(*single)) {
266✔
243
                        zend_string *name = ZEND_TYPE_NAME(*single);
98✔
244

245
                        ZEND_TYPE_SET_PTR(*single, php_parallel_copy_string_interned(name));
98✔
246
                }
247
        }
248
        ZEND_TYPE_FOREACH_END();
266✔
249
} /* }}} */
250

251
/* {{{ */
252
static zend_op_array *php_parallel_cache_create(const zend_function *source PARALLEL_CACHE_STATICS_PARAM)
2,832✔
253
{
254
        zend_op_array *cached = php_parallel_cache_copy_mem((void *)source, sizeof(zend_op_array));
2,832✔
255
        bool           shared = cached->refcount == NULL;
2,832✔
256

257
        cached->fn_flags |= ZEND_ACC_IMMUTABLE;
2,832✔
258

259
#if PHP_VERSION_ID < 80200
260
        if (statics && cached->static_variables) {
894✔
261
                cached->static_variables = php_parallel_cache_statics(cached->static_variables);
48✔
262
        }
263
#endif
264

265
#if PHP_VERSION_ID >= 80200
266
        ZEND_MAP_PTR_INIT(cached->static_variables_ptr, cached->static_variables);
1,938✔
267
#else
268
        ZEND_MAP_PTR_INIT(cached->static_variables_ptr, &cached->static_variables);
894✔
269
#endif
270

271
        ZEND_MAP_PTR_INIT(cached->run_time_cache, NULL);
2,832✔
272

273
#if PHP_VERSION_ID >= 80100
274
        if (cached->num_dynamic_func_defs) {
2,412✔
275
                uint32_t it = 0;
195✔
276

277
                cached->dynamic_func_defs = php_parallel_cache_copy_mem(
390✔
278
                    cached->dynamic_func_defs, sizeof(zend_op_array *) * cached->num_dynamic_func_defs);
195✔
279

280
                while (it < cached->num_dynamic_func_defs) {
420✔
281
                        cached->dynamic_func_defs[it] = (zend_op_array *)php_parallel_cache_create(
450✔
282
                            (zend_function *)cached->dynamic_func_defs[it] PARALLEL_CACHE_STATICS_ARG(statics));
225✔
283
                        it++;
225✔
284
                }
285
        }
286
#endif
287

288
        if (shared) {
2,832✔
289
                php_parallel_cache_identities(source, (zend_function *)cached);
1,870✔
290
                goto _php_parallel_cached_function_return;
1,870✔
291
        }
292

293
        cached->refcount = NULL;
962✔
294

295
        if (cached->last_literal) {
962✔
296
                zval *literal = source->op_array.literals, *end = literal + cached->last_literal;
962✔
297
                zval *slot = php_parallel_cache_alloc(sizeof(zval) * cached->last_literal);
962✔
298

299
                cached->literals = slot;
962✔
300

301
                while (literal < end) {
4,597✔
302
                        if (Z_TYPE_P(literal) == IS_ARRAY) {
3,635✔
303
                                ZVAL_ARR(slot, php_parallel_copy_hash_persistent(Z_ARRVAL_P(literal), php_parallel_copy_string_interned,
42✔
304
                                                                                 php_parallel_cache_copy_mem,
305
                                                                                 PHP_PARALLEL_COPY_STORAGE_CACHE_POOL));
306
                        } else if (Z_TYPE_P(literal) == IS_STRING) {
3,593✔
307
                                ZVAL_STR(slot, php_parallel_copy_string_interned(Z_STR_P(literal)));
2,062✔
308
                        } else {
309
                                *slot = *literal;
1,531✔
310
                        }
311

312
                        Z_TYPE_FLAGS_P(slot) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COLLECTABLE);
3,635✔
313
                        literal++;
3,635✔
314
                        slot++;
3,635✔
315
                }
316
        }
317

318
        if (cached->last) {
962✔
319
                zend_op *opcodes = php_parallel_cache_copy_mem(cached->opcodes, sizeof(zend_op) * cached->last);
962✔
320
                zend_op *opline = opcodes, *end = opline + cached->last;
962✔
321

322
                while (opline < end) {
7,222✔
323
                        if (opline->op1_type == IS_CONST) {
6,260✔
324
                                uint32_t idx;
1,975✔
325
                                zend_op *src_opline = source->op_array.opcodes + (opline - opcodes);
1,975✔
326
#if ZEND_USE_ABS_CONST_ADDR
327
                                idx = (zval *)src_opline->op1.zv - source->op_array.literals;
328
                                opline->op1.zv = &cached->literals[idx];
329
#else
330
                                idx = ((zval *)((char *)src_opline + src_opline->op1.constant) - source->op_array.literals);
1,975✔
331
                                opline->op1.constant = (char *)&cached->literals[idx] - (char *)opline;
1,975✔
332
#endif
333
                                if (opline->opcode == ZEND_SEND_VAL || opline->opcode == ZEND_SEND_VAL_EX ||
1,975✔
334
                                    opline->opcode == ZEND_QM_ASSIGN) {
335
                                        zend_vm_set_opcode_handler_ex(opline, 0, 0, 0);
271✔
336
                                }
337
                        }
338
                        if (opline->op2_type == IS_CONST) {
6,260✔
339
                                uint32_t idx;
1,065✔
340
                                zend_op *src_opline = source->op_array.opcodes + (opline - opcodes);
1,065✔
341
#if ZEND_USE_ABS_CONST_ADDR
342
                                idx = (zval *)src_opline->op2.zv - source->op_array.literals;
343
                                opline->op2.zv = &cached->literals[idx];
344
#else
345
                                idx = ((zval *)((char *)src_opline + src_opline->op2.constant) - source->op_array.literals);
1,065✔
346
                                opline->op2.constant = (char *)&cached->literals[idx] - (char *)opline;
1,065✔
347
#endif
348
                        }
349

350
                        if (opline->opcode == ZEND_INIT_FCALL) {
6,260✔
351
                                Z_EXTRA_P(RT_CONSTANT(opline, opline->op2)) = 0;
327✔
352
                                ZEND_VM_SET_OPCODE_HANDLER(opline);
327✔
353
                        }
354
#if ZEND_USE_ABS_JMP_ADDR
355
                        switch (opline->opcode) {
356
                        case ZEND_JMP:
357
                        case ZEND_FAST_CALL:
358
                                opline->op1.jmp_addr = &opcodes[opline->op1.jmp_addr - source->op_array.opcodes];
359
                                break;
360
#if PHP_VERSION_ID < 80200
361
                        case ZEND_JMPZNZ:
362
#endif
363
                        case ZEND_JMPZ:
364
                        case ZEND_JMPNZ:
365
                        case ZEND_JMPZ_EX:
366
                        case ZEND_JMPNZ_EX:
367
                        case ZEND_JMP_SET:
368
                        case ZEND_COALESCE:
369
                        case ZEND_FE_RESET_R:
370
                        case ZEND_FE_RESET_RW:
371
                        case ZEND_ASSERT_CHECK:
372
                                opline->op2.jmp_addr = &opcodes[opline->op2.jmp_addr - source->op_array.opcodes];
373
                                break;
374

375
                        case ZEND_CATCH:
376
                                if (!(opline->extended_value & ZEND_LAST_CATCH)) {
377
                                        opline->op2.jmp_addr = &opcodes[opline->op2.jmp_addr - source->op_array.opcodes];
378
                                }
379
                                break;
380
                        }
381
#endif
382

383
                        opline++;
6,260✔
384
                }
385
                cached->opcodes = opcodes;
962✔
386
        }
387

388
        php_parallel_cache_identities(source, (zend_function *)cached);
962✔
389

390
        if (cached->last_var) {
962✔
391
                zend_string **vars = cached->vars;
619✔
392
                uint32_t      it = 0, end = cached->last_var;
619✔
393
                zend_string **heap = php_parallel_cache_alloc(cached->last_var * sizeof(zend_string *));
619✔
394

395
                while (it < end) {
1,441✔
396
                        heap[it] = php_parallel_copy_string_interned(vars[it]);
822✔
397
                        it++;
822✔
398
                }
399
                cached->vars = heap;
619✔
400
        }
401

402
        if (cached->arg_info) {
962✔
403
                zend_arg_info *it = cached->arg_info, *end = it + cached->num_args, *info;
312✔
404

405
                if (cached->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
312✔
406
                        it--;
52✔
407
                }
408
                if (cached->fn_flags & ZEND_ACC_VARIADIC) {
312✔
409
                        end++;
12✔
410
                }
411

412
                cached->arg_info = info = php_parallel_cache_copy_mem(it, (end - it) * sizeof(zend_arg_info));
312✔
413

414
                while (it < end) {
688✔
415
                        if (info->name) {
376✔
416
                                info->name = php_parallel_copy_string_interned(it->name);
324✔
417
                        }
418

419
                        php_parallel_cache_type(&info->type);
376✔
420

421
                        info++;
376✔
422
                        it++;
376✔
423
                }
424
                if (cached->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
312✔
425
                        cached->arg_info++;
52✔
426
                }
427
        }
428

429
        if (cached->try_catch_array) {
962✔
430
                cached->try_catch_array = php_parallel_cache_copy_mem(cached->try_catch_array,
18✔
431
                                                                      sizeof(zend_try_catch_element) * cached->last_try_catch);
18✔
432
        }
433

434
        if (cached->live_range) {
962✔
435
                cached->live_range =
246✔
436
                    php_parallel_cache_copy_mem(cached->live_range, sizeof(zend_live_range) * cached->last_live_range);
246✔
437
        }
438

439
        if (cached->function_name)
962✔
440
                cached->function_name = php_parallel_copy_string_interned(cached->function_name);
962✔
441

442
        if (cached->filename)
962✔
443
                cached->filename = php_parallel_copy_string_interned(cached->filename);
962✔
444

445
        if (cached->doc_comment)
962✔
446
                cached->doc_comment = php_parallel_copy_string_interned(cached->doc_comment);
6✔
447

448
_php_parallel_cached_function_return:
956✔
449
        return cached;
2,832✔
450
} /* }}} */
451

452
/* {{{ */
453
static zend_always_inline zend_function *
454
php_parallel_cache_function_ex(const zend_function *source PARALLEL_CACHE_STATICS_PARAM)
3,303✔
455
{
456
        php_parallel_cache_entry_t *entry;
3,303✔
457
        zend_op_array              *cached;
3,303✔
458
#if PHP_VERSION_ID >= 80400
459
        uint64_t source_hash = php_parallel_cache_file_hash(&source->op_array);
2,288✔
460
#endif
461

462
        pthread_mutex_lock(&PCG(mutex));
3,303✔
463

464
        if ((entry = zend_hash_index_find_ptr(&PCG(functions), (zend_ulong)source->op_array.opcodes))) {
4,001✔
465
#if PHP_VERSION_ID >= 80400
466
                if (!zend_string_equals(entry->function->function_name, source->op_array.function_name) ||
332✔
467
                    entry->source != source_hash) {
246✔
468
                        goto _php_parallel_cached_function_create;
2✔
469
                }
470
#endif
471
                cached = entry->function;
696✔
472
                goto _php_parallel_cached_function_return;
696✔
473
        }
474

475
#if PHP_VERSION_ID >= 80400
476
_php_parallel_cached_function_create:
477
#endif
478
        entry = php_parallel_cache_alloc(sizeof(php_parallel_cache_entry_t));
2,607✔
479

480
        cached = php_parallel_cache_create(source PARALLEL_CACHE_STATICS_ARG(statics));
2,607✔
481
        entry->function = cached;
2,607✔
482
#if PHP_VERSION_ID >= 80400
483
        entry->source = source_hash;
900✔
484
#endif
485

486
        zend_hash_index_update_ptr(&PCG(functions), (zend_ulong)source->op_array.opcodes, entry);
2,607✔
487

488
_php_parallel_cached_function_return:
3,303✔
489
        pthread_mutex_unlock(&PCG(mutex));
3,303✔
490

491
        return (zend_function *)cached;
3,303✔
492
} /* }}} */
493

494
zend_function *php_parallel_cache_closure(const zend_function *source, zend_function *closure)
3,264✔
495
{ /* {{{ */
496
        zend_op_array *cache;
3,264✔
497

498
        cache = (zend_op_array *)php_parallel_cache_function_ex((zend_function *)source PARALLEL_CACHE_STATICS_ARG(0));
3,264✔
499

500
        if (!closure) {
3,264✔
501
                closure = php_parallel_copy_mem(cache, sizeof(zend_op_array), 1);
2,556✔
502
        } else {
503
                memcpy(closure, cache, sizeof(zend_op_array));
708✔
504
        }
505

506
        if (source->op_array.static_variables) {
3,264✔
507
                HashTable *statics = ZEND_MAP_PTR_GET(source->op_array.static_variables_ptr);
708✔
508

509
                if (statics) {
708✔
510
                        closure->op_array.static_variables = php_parallel_copy_hash_ctor(statics, 1);
558✔
511

512
#if PHP_VERSION_ID >= 80200
513
                        ZEND_MAP_PTR_INIT(closure->op_array.static_variables_ptr, closure->op_array.static_variables);
372✔
514
#else
515
                        ZEND_MAP_PTR_INIT(closure->op_array.static_variables_ptr, &closure->op_array.static_variables);
186✔
516
#endif
517
                }
518
        }
519

520
#if PHP_VERSION_ID >= 80100
521
        if (source->op_array.num_dynamic_func_defs) {
2,779✔
522
                uint32_t it = 0;
210✔
523
                /* Use regular persistent memory for dynamic_func_defs array, not cache pool */
524
                closure->op_array.dynamic_func_defs =
420✔
525
                    pemalloc(sizeof(zend_op_array *) * source->op_array.num_dynamic_func_defs, 1);
210✔
526
                memcpy(closure->op_array.dynamic_func_defs, source->op_array.dynamic_func_defs,
660✔
527
                       sizeof(zend_op_array *) * source->op_array.num_dynamic_func_defs);
210✔
528
                while (it < source->op_array.num_dynamic_func_defs) {
450✔
529
                        closure->op_array.dynamic_func_defs[it] = (zend_op_array *)php_parallel_cache_closure(
480✔
530
                            (zend_function *)source->op_array.dynamic_func_defs[it], NULL);
240✔
531
                        it++;
240✔
532
                }
533
        }
534
#endif
535

536
        return closure;
3,264✔
537
} /* }}} */
538

539
#if PHP_VERSION_ID < 80200
540
zend_function *php_parallel_cache_function(const zend_function *source)
39✔
541
{ /* {{{ */
542
        return php_parallel_cache_function_ex(source, 1);
39✔
543
} /* }}} */
544
#endif
545

546
/* {{{ */
547
PHP_MINIT_FUNCTION(PARALLEL_CACHE)
3,357✔
548
{
549
        zend_hash_init(&PCG(functions), 32, NULL, NULL, 1);
3,357✔
550
        zend_hash_init(&PCG(identities), 32, NULL, NULL, 1);
3,357✔
551
#if PHP_VERSION_ID < 80200
552
        zend_hash_init(&PCG(statics), 32, NULL, NULL, 1);
1,373✔
553
#endif
554

555
        PCM(size) = PARALLEL_CACHE_CHUNK;
3,357✔
556
        PCM(mem) = PCM(block) = malloc(PCM(size));
3,357✔
557

558
        if (!PCM(mem)) {
3,357✔
559
                /* out of memory */
560
        }
3,357✔
561

562
        return SUCCESS;
3,357✔
563
}
564

565
PHP_MSHUTDOWN_FUNCTION(PARALLEL_CACHE)
3,357✔
566
{
567
        zend_hash_destroy(&PCG(functions));
3,357✔
568
        zend_hash_destroy(&PCG(identities));
3,357✔
569
#if PHP_VERSION_ID < 80200
570
        zend_hash_destroy(&PCG(statics));
1,373✔
571
#endif
572

573
        if (PCM(mem))
3,357✔
574
                free(PCM(mem));
3,357✔
575

576
        return SUCCESS;
3,357✔
577
} /* }}} */
578
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc