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

krakjoe / parallel / 9116320497

16 May 2024 05:04PM UTC coverage: 96.796% (+1.0%) from 95.846%
9116320497

push

github

web-flow
Merge pull request #298 from flavioheleno/fix/pipeline

Replace Docker Hub with GitHub Container Registry

2870 of 2965 relevant lines covered (96.8%)

3551.53 hits per line

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

97.33
/src/cache.c
1
/*
2
  +----------------------------------------------------------------------+
3
  | parallel                                                             |
4
  +----------------------------------------------------------------------+
5
  | Copyright (c) Joe Watkins 2019-2022                                  |
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       table;
26
    struct {
27
        size_t      size;
28
        size_t      used;
29
        void       *mem;
30
        void       *block;
31
    } memory;
32
} php_parallel_cache_globals = {PTHREAD_MUTEX_INITIALIZER};
33

34
#define PCG(e) php_parallel_cache_globals.e
35
#define PCM(e) PCG(memory).e
36

37
#define PARALLEL_CACHE_CHUNK \
38
    PARALLEL_PLATFORM_ALIGNED((1024 * 1024) * 8)
39

40
/* {{{ */
41
static zend_always_inline void* php_parallel_cache_alloc(size_t size) {
2,295✔
42
    void *mem;
2,295✔
43
    size_t aligned =
2,295✔
44
        PARALLEL_PLATFORM_ALIGNED(size);
1,233✔
45

46
    ZEND_ASSERT(size < PARALLEL_CACHE_CHUNK);
2,295✔
47

48
    if ((PCM(used) + aligned) >= PCM(size)) {
2,295✔
49
        PCM(size) = PARALLEL_PLATFORM_ALIGNED(
×
50
            PCM(size) + PARALLEL_CACHE_CHUNK);
51
        PCM(mem) = (void*) realloc(PCM(mem), PCM(size));
×
52

53
        if (!PCM(mem)) {
×
54
            /* out of memory */
55
            return NULL;
56
        }
57

58
        PCM(block) = (void*)(((char*)PCM(mem)) + PCM(used));
×
59
    }
60

61
    mem = PCM(block);
2,295✔
62
    PCM(block) =
2,295✔
63
        (void*)(((char*)PCM(block)) + aligned);
2,295✔
64
    PCM(used) += aligned;
2,295✔
65

66
    return mem;
2,295✔
67
}
68

69
static zend_always_inline void* php_parallel_cache_copy_mem(void *source, zend_long size) {
2,076✔
70
    void *destination =
2,076✔
71
        php_parallel_cache_alloc(size);
78✔
72

73
    memcpy(destination, source, size);
1,998✔
74

75
    return destination;
2,076✔
76
} /* }}} */
77

78
static zend_always_inline HashTable* php_parallel_cache_statics(HashTable *statics) { /* {{{ */
21✔
79
    HashTable *cached = zend_hash_index_find_ptr(&PCG(table), (zend_ulong) statics);
42✔
80

81
    if (cached) {
×
82
        return cached;
83
    }
84

85
    cached = php_parallel_copy_hash_persistent(
21✔
86
                statics,
87
                php_parallel_copy_string_interned,
88
                php_parallel_cache_copy_mem);
89

90
    return zend_hash_index_update_ptr(&PCG(table), (zend_ulong) statics, cached);
21✔
91
} /* }}} */
92

93
static zend_always_inline void php_parallel_cache_type(zend_type *type) { /* {{{ */
117✔
94
    zend_type *single;
117✔
95

96
    if (!ZEND_TYPE_IS_SET(*type)) {
117✔
97
        return;
98
    }
99

100
    if (ZEND_TYPE_HAS_LIST(*type)) {
72✔
101
        zend_type_list *list = ZEND_TYPE_LIST(*type);
3✔
102

103
        list = php_parallel_cache_copy_mem(
6✔
104
                    list, ZEND_TYPE_LIST_SIZE(list->num_types));
3✔
105

106
        if (ZEND_TYPE_USES_ARENA(*type)) {
3✔
107
            ZEND_TYPE_FULL_MASK(*type) &= ~_ZEND_TYPE_ARENA_BIT;
2✔
108
        }
109
 
110
        ZEND_TYPE_SET_PTR(*type, list);
3✔
111
    }
112

113
    ZEND_TYPE_FOREACH(*type, single) {
72✔
114
        if (ZEND_TYPE_HAS_NAME(*single)) {
75✔
115
            zend_string *name = ZEND_TYPE_NAME(*single);
42✔
116

117
            ZEND_TYPE_SET_PTR(
42✔
118
                *single,
119
                php_parallel_copy_string_interned(name));
120
        }
121
    } ZEND_TYPE_FOREACH_END();
75✔
122
} /* }}} */
123

124

125
/* {{{ */
126
static zend_op_array* php_parallel_cache_create(const zend_function *source, zend_bool statics) {
1,062✔
127
    zend_op_array *cached = php_parallel_cache_copy_mem((void*) source, sizeof(zend_op_array));
1,062✔
128

129
    cached->fn_flags |= ZEND_ACC_IMMUTABLE;
1,062✔
130

131
    if (statics && cached->static_variables) {
1,062✔
132
        cached->static_variables =
42✔
133
            php_parallel_cache_statics(cached->static_variables);
42✔
134
    }
135

136
#if PHP_VERSION_ID >= 80200
137
    ZEND_MAP_PTR_INIT(cached->static_variables_ptr, cached->static_variables);
354✔
138
#else
139
    ZEND_MAP_PTR_INIT(cached->static_variables_ptr, &cached->static_variables);
708✔
140
#endif
141

142
    ZEND_MAP_PTR_INIT(cached->run_time_cache, NULL);
1,062✔
143

144
#if PHP_VERSION_ID >= 80100
145
    if (cached->num_dynamic_func_defs) {
708✔
146
            uint32_t it = 0;
60✔
147
            
148
            cached->dynamic_func_defs = php_parallel_cache_copy_mem(
120✔
149
                                            cached->dynamic_func_defs,
60✔
150
                                            sizeof(zend_op_array*) * cached->num_dynamic_func_defs);
60✔
151
            
152
            while (it < cached->num_dynamic_func_defs) {
132✔
153
                cached->dynamic_func_defs[it] = 
144✔
154
                (zend_op_array*) php_parallel_cache_create(
72✔
155
                        (zend_function*) cached->dynamic_func_defs[it], statics);
72✔
156
            it++;
72✔
157
            }
158
    }
159
#endif
160

161
    if (!cached->refcount) {
1,062✔
162
        goto _php_parallel_cached_function_return;
699✔
163
    }
164

165
    cached->refcount  = NULL;
363✔
166

167
    if (cached->last_literal) {
363✔
168
        zval     *literal = cached->literals,
363✔
169
                 *end     = literal + cached->last_literal;
363✔
170
        zval     *slot    = php_parallel_cache_copy_mem(
726✔
171
                                    cached->literals,
363✔
172
                                        sizeof(zval) * cached->last_literal);
173

174
        cached->literals = slot;
363✔
175

176
        while (literal < end) {
1,818✔
177
            if (Z_TYPE_P(literal) == IS_ARRAY) {
1,455✔
178
                ZVAL_ARR(slot,
18✔
179
                    php_parallel_copy_hash_persistent(
180
                        Z_ARRVAL_P(literal),
181
                        php_parallel_copy_string_interned,
182
                        php_parallel_cache_copy_mem));
183
            } else if (Z_TYPE_P(literal) == IS_STRING) {
1,437✔
184
                ZVAL_STR(slot,
852✔
185
                    php_parallel_copy_string_interned(Z_STR_P(literal)));
186
            }
187

188
                Z_TYPE_FLAGS_P(slot) &= ~(IS_TYPE_REFCOUNTED|IS_TYPE_COLLECTABLE);
1,455✔
189
            literal++;
1,455✔
190
            slot++;
1,455✔
191
        }
192
    }
193

194
    if (cached->last_var) {
363✔
195
        zend_string **vars = cached->vars;
219✔
196
        uint32_t      it = 0,
219✔
197
                      end = cached->last_var;
219✔
198
        zend_string **heap = php_parallel_cache_alloc(cached->last_var * sizeof(zend_string*));
219✔
199

200
        while (it < end) {
522✔
201
            heap[it] =
606✔
202
                php_parallel_copy_string_interned(vars[it]);
303✔
203
            it++;
303✔
204
        }
205
        cached->vars = heap;
219✔
206
    }
207

208
    if (cached->last) {
363✔
209
        zend_op *opcodes = php_parallel_cache_copy_mem(cached->opcodes, sizeof(zend_op) * cached->last);
363✔
210
        zend_op *opline  = opcodes,
363✔
211
                *end     = opline + cached->last;
363✔
212

213
        while (opline < end) {
2,730✔
214
            if (opline->op1_type == IS_CONST) {
2,367✔
215
#if ZEND_USE_ABS_CONST_ADDR
216
                opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)cached->literals - (char*)source->op_array.literals));
217
#else
218
                opline->op1.constant =
795✔
219
                    (char*)(cached->literals +
795✔
220
                            ((zval*)((char*)(source->op_array.opcodes + (opline - opcodes)) +
795✔
221
                            (int32_t)opline->op1.constant) - source->op_array.literals)) -
795✔
222
                            (char*)opline;
223
#endif
224
                if (opline->opcode == ZEND_SEND_VAL
795✔
225
                 || opline->opcode == ZEND_SEND_VAL_EX
795✔
226
                 || opline->opcode == ZEND_QM_ASSIGN) {
672✔
227
                    zend_vm_set_opcode_handler_ex(opline, 0, 0, 0);
123✔
228
                }
229
            }
230
            if (opline->op2_type == IS_CONST) {
2,367✔
231
#if ZEND_USE_ABS_CONST_ADDR
232
                opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)cached->literals - (char*)source->op_array.literals));
233
#else
234
                opline->op2.constant =
402✔
235
                    (char*)(cached->literals +
402✔
236
                            ((zval*)((char*)(source->op_array.opcodes + (opline - opcodes)) +
402✔
237
                            (int32_t)opline->op2.constant) - source->op_array.literals)) -
402✔
238
                            (char*)opline;
239
#endif
240
            }
241
#if ZEND_USE_ABS_JMP_ADDR
242
            switch (opline->opcode) {
243
                case ZEND_JMP:
244
                case ZEND_FAST_CALL:
245
                    opline->op1.jmp_addr = &opcodes[opline->op1.jmp_addr - source->op_array.opcodes];
246
                break;
247
#if PHP_VERSION_ID < 80200
248
                case ZEND_JMPZNZ:
249
#endif
250
                case ZEND_JMPZ:
251
                case ZEND_JMPNZ:
252
                case ZEND_JMPZ_EX:
253
                case ZEND_JMPNZ_EX:
254
                case ZEND_JMP_SET:
255
                case ZEND_COALESCE:
256
                case ZEND_FE_RESET_R:
257
                case ZEND_FE_RESET_RW:
258
                case ZEND_ASSERT_CHECK:
259
                    opline->op2.jmp_addr = &opcodes[opline->op2.jmp_addr - source->op_array.opcodes];
260
                    break;
261

262
                case ZEND_CATCH:
263
                    if (!(opline->extended_value & ZEND_LAST_CATCH)) {
264
                        opline->op2.jmp_addr = &opcodes[opline->op2.jmp_addr - source->op_array.opcodes];
265
                    }
266
                    break;
267
            }
268
#endif
269

270
            opline++;
2,367✔
271
        }
272
        cached->opcodes = opcodes;
363✔
273
    }
274

275
    if (cached->arg_info) {
363✔
276
        zend_arg_info *it    = cached->arg_info,
93✔
277
                      *end   = it + cached->num_args,
93✔
278
                      *info;
279

280
        if (cached->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
93✔
281
            it--;
18✔
282
        }
283
        if (cached->fn_flags & ZEND_ACC_VARIADIC) {
93✔
284
            end++;
6✔
285
        }
286

287
        cached->arg_info = info = php_parallel_cache_copy_mem(it, (end - it) * sizeof(zend_arg_info));
93✔
288

289
         while (it < end) {
210✔
290
            if (info->name) {
117✔
291
                info->name =
99✔
292
                    php_parallel_copy_string_interned(it->name);
99✔
293
            }
294
            
295
            php_parallel_cache_type(&info->type);
117✔
296

297
            info++;
117✔
298
            it++;
117✔
299
        }
300
        if (cached->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
93✔
301
            cached->arg_info++;
18✔
302
        }
303
    }
304

305
    if (cached->try_catch_array) {
363✔
306
        cached->try_catch_array =
18✔
307
            php_parallel_cache_copy_mem(
9✔
308
                cached->try_catch_array,
9✔
309
                    sizeof(zend_try_catch_element) * cached->last_try_catch);
9✔
310
    }
311

312
    if (cached->live_range) {
363✔
313
        cached->live_range =
90✔
314
            php_parallel_cache_copy_mem(
45✔
315
                cached->live_range,
45✔
316
                sizeof(zend_live_range) * cached->last_live_range);
45✔
317
    }
318

319
    if (cached->function_name)
363✔
320
        cached->function_name =
363✔
321
            php_parallel_copy_string_interned(cached->function_name);
363✔
322

323
    if (cached->filename)
363✔
324
        cached->filename =
363✔
325
            php_parallel_copy_string_interned(cached->filename);
363✔
326

327
    if (cached->doc_comment)
363✔
328
        cached->doc_comment =
3✔
329
            php_parallel_copy_string_interned(cached->doc_comment);
3✔
330

331
_php_parallel_cached_function_return:
360✔
332
    return cached;
1,062✔
333
} /* }}} */
334

335
/* {{{ */
336
static zend_always_inline zend_function* php_parallel_cache_function_ex(const zend_function *source, zend_bool statics) {
1,221✔
337
    zend_op_array *cached;
1,221✔
338
    
339
    pthread_mutex_lock(&PCG(mutex));
1,221✔
340

341
    if ((cached = zend_hash_index_find_ptr(&PCG(table), (zend_ulong) source->op_array.opcodes))) {
1,452✔
342
        goto _php_parallel_cached_function_return;
231✔
343
    }
344

345
    cached = php_parallel_cache_create(source, statics);
990✔
346

347
    zend_hash_index_add_ptr(
2,211✔
348
        &PCG(table),
349
        (zend_ulong) source->op_array.opcodes, 
990✔
350
        cached);
351

352
_php_parallel_cached_function_return:
1,221✔
353
    pthread_mutex_unlock(&PCG(mutex));
1,221✔
354

355
    return (zend_function*) cached;
1,221✔
356
} /* }}} */
357

358
zend_function* php_parallel_cache_closure(const zend_function *source, zend_function *closure) { /* {{{ */
1,185✔
359
    zend_op_array *cache;
1,185✔
360

361
    cache =
1,185✔
362
        (zend_op_array*)
363
            php_parallel_cache_function_ex(
1,185✔
364
                (zend_function*) source, 0);
365

366
    if (!closure) {
1,185✔
367
        closure = php_parallel_copy_mem(
849✔
368
            cache, sizeof(zend_op_array), 1);
369
    } else {
370
        memcpy(closure, cache, sizeof(zend_op_array));
336✔
371
    }
372

373
    if (closure->op_array.static_variables) {
1,185✔
374
        HashTable *statics =
558✔
375
            ZEND_MAP_PTR_GET(
279✔
376
                source->op_array.static_variables_ptr);
377

378
        closure->op_array.static_variables =
558✔
379
            php_parallel_copy_hash_ctor(statics, 1);
279✔
380

381
#if PHP_VERSION_ID >= 80200
382
        ZEND_MAP_PTR_INIT(
93✔
383
            closure->op_array.static_variables_ptr,
384
            closure->op_array.static_variables);
385
#else
386
        ZEND_MAP_PTR_INIT(
186✔
387
            closure->op_array.static_variables_ptr,
388
            &closure->op_array.static_variables);
389
#endif
390
    }
391

392
    return closure;
1,185✔
393
} /* }}} */
394

395
zend_function* php_parallel_cache_function(const zend_function *source) { /* {{{ */
36✔
396
    return php_parallel_cache_function_ex(source, 1);
36✔
397
} /* }}} */
398

399
/* {{{ */
400
PHP_MINIT_FUNCTION(PARALLEL_CACHE)
1,686✔
401
{
402
    zend_hash_init(&PCG(table), 32, NULL, NULL, 1);
1,686✔
403

404
    PCM(size) = PARALLEL_CACHE_CHUNK;
1,686✔
405
    PCM(mem) =
1,686✔
406
        PCM(block) =
1,686✔
407
            malloc(PCM(size));
1,686✔
408

409
    if (!PCM(mem)) {
1,686✔
410
        /* out of memory */
411
    }
1,686✔
412

413
    return SUCCESS;
1,686✔
414
}
415

416
PHP_MSHUTDOWN_FUNCTION(PARALLEL_CACHE)
1,686✔
417
{
418
    zend_hash_destroy(&PCG(table));
1,686✔
419

420
    if (PCM(mem))
1,686✔
421
        free(PCM(mem));
1,686✔
422

423
    return SUCCESS;
1,686✔
424
} /* }}} */
425
#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