This source file includes following definitions.
- zend_accel_destroy_zend_function
- zend_accel_destroy_zend_class
- create_persistent_script
- compact_hash_table
- compact_persistent_script
- free_persistent_script
- is_not_internal_function
- zend_accel_free_user_functions
- move_user_function
- zend_accel_move_user_functions
- copy_internal_function
- zend_accel_copy_internal_functions
- zend_destroy_property_info
- zend_ast_clone
- zend_clone_zval
- zend_hash_clone_zval
- zend_hash_clone_methods
- zend_hash_clone_prop_info
- zend_prepare_function_for_execution
- zend_class_copy_ctor
- zend_hash_unique_copy
- zend_accel_function_hash_copy
- zend_accel_class_hash_copy
- zend_do_delayed_early_binding
- zend_accel_load_script
- zend_adler32
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include "zend_API.h"
23 #include "zend_constants.h"
24 #include "zend_accelerator_util_funcs.h"
25 #include "zend_persist.h"
26 #include "zend_shared_alloc.h"
27
28 #define ZEND_PROTECTED_REFCOUNT (1<<30)
29
30 static zend_uint zend_accel_refcount = ZEND_PROTECTED_REFCOUNT;
31
32 #if SIZEOF_SIZE_T <= SIZEOF_LONG
33
34 # define accel_xlat_set(old, new) zend_hash_index_update(&ZCG(bind_hash), (ulong)(zend_uintptr_t)(old), &(new), sizeof(void*), NULL)
35 # define accel_xlat_get(old, new) zend_hash_index_find(&ZCG(bind_hash), (ulong)(zend_uintptr_t)(old), (void**)&(new))
36 #else
37 # define accel_xlat_set(old, new) zend_hash_quick_add(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (ulong)(zend_uintptr_t)(old), (void**)&(new), sizeof(void*), NULL)
38 # define accel_xlat_get(old, new) zend_hash_quick_find(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (ulong)(zend_uintptr_t)(old), (void**)&(new))
39 #endif
40
41 typedef int (*id_function_t)(void *, void *);
42 typedef void (*unique_copy_ctor_func_t)(void *pElement);
43
44 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
45 static const Bucket *uninitialized_bucket = NULL;
46 #endif
47
48 static int zend_prepare_function_for_execution(zend_op_array *op_array);
49 static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind);
50
51 static void zend_accel_destroy_zend_function(zend_function *function)
52 {
53 TSRMLS_FETCH();
54
55 if (function->type == ZEND_USER_FUNCTION) {
56 if (function->op_array.static_variables) {
57
58 efree(function->op_array.static_variables);
59 function->op_array.static_variables = NULL;
60 }
61 }
62
63 destroy_zend_function(function TSRMLS_CC);
64 }
65
66 static void zend_accel_destroy_zend_class(zend_class_entry **pce)
67 {
68 zend_class_entry *ce = *pce;
69
70 ce->function_table.pDestructor = (dtor_func_t) zend_accel_destroy_zend_function;
71 destroy_zend_class(pce);
72 }
73
74 zend_persistent_script* create_persistent_script(void)
75 {
76 zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script));
77 memset(persistent_script, 0, sizeof(zend_persistent_script));
78
79 zend_hash_init(&persistent_script->function_table, 100, NULL, (dtor_func_t) zend_accel_destroy_zend_function, 0);
80
81
82
83
84 zend_hash_init(&persistent_script->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
85
86 return persistent_script;
87 }
88
89 static int compact_hash_table(HashTable *ht)
90 {
91 uint i = 3;
92 uint nSize;
93 Bucket **t;
94
95 if (!ht->nNumOfElements) {
96
97 return 1;
98 }
99
100 if (ht->nNumOfElements >= 0x80000000) {
101
102 nSize = 0x80000000;
103 } else {
104 while ((1U << i) < ht->nNumOfElements) {
105 i++;
106 }
107 nSize = 1 << i;
108 }
109
110 if (nSize >= ht->nTableSize) {
111
112 return 1;
113 }
114
115 t = (Bucket **)pemalloc(nSize * sizeof(Bucket *), ht->persistent);
116 if (!t) {
117 return 0;
118 }
119
120 pefree(ht->arBuckets, ht->persistent);
121
122 ht->arBuckets = t;
123 ht->nTableSize = nSize;
124 ht->nTableMask = ht->nTableSize - 1;
125 zend_hash_rehash(ht);
126
127 return 1;
128 }
129
130 int compact_persistent_script(zend_persistent_script *persistent_script)
131 {
132 return compact_hash_table(&persistent_script->function_table) &&
133 compact_hash_table(&persistent_script->class_table);
134 }
135
136 void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements)
137 {
138 if (destroy_elements) {
139 persistent_script->function_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_function;
140 persistent_script->class_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_class;
141 } else {
142 persistent_script->function_table.pDestructor = NULL;
143 persistent_script->class_table.pDestructor = NULL;
144 }
145
146 zend_hash_destroy(&persistent_script->function_table);
147 zend_hash_destroy(&persistent_script->class_table);
148
149 if (persistent_script->full_path) {
150 efree(persistent_script->full_path);
151 }
152
153 efree(persistent_script);
154 }
155
156 static int is_not_internal_function(zend_function *function)
157 {
158 return(function->type != ZEND_INTERNAL_FUNCTION);
159 }
160
161 void zend_accel_free_user_functions(HashTable *ht TSRMLS_DC)
162 {
163 dtor_func_t orig_dtor = ht->pDestructor;
164
165 ht->pDestructor = NULL;
166 zend_hash_apply(ht, (apply_func_t) is_not_internal_function TSRMLS_CC);
167 ht->pDestructor = orig_dtor;
168 }
169
170 static int move_user_function(zend_function *function
171 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
172 TSRMLS_DC
173 #endif
174 , int num_args, va_list args, zend_hash_key *hash_key)
175 {
176 HashTable *function_table = va_arg(args, HashTable *);
177 (void)num_args;
178 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
179 TSRMLS_FETCH();
180 #endif
181
182 if (function->type == ZEND_USER_FUNCTION) {
183 zend_hash_quick_update(function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, function, sizeof(zend_function), NULL);
184 return 1;
185 } else {
186 return 0;
187 }
188 }
189
190 void zend_accel_move_user_functions(HashTable *src, HashTable *dst TSRMLS_DC)
191 {
192 dtor_func_t orig_dtor = src->pDestructor;
193
194 src->pDestructor = NULL;
195 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
196 zend_hash_apply_with_arguments(src, (apply_func_args_t)move_user_function, 1, dst);
197 #else
198 zend_hash_apply_with_arguments(src TSRMLS_CC, (apply_func_args_t)move_user_function, 1, dst);
199 #endif
200 src->pDestructor = orig_dtor;
201 }
202
203 static int copy_internal_function(zend_function *function, HashTable *function_table TSRMLS_DC)
204 {
205 if (function->type == ZEND_INTERNAL_FUNCTION) {
206 zend_hash_update(function_table, function->common.function_name, strlen(function->common.function_name) + 1, function, sizeof(zend_function), NULL);
207 }
208 return 0;
209 }
210
211 void zend_accel_copy_internal_functions(TSRMLS_D)
212 {
213 zend_hash_apply_with_argument(CG(function_table), (apply_func_arg_t)copy_internal_function, &ZCG(function_table) TSRMLS_CC);
214 ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table));
215 }
216
217 static void zend_destroy_property_info(zend_property_info *property_info)
218 {
219 interned_efree((char*)property_info->name);
220 if (property_info->doc_comment) {
221 efree((char*)property_info->doc_comment);
222 }
223 }
224
225 #if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
226 static zend_ast *zend_ast_clone(zend_ast *ast TSRMLS_DC)
227 {
228 int i;
229 zend_ast *node;
230
231 if (ast->kind == ZEND_CONST) {
232 node = emalloc(sizeof(zend_ast) + sizeof(zval));
233 node->kind = ZEND_CONST;
234 node->children = 0;
235 node->u.val = (zval*)(node + 1);
236 *node->u.val = *ast->u.val;
237 if ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
238 switch ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK)) {
239 case IS_STRING:
240 case IS_CONSTANT:
241 Z_STRVAL_P(node->u.val) = (char *) interned_estrndup(Z_STRVAL_P(ast->u.val), Z_STRLEN_P(ast->u.val));
242 break;
243 case IS_ARRAY:
244 #if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
245 case IS_CONSTANT_ARRAY:
246 #endif
247 if (ast->u.val->value.ht && ast->u.val->value.ht != &EG(symbol_table)) {
248 ALLOC_HASHTABLE(node->u.val->value.ht);
249 zend_hash_clone_zval(node->u.val->value.ht, ast->u.val->value.ht, 0);
250 }
251 break;
252 case IS_CONSTANT_AST:
253 Z_AST_P(node->u.val) = zend_ast_clone(Z_AST_P(ast->u.val) TSRMLS_CC);
254 break;
255 }
256 }
257 } else {
258 node = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
259 node->kind = ast->kind;
260 node->children = ast->children;
261 for (i = 0; i < ast->children; i++) {
262 if ((&ast->u.child)[i]) {
263 (&node->u.child)[i] = zend_ast_clone((&ast->u.child)[i] TSRMLS_CC);
264 } else {
265 (&node->u.child)[i] = NULL;
266 }
267 }
268 }
269 return node;
270 }
271 #endif
272
273 static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC)
274 {
275 zval *ret, **ret_ptr = NULL;
276
277 if (!bind) {
278 ALLOC_ZVAL(ret);
279 *ret = *src;
280 INIT_PZVAL(ret);
281 } else if (Z_REFCOUNT_P(src) == 1) {
282 ALLOC_ZVAL(ret);
283 *ret = *src;
284 } else if (accel_xlat_get(src, ret_ptr) != SUCCESS) {
285 ALLOC_ZVAL(ret);
286 *ret = *src;
287 accel_xlat_set(src, ret);
288 } else {
289 return *ret_ptr;
290 }
291
292 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
293 if ((Z_TYPE_P(ret) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
294 switch ((Z_TYPE_P(ret) & IS_CONSTANT_TYPE_MASK)) {
295 #else
296 if ((Z_TYPE_P(ret) & ~IS_CONSTANT_INDEX) >= IS_ARRAY) {
297 switch ((Z_TYPE_P(ret) & ~IS_CONSTANT_INDEX)) {
298 #endif
299 case IS_STRING:
300 case IS_CONSTANT:
301 Z_STRVAL_P(ret) = (char *) interned_estrndup(Z_STRVAL_P(ret), Z_STRLEN_P(ret));
302 break;
303 case IS_ARRAY:
304 #if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
305 case IS_CONSTANT_ARRAY:
306 #endif
307 if (ret->value.ht && ret->value.ht != &EG(symbol_table)) {
308 ALLOC_HASHTABLE(ret->value.ht);
309 zend_hash_clone_zval(ret->value.ht, src->value.ht, 0);
310 }
311 break;
312 #if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
313 case IS_CONSTANT_AST:
314 Z_AST_P(ret) = zend_ast_clone(Z_AST_P(ret) TSRMLS_CC);
315 break;
316 #endif
317 }
318 }
319 return ret;
320 }
321
322 static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
323 {
324 Bucket *p, *q, **prev;
325 ulong nIndex;
326 zval *ppz;
327 TSRMLS_FETCH();
328
329 ht->nTableSize = source->nTableSize;
330 ht->nTableMask = source->nTableMask;
331 ht->nNumOfElements = source->nNumOfElements;
332 ht->nNextFreeElement = source->nNextFreeElement;
333 ht->pDestructor = ZVAL_PTR_DTOR;
334 #if ZEND_DEBUG
335 ht->inconsistent = 0;
336 #endif
337 ht->persistent = 0;
338 ht->arBuckets = NULL;
339 ht->pListHead = NULL;
340 ht->pListTail = NULL;
341 ht->pInternalPointer = NULL;
342 ht->nApplyCount = 0;
343 ht->bApplyProtection = 1;
344
345 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
346 if (!ht->nTableMask) {
347 ht->arBuckets = (Bucket**)&uninitialized_bucket;
348 return;
349 }
350 #endif
351
352 ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *));
353
354 prev = &ht->pListHead;
355 p = source->pListHead;
356 while (p) {
357 nIndex = p->h & ht->nTableMask;
358
359
360 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
361 if (!p->nKeyLength) {
362 q = (Bucket *) emalloc(sizeof(Bucket));
363 q->arKey = NULL;
364 } else if (IS_INTERNED(p->arKey)) {
365 q = (Bucket *) emalloc(sizeof(Bucket));
366 q->arKey = p->arKey;
367 } else {
368 q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);
369 q->arKey = ((char*)q) + sizeof(Bucket);
370 memcpy((char*)q->arKey, p->arKey, p->nKeyLength);
371 }
372 #else
373 q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength);
374 if (p->nKeyLength) {
375 memcpy(q->arKey, p->arKey, p->nKeyLength);
376 }
377 #endif
378 q->h = p->h;
379 q->nKeyLength = p->nKeyLength;
380
381
382 q->pNext = ht->arBuckets[nIndex];
383 q->pLast = NULL;
384 if (q->pNext) {
385 q->pNext->pLast = q;
386 }
387 ht->arBuckets[nIndex] = q;
388
389
390 q->pListLast = ht->pListTail;
391 ht->pListTail = q;
392 q->pListNext = NULL;
393 *prev = q;
394 prev = &q->pListNext;
395
396
397 q->pData = &q->pDataPtr;
398 if (!bind) {
399 ALLOC_ZVAL(ppz);
400 *ppz = *((zval*)p->pDataPtr);
401 INIT_PZVAL(ppz);
402 } else if (Z_REFCOUNT_P((zval*)p->pDataPtr) == 1) {
403 ALLOC_ZVAL(ppz);
404 *ppz = *((zval*)p->pDataPtr);
405 } else if (accel_xlat_get(p->pDataPtr, ppz) != SUCCESS) {
406 ALLOC_ZVAL(ppz);
407 *ppz = *((zval*)p->pDataPtr);
408 accel_xlat_set(p->pDataPtr, ppz);
409 } else {
410 q->pDataPtr = *(void**)ppz;
411 p = p->pListNext;
412 continue;
413 }
414 q->pDataPtr = (void*)ppz;
415
416 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
417 if ((Z_TYPE_P((zval*)p->pDataPtr) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
418 switch ((Z_TYPE_P((zval*)p->pDataPtr) & IS_CONSTANT_TYPE_MASK)) {
419 #else
420 if ((Z_TYPE_P((zval*)p->pDataPtr) & ~IS_CONSTANT_INDEX) >= IS_ARRAY) {
421 switch ((Z_TYPE_P((zval*)p->pDataPtr) & ~IS_CONSTANT_INDEX)) {
422 #endif
423 case IS_STRING:
424 case IS_CONSTANT:
425 Z_STRVAL_P(ppz) = (char *) interned_estrndup(Z_STRVAL_P((zval*)p->pDataPtr), Z_STRLEN_P((zval*)p->pDataPtr));
426 break;
427 case IS_ARRAY:
428 #if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
429 case IS_CONSTANT_ARRAY:
430 #endif
431 if (((zval*)p->pDataPtr)->value.ht && ((zval*)p->pDataPtr)->value.ht != &EG(symbol_table)) {
432 ALLOC_HASHTABLE(ppz->value.ht);
433 zend_hash_clone_zval(ppz->value.ht, ((zval*)p->pDataPtr)->value.ht, 0);
434 }
435 break;
436 #if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
437 case IS_CONSTANT_AST:
438 Z_AST_P(ppz) = zend_ast_clone(Z_AST_P(ppz) TSRMLS_CC);
439 break;
440 #endif
441 }
442 }
443
444 p = p->pListNext;
445 }
446 ht->pInternalPointer = ht->pListHead;
447 }
448
449 static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce TSRMLS_DC)
450 {
451 Bucket *p, *q, **prev;
452 ulong nIndex;
453 zend_class_entry **new_ce;
454 zend_function** new_prototype;
455 zend_op_array *new_entry;
456
457 ht->nTableSize = source->nTableSize;
458 ht->nTableMask = source->nTableMask;
459 ht->nNumOfElements = source->nNumOfElements;
460 ht->nNextFreeElement = source->nNextFreeElement;
461 ht->pDestructor = ZEND_FUNCTION_DTOR;
462 #if ZEND_DEBUG
463 ht->inconsistent = 0;
464 #endif
465 ht->persistent = 0;
466 ht->pListHead = NULL;
467 ht->pListTail = NULL;
468 ht->pInternalPointer = NULL;
469 ht->nApplyCount = 0;
470 ht->bApplyProtection = 1;
471
472 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
473 if (!ht->nTableMask) {
474 ht->arBuckets = (Bucket**)&uninitialized_bucket;
475 return;
476 }
477 #endif
478
479 ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *));
480
481 prev = &ht->pListHead;
482 p = source->pListHead;
483 while (p) {
484 nIndex = p->h & ht->nTableMask;
485
486
487 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
488 if (!p->nKeyLength) {
489 q = (Bucket *) emalloc(sizeof(Bucket));
490 q->arKey = NULL;
491 } else if (IS_INTERNED(p->arKey)) {
492 q = (Bucket *) emalloc(sizeof(Bucket));
493 q->arKey = p->arKey;
494 } else {
495 q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);
496 q->arKey = ((char*)q) + sizeof(Bucket);
497 memcpy((char*)q->arKey, p->arKey, p->nKeyLength);
498 }
499 #else
500 q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength);
501 if (p->nKeyLength) {
502 memcpy(q->arKey, p->arKey, p->nKeyLength);
503 }
504 #endif
505 q->h = p->h;
506 q->nKeyLength = p->nKeyLength;
507
508
509 q->pNext = ht->arBuckets[nIndex];
510 q->pLast = NULL;
511 if (q->pNext) {
512 q->pNext->pLast = q;
513 }
514 ht->arBuckets[nIndex] = q;
515
516
517 q->pListLast = ht->pListTail;
518 ht->pListTail = q;
519 q->pListNext = NULL;
520 *prev = q;
521 prev = &q->pListNext;
522
523
524 q->pData = (void *) emalloc(sizeof(zend_function));
525 new_entry = (zend_op_array*)q->pData;
526 *new_entry = *(zend_op_array*)p->pData;
527 q->pDataPtr = NULL;
528
529
530
531 if (new_entry->refcount != NULL) {
532 accel_xlat_set(p->pData, new_entry);
533 }
534
535 zend_prepare_function_for_execution(new_entry);
536
537 if (old_ce == new_entry->scope) {
538 new_entry->scope = ce;
539 } else {
540 if (accel_xlat_get(new_entry->scope, new_ce) == SUCCESS) {
541 new_entry->scope = *new_ce;
542 } else {
543 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name, new_entry->function_name);
544 }
545 }
546
547
548 if (new_entry->prototype) {
549 if (accel_xlat_get(new_entry->prototype, new_prototype) == SUCCESS) {
550 new_entry->prototype = *new_prototype;
551 } else {
552 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name, new_entry->function_name);
553 }
554 }
555
556 p = p->pListNext;
557 }
558 ht->pInternalPointer = ht->pListHead;
559 }
560
561 static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce TSRMLS_DC)
562 {
563 Bucket *p, *q, **prev;
564 ulong nIndex;
565 zend_class_entry **new_ce;
566 zend_property_info *prop_info;
567
568 ht->nTableSize = source->nTableSize;
569 ht->nTableMask = source->nTableMask;
570 ht->nNumOfElements = source->nNumOfElements;
571 ht->nNextFreeElement = source->nNextFreeElement;
572 ht->pDestructor = (dtor_func_t) zend_destroy_property_info;
573 #if ZEND_DEBUG
574 ht->inconsistent = 0;
575 #endif
576 ht->persistent = 0;
577 ht->pListHead = NULL;
578 ht->pListTail = NULL;
579 ht->pInternalPointer = NULL;
580 ht->nApplyCount = 0;
581 ht->bApplyProtection = 1;
582
583 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
584 if (!ht->nTableMask) {
585 ht->arBuckets = (Bucket**)&uninitialized_bucket;
586 return;
587 }
588 #endif
589
590 ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *));
591
592 prev = &ht->pListHead;
593 p = source->pListHead;
594 while (p) {
595 nIndex = p->h & ht->nTableMask;
596
597
598 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
599 if (!p->nKeyLength) {
600 q = (Bucket *) emalloc(sizeof(Bucket));
601 q->arKey = NULL;
602 } else if (IS_INTERNED(p->arKey)) {
603 q = (Bucket *) emalloc(sizeof(Bucket));
604 q->arKey = p->arKey;
605 } else {
606 q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);
607 q->arKey = ((char*)q) + sizeof(Bucket);
608 memcpy((char*)q->arKey, p->arKey, p->nKeyLength);
609 }
610 #else
611 q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength);
612 if (p->nKeyLength) {
613 memcpy(q->arKey, p->arKey, p->nKeyLength);
614 }
615 #endif
616 q->h = p->h;
617 q->nKeyLength = p->nKeyLength;
618
619
620 q->pNext = ht->arBuckets[nIndex];
621 q->pLast = NULL;
622 if (q->pNext) {
623 q->pNext->pLast = q;
624 }
625 ht->arBuckets[nIndex] = q;
626
627
628 q->pListLast = ht->pListTail;
629 ht->pListTail = q;
630 q->pListNext = NULL;
631 *prev = q;
632 prev = &q->pListNext;
633
634
635 q->pData = (void *) emalloc(sizeof(zend_property_info));
636 prop_info = q->pData;
637 *prop_info = *(zend_property_info*)p->pData;
638 q->pDataPtr = NULL;
639
640
641 prop_info->name = interned_estrndup(prop_info->name, prop_info->name_length);
642 if (prop_info->doc_comment) {
643 if (ZCG(accel_directives).load_comments) {
644 prop_info->doc_comment = estrndup(prop_info->doc_comment, prop_info->doc_comment_len);
645 } else {
646 prop_info->doc_comment = NULL;
647 }
648 }
649 if (prop_info->ce == old_ce) {
650 prop_info->ce = ce;
651 } else if (accel_xlat_get(prop_info->ce, new_ce) == SUCCESS) {
652 prop_info->ce = *new_ce;
653 } else {
654 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s, property %s", ce->name, prop_info->name);
655 }
656
657 p = p->pListNext;
658 }
659 ht->pInternalPointer = ht->pListHead;
660 }
661
662
663 static int zend_prepare_function_for_execution(zend_op_array *op_array)
664 {
665 HashTable *shared_statics = op_array->static_variables;
666
667
668 op_array->refcount = &zend_accel_refcount;
669 (*op_array->refcount) = ZEND_PROTECTED_REFCOUNT;
670
671
672 if (shared_statics) {
673 ALLOC_HASHTABLE(op_array->static_variables);
674 zend_hash_clone_zval(op_array->static_variables, shared_statics, 0);
675 }
676
677 return 0;
678 }
679
680 #define zend_update_inherited_handler(handler) \
681 { \
682 if (ce->handler != NULL) { \
683 if (accel_xlat_get(ce->handler, new_func) == SUCCESS) { \
684 ce->handler = *new_func; \
685 } else { \
686 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s", ce->name); \
687 } \
688 } \
689 }
690
691
692 static void zend_class_copy_ctor(zend_class_entry **pce)
693 {
694 zend_class_entry *ce = *pce;
695 zend_class_entry *old_ce = ce;
696 zend_class_entry **new_ce;
697 zend_function **new_func;
698 TSRMLS_FETCH();
699
700 *pce = ce = emalloc(sizeof(zend_class_entry));
701 *ce = *old_ce;
702 ce->refcount = 1;
703
704 if (old_ce->refcount != 1) {
705
706 accel_xlat_set(old_ce, ce);
707 }
708
709 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
710 if (old_ce->default_properties_table) {
711 int i;
712
713 ce->default_properties_table = emalloc(sizeof(zval*) * old_ce->default_properties_count);
714 for (i = 0; i < old_ce->default_properties_count; i++) {
715 if (old_ce->default_properties_table[i]) {
716 ce->default_properties_table[i] = zend_clone_zval(old_ce->default_properties_table[i], 0 TSRMLS_CC);
717 } else {
718 ce->default_properties_table[i] = NULL;
719 }
720 }
721 }
722 #else
723 zend_hash_clone_zval(&ce->default_properties, &old_ce->default_properties, 0);
724 #endif
725
726 zend_hash_clone_methods(&ce->function_table, &old_ce->function_table, old_ce, ce TSRMLS_CC);
727
728
729 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
730 if (old_ce->default_static_members_table) {
731 int i;
732
733 ce->default_static_members_table = emalloc(sizeof(zval*) * old_ce->default_static_members_count);
734 for (i = 0; i < old_ce->default_static_members_count; i++) {
735 if (old_ce->default_static_members_table[i]) {
736 ce->default_static_members_table[i] = zend_clone_zval(old_ce->default_static_members_table[i], 1 TSRMLS_CC);
737 } else {
738 ce->default_static_members_table[i] = NULL;
739 }
740 }
741 }
742 ce->static_members_table = ce->default_static_members_table;
743 #else
744 zend_hash_clone_zval(&ce->default_static_members, &old_ce->default_static_members, 1);
745 ce->static_members = &ce->default_static_members;
746 #endif
747
748
749 zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce, ce TSRMLS_CC);
750
751
752 zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 0);
753
754 ce->name = interned_estrndup(ce->name, ce->name_length);
755
756
757 if (ce->num_interfaces) {
758 ce->interfaces = emalloc(sizeof(zend_class_entry *) * ce->num_interfaces);
759 memset(ce->interfaces, 0, sizeof(zend_class_entry *) * ce->num_interfaces);
760 } else {
761 ce->interfaces = NULL;
762 }
763 if (ZEND_CE_DOC_COMMENT(ce)) {
764 if (ZCG(accel_directives).load_comments) {
765 ZEND_CE_DOC_COMMENT(ce) = estrndup(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce));
766 } else {
767 ZEND_CE_DOC_COMMENT(ce) = NULL;
768 }
769 }
770
771 if (ce->parent) {
772 if (accel_xlat_get(ce->parent, new_ce) == SUCCESS) {
773 ce->parent = *new_ce;
774 } else {
775 zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s", ce->name);
776 }
777 }
778
779 zend_update_inherited_handler(constructor);
780 zend_update_inherited_handler(destructor);
781 zend_update_inherited_handler(clone);
782 zend_update_inherited_handler(__get);
783 zend_update_inherited_handler(__set);
784 zend_update_inherited_handler(__call);
785
786 zend_update_inherited_handler(serialize_func);
787 zend_update_inherited_handler(unserialize_func);
788 zend_update_inherited_handler(__isset);
789 zend_update_inherited_handler(__unset);
790
791 zend_update_inherited_handler(__tostring);
792
793 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
794
795 zend_update_inherited_handler(__callstatic);
796 #endif
797
798 #if ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
799
800 zend_update_inherited_handler(__debugInfo);
801 #endif
802
803 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
804
805 if (ce->trait_aliases) {
806 zend_trait_alias **trait_aliases;
807 int i = 0;
808
809 while (ce->trait_aliases[i]) {
810 i++;
811 }
812 trait_aliases = emalloc(sizeof(zend_trait_alias*) * (i + 1));
813 i = 0;
814 while (ce->trait_aliases[i]) {
815 trait_aliases[i] = emalloc(sizeof(zend_trait_alias));
816 memcpy(trait_aliases[i], ce->trait_aliases[i], sizeof(zend_trait_alias));
817 trait_aliases[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
818 memcpy(trait_aliases[i]->trait_method, ce->trait_aliases[i]->trait_method, sizeof(zend_trait_method_reference));
819 if (trait_aliases[i]->trait_method) {
820 if (trait_aliases[i]->trait_method->method_name) {
821 trait_aliases[i]->trait_method->method_name =
822 estrndup(trait_aliases[i]->trait_method->method_name,
823 trait_aliases[i]->trait_method->mname_len);
824 }
825 if (trait_aliases[i]->trait_method->class_name) {
826 trait_aliases[i]->trait_method->class_name =
827 estrndup(trait_aliases[i]->trait_method->class_name,
828 trait_aliases[i]->trait_method->cname_len);
829 }
830 }
831
832 if (trait_aliases[i]->alias) {
833 trait_aliases[i]->alias =
834 estrndup(trait_aliases[i]->alias,
835 trait_aliases[i]->alias_len);
836 }
837 i++;
838 }
839 trait_aliases[i] = NULL;
840 ce->trait_aliases = trait_aliases;
841 }
842
843 if (ce->trait_precedences) {
844 zend_trait_precedence **trait_precedences;
845 int i = 0;
846
847 while (ce->trait_precedences[i]) {
848 i++;
849 }
850 trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i + 1));
851 i = 0;
852 while (ce->trait_precedences[i]) {
853 trait_precedences[i] = emalloc(sizeof(zend_trait_precedence));
854 memcpy(trait_precedences[i], ce->trait_precedences[i], sizeof(zend_trait_precedence));
855 trait_precedences[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
856 memcpy(trait_precedences[i]->trait_method, ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference));
857
858 trait_precedences[i]->trait_method->method_name =
859 estrndup(trait_precedences[i]->trait_method->method_name,
860 trait_precedences[i]->trait_method->mname_len);
861 trait_precedences[i]->trait_method->class_name =
862 estrndup(trait_precedences[i]->trait_method->class_name,
863 trait_precedences[i]->trait_method->cname_len);
864
865 if (trait_precedences[i]->exclude_from_classes) {
866 zend_class_entry **exclude_from_classes;
867 int j = 0;
868
869 while (trait_precedences[i]->exclude_from_classes[j]) {
870 j++;
871 }
872 exclude_from_classes = emalloc(sizeof(zend_class_entry*) * (j + 1));
873 j = 0;
874 while (trait_precedences[i]->exclude_from_classes[j]) {
875 exclude_from_classes[j] = (zend_class_entry*)estrndup(
876 (char*)trait_precedences[i]->exclude_from_classes[j],
877 strlen((char*)trait_precedences[i]->exclude_from_classes[j]));
878 j++;
879 }
880 exclude_from_classes[j] = NULL;
881 trait_precedences[i]->exclude_from_classes = exclude_from_classes;
882 }
883 i++;
884 }
885 trait_precedences[i] = NULL;
886 ce->trait_precedences = trait_precedences;
887 }
888 #endif
889 }
890
891 static int zend_hash_unique_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor, uint size, int ignore_dups, void **fail_data, void **conflict_data)
892 {
893 Bucket *p;
894 void *t;
895
896 p = source->pListHead;
897 while (p) {
898 if (p->nKeyLength > 0) {
899 if (zend_hash_quick_add(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t) == SUCCESS) {
900 if (pCopyConstructor) {
901 pCopyConstructor(t);
902 }
903 } else {
904 if (p->nKeyLength > 0 && p->arKey[0] == 0) {
905
906 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
907 if (zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t) == SUCCESS) {
908 if (pCopyConstructor) {
909 pCopyConstructor(t);
910 }
911 }
912 #endif
913 } else if (!ignore_dups && zend_hash_quick_find(target, p->arKey, p->nKeyLength, p->h, &t) == SUCCESS) {
914 *fail_data = p->pData;
915 *conflict_data = t;
916 return FAILURE;
917 }
918 }
919 } else {
920 if (!zend_hash_index_exists(target, p->h) && zend_hash_index_update(target, p->h, p->pData, size, &t) == SUCCESS) {
921 if (pCopyConstructor) {
922 pCopyConstructor(t);
923 }
924 } else if (!ignore_dups && zend_hash_index_find(target,p->h, &t) == SUCCESS) {
925 *fail_data = p->pData;
926 *conflict_data = t;
927 return FAILURE;
928 }
929 }
930 p = p->pListNext;
931 }
932 target->pInternalPointer = target->pListHead;
933
934 return SUCCESS;
935 }
936
937 static void zend_accel_function_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor)
938 {
939 zend_function *function1, *function2;
940 TSRMLS_FETCH();
941
942 if (zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_function), 0, (void**)&function1, (void**)&function2) != SUCCESS) {
943 CG(in_compilation) = 1;
944 zend_set_compiled_filename(function1->op_array.filename TSRMLS_CC);
945 CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
946 if (function2->type == ZEND_USER_FUNCTION
947 && function2->op_array.last > 0) {
948 zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
949 function1->common.function_name,
950 function2->op_array.filename,
951 (int)function2->op_array.opcodes[0].lineno);
952 } else {
953 zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name);
954 }
955 }
956 }
957
958 static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor TSRMLS_DC)
959 {
960 zend_class_entry **pce1, **pce2;
961
962 if (zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_class_entry*), ZCG(accel_directives).ignore_dups, (void**)&pce1, (void**)&pce2) != SUCCESS) {
963 CG(in_compilation) = 1;
964 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
965 zend_set_compiled_filename((*pce1)->info.user.filename TSRMLS_CC);
966 CG(zend_lineno) = (*pce1)->info.user.line_start;
967 #else
968 zend_set_compiled_filename((*pce1)->filename TSRMLS_CC);
969 CG(zend_lineno) = (*pce1)->line_start;
970 #endif
971 zend_error(E_ERROR, "Cannot redeclare class %s", (*pce1)->name);
972 }
973 }
974
975 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
976 static void zend_do_delayed_early_binding(zend_op_array *op_array, zend_uint early_binding TSRMLS_DC)
977 {
978 zend_uint opline_num = early_binding;
979
980 if ((int)opline_num != -1) {
981 zend_bool orig_in_compilation = CG(in_compilation);
982 char *orig_compiled_filename = zend_set_compiled_filename(op_array->filename TSRMLS_CC);
983 zend_class_entry **pce;
984
985 CG(in_compilation) = 1;
986 while ((int)opline_num != -1) {
987 if (zend_lookup_class(Z_STRVAL(op_array->opcodes[opline_num - 1].op2.u.constant), Z_STRLEN(op_array->opcodes[opline_num - 1].op2.u.constant), &pce TSRMLS_CC) == SUCCESS) {
988 do_bind_inherited_class(&op_array->opcodes[opline_num], EG(class_table), *pce, 1 TSRMLS_CC);
989 }
990 opline_num = op_array->opcodes[opline_num].result.u.opline_num;
991 }
992 zend_restore_compiled_filename(orig_compiled_filename TSRMLS_CC);
993 CG(in_compilation) = orig_in_compilation;
994 }
995 }
996 #endif
997
998 zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory TSRMLS_DC)
999 {
1000 zend_op_array *op_array;
1001
1002 op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
1003 *op_array = persistent_script->main_op_array;
1004
1005 if (from_shared_memory) {
1006
1007 if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
1008 zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0);
1009 zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor TSRMLS_CC);
1010 zend_hash_destroy(&ZCG(bind_hash));
1011 }
1012
1013
1014 if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
1015 zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table, (unique_copy_ctor_func_t)zend_prepare_function_for_execution);
1016 }
1017
1018 zend_prepare_function_for_execution(op_array);
1019
1020
1021 if (persistent_script->compiler_halt_offset != 0 &&
1022 persistent_script->full_path) {
1023 char *name, *cfilename;
1024 char haltoff[] = "__COMPILER_HALT_OFFSET__";
1025 int len, clen;
1026
1027 cfilename = persistent_script->full_path;
1028 clen = strlen(cfilename);
1029 zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0);
1030 if (!zend_hash_exists(EG(zend_constants), name, len + 1)) {
1031 zend_register_long_constant(name, len + 1, persistent_script->compiler_halt_offset, CONST_CS, 0 TSRMLS_CC);
1032 }
1033 efree(name);
1034 }
1035
1036 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
1037 if ((int)persistent_script->early_binding != -1) {
1038 zend_do_delayed_early_binding(op_array, persistent_script->early_binding TSRMLS_CC);
1039 }
1040 #endif
1041
1042 } else {
1043 if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
1044 zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table, NULL);
1045 }
1046 if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
1047 zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, NULL TSRMLS_CC);
1048 }
1049 }
1050
1051 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
1052 if (op_array->early_binding != (zend_uint)-1) {
1053 char *orig_compiled_filename = CG(compiled_filename);
1054 CG(compiled_filename) = persistent_script->full_path;
1055 zend_do_delayed_early_binding(op_array TSRMLS_CC);
1056 CG(compiled_filename) = orig_compiled_filename;
1057 }
1058 #endif
1059
1060 if (!from_shared_memory) {
1061 free_persistent_script(persistent_script, 0);
1062 }
1063
1064 return op_array;
1065 }
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094 #define ADLER32_BASE 65521
1095 #define ADLER32_NMAX 5552
1096
1097
1098 #define ADLER32_DO1(buf) {s1 += *(buf); s2 += s1;}
1099 #define ADLER32_DO2(buf, i) ADLER32_DO1(buf + i); ADLER32_DO1(buf + i + 1);
1100 #define ADLER32_DO4(buf, i) ADLER32_DO2(buf, i); ADLER32_DO2(buf, i + 2);
1101 #define ADLER32_DO8(buf, i) ADLER32_DO4(buf, i); ADLER32_DO4(buf, i + 4);
1102 #define ADLER32_DO16(buf) ADLER32_DO8(buf, 0); ADLER32_DO8(buf, 8);
1103
1104 unsigned int zend_adler32(unsigned int checksum, signed char *buf, uint len)
1105 {
1106 unsigned int s1 = checksum & 0xffff;
1107 unsigned int s2 = (checksum >> 16) & 0xffff;
1108 signed char *end;
1109
1110 while (len >= ADLER32_NMAX) {
1111 len -= ADLER32_NMAX;
1112 end = buf + ADLER32_NMAX;
1113 do {
1114 ADLER32_DO16(buf);
1115 buf += 16;
1116 } while (buf != end);
1117 s1 %= ADLER32_BASE;
1118 s2 %= ADLER32_BASE;
1119 }
1120
1121 if (len) {
1122 if (len >= 16) {
1123 end = buf + (len & 0xfff0);
1124 len &= 0xf;
1125 do {
1126 ADLER32_DO16(buf);
1127 buf += 16;
1128 } while (buf != end);
1129 }
1130 if (len) {
1131 end = buf + len;
1132 do {
1133 ADLER32_DO1(buf);
1134 buf++;
1135 } while (buf != end);
1136 }
1137 s1 %= ADLER32_BASE;
1138 s2 %= ADLER32_BASE;
1139 }
1140
1141 return (s2 << 16) | s1;
1142 }