source: trunk/processor/head.m4 @ 4

Last change on this file since 4 was 4, checked in by moo, 9 years ago

compatibility fix: remove the using of gnu m4 extension

File size: 8.5 KB
RevLine 
[1]1dnl {{{ === program start ========================================
2divert(0)
3#include <string.h>
4#include <stdio.h>
5
6#include "php.h"
7#include "zend_compile.h"
8#include "zend_API.h"
[4]9#include "zend_ini.h"
[1]10
11#include "xcache.h"
12#include "align.h"
13#include "const_string.h"
14#include "processor.h"
15#include "stack.h"
16#include "xcache_globals.h"
17
18define(`SIZEOF_zend_uint', `sizeof(zend_uint)')
19define(`COUNTOF_zend_uint', `1')
20define(`SIZEOF_int', `sizeof(int)')
21define(`COUNTOF_int', `1')
22define(`SIZEOF_zend_function', `sizeof(zend_function)')
23define(`COUNTOF_zend_function', `1')
24define(`SIZEOF_zval_ptr', `sizeof(zval_ptr)')
25define(`COUNTOF_zval_ptr', `1')
26define(`SIZEOF_xc_entry_name_t', `sizeof(xc_entry_name_t)')
27define(`COUNTOF_xc_entry_name_t', `1')
28
29ifdef(`XCACHE_ENABLE_TEST', `
30#undef NDEBUG
31#include <assert.h>
[4]32include(builddir`/structinfo.m4')
[1]33')
34#ifndef NDEBUG
35#   undef inline
36#define inline
37#endif
38
39typedef zval *zval_ptr;
40typedef zend_uchar zval_data_type;
41
42#define MAX_DUP_STR_LEN 256
43dnl }}}
44/* export: typedef struct _processor_t processor_t; :export {{{ */
45struct _processor_t {
46    char *p;
47    zend_uint size;
48    HashTable strings;
49    HashTable zvalptrs;
50    zend_bool reference; /* enable if to deal with reference */
51    const xc_entry_t *xce_src;
52    const xc_entry_t *xce_dst;
53    const zend_class_entry *cache_ce;
54    zend_uint cache_class_num;
55
56    const zend_op          *active_opcodes_src;
57    zend_op                *active_opcodes_dst;
58    const zend_class_entry *active_class_entry_src;
59    zend_class_entry       *active_class_entry_dst;
60    zend_uint               active_class_num;
61
62    zend_bool readonly_protection; /* wheather it's present */
63IFASSERT(xc_stack_t allocsizes;)
64};
65/* }}} */
66#ifdef XCACHE_HAVE_DPRINT
67static void xc_dprint_indent(int indent) /* {{{ */
68{
69    int i;
70    for (i = 0; i < indent; i ++) {
71        fprintf(stderr, "  ");
72    }
73}
74#endif
75/* }}} */
76/* {{{ xc_calc_string_n */
77REDEF(`KIND', `calc')
78static inline void xc_calc_string_n(processor_t *processor, zend_uchar type, char *str, long size IFASSERT(`, int relayline')) {
79    pushdef(`__LINE__', `relayline')
80    int realsize = UNISW(size, (type == IS_UNICODE) ? UBYTES(size) : size);
81
82    if (realsize > MAX_DUP_STR_LEN) {
83        ALLOC(, char, realsize)
84    }
85    else if (zend_u_hash_add(&processor->strings, type, str, size, (void*)&str, sizeof(char*), NULL) == SUCCESS) {
86        /* new string */
87        ALLOC(, char, realsize)
88    }
89    IFASSERT(`
90        else {
91            dnl fprintf(stderr, "dupstr %s\n", str);
92        }
93    ')
94    popdef(`__LINE__')
95}
96/* }}} */
97/* {{{ xc_store_string_n */
98REDEF(`KIND', `store')
99static inline char *xc_store_string_n(processor_t *processor, zend_uchar type, char *str, long size IFASSERT(`, int relayline')) {
100    pushdef(`__LINE__', `relayline')
101    int realsize = UNISW(size, (type == IS_UNICODE) ? UBYTES(size) : size);
102    char *s;
103
104    if (realsize > MAX_DUP_STR_LEN) {
105        ALLOC(s, char, realsize)
106        memcpy(s, str, realsize);
107    }
108    else if (zend_u_hash_find(&processor->strings, type, str, size, (void*)&s) != SUCCESS) {
109        /* new string */
110        ALLOC(s, char, realsize)
111        memcpy(s, str, realsize);
112        zend_u_hash_add(&processor->strings, type, str, size, (void*)&s, sizeof(char*), NULL);
113    }
114    else {
115        s = *(char**)s;
116    }
117    return s;
118    popdef(`__LINE__')
119}
120/* }}} */
121/* {{{ xc_get_class_num
122 * return class_index + 1
123 */
124static zend_uint xc_get_class_num(processor_t *processor, zend_class_entry *ce) {
125    zend_uint i;
126    const xc_entry_t *xce = processor->xce_src;
127    zend_class_entry *ceptr;
128
129    if (processor->cache_ce == ce) {
130        return processor->cache_class_num;
131    }
132    for (i = 0; i < xce->data.php->classinfo_cnt; i ++) {
133        ceptr = CestToCePtr(xce->data.php->classinfos[i].cest);
134        if (ZCEP_REFCOUNT_PTR(ceptr) == ZCEP_REFCOUNT_PTR(ce)) {
135            processor->cache_ce = ceptr;
136            processor->cache_class_num = i + 1;
137            return i + 1;
138        }
139    }
140    assert(0);
141    return (zend_uint) -1;
142}
143/* }}} */
144/* {{{ xc_get_class */
145#ifdef ZEND_ENGINE_2
146static zend_class_entry *xc_get_class(processor_t *processor, zend_uint class_num) {
147    /* must be parent or currrent class */
148    assert(class_num <= processor->active_class_num);
149    return CestToCePtr(processor->xce_dst->data.php->classinfos[class_num - 1].cest);
150}
151#endif
152/* }}} */
153#ifdef ZEND_ENGINE_2
154/* fix method on store */
155static void xc_fix_method(processor_t *processor, zend_op_array *dst) /* {{{ */
156{
157    zend_function *zf = (zend_function *) dst;
158    zend_class_entry *ce = processor->active_class_entry_dst;
159
160    /* Fixing up the default functions for objects here since
161     * we need to compare with the newly allocated functions
162     *
163     * caveat: a sub-class method can have the same name as the
164     * parent~s constructor and create problems.
165     */
166
167    if (zf->common.fn_flags & ZEND_ACC_CTOR) {
168        if (!ce->constructor) {
169            ce->constructor = zf;
170        }
171    }
172    else if (zf->common.fn_flags & ZEND_ACC_DTOR) {
173        ce->destructor = zf;
174    }
175    else if (zf->common.fn_flags & ZEND_ACC_CLONE) {
176        ce->clone = zf;
177    }
178    else {
179#define SET_IF_SAME_NAME(member) \
180        do { \
181            if(!strcasecmp(zf->common.function_name, #member)) { \
182                ce->member = zf; \
183            } \
184        } \
185        while(0)
186        /* if(ce->member && !strcmp(zf->common.function_name, ce->member->common.function_name)) { \ */
187
188        SET_IF_SAME_NAME(__get);
189        SET_IF_SAME_NAME(__set);
190        SET_IF_SAME_NAME(__unset);
191        SET_IF_SAME_NAME(__isset);
192        SET_IF_SAME_NAME(__call);
193#if PHP_MAJOR_VERSION >= 6
194        SET_IF_SAME_NAME(__tostring);
195#endif
196
197#undef SET_IF_SAME_NAME
198    }
199}
200/* }}} */
201#endif
202dnl ================ export API
203/* export: xc_entry_t *xc_processor_store_xc_entry_t(xc_entry_t *src TSRMLS_DC); :export {{{ */
204xc_entry_t *xc_processor_store_xc_entry_t(xc_entry_t *src TSRMLS_DC) {
205    xc_entry_t *dst;
206    processor_t processor;
207
208    memset(&processor, 0, sizeof(processor));
209    if (src->type == XC_TYPE_VAR) {
210        processor.reference = 1;
211    }
212
213    IFASSERT(`xc_stack_init(&processor.allocsizes);')
214
215    /* calc size */ {
216        zend_hash_init(&processor.strings, 0, NULL, NULL, 0);
217        if (processor.reference) {
218            zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0);
219        }
220
221        processor.size = 0;
222        /* allocate */
223        processor.size = ALIGN(processor.size + sizeof(src[0]));
224
225        xc_calc_xc_entry_t(&processor, src TSRMLS_CC);
226        if (processor.reference) {
227            zend_hash_destroy(&processor.zvalptrs);
228        }
229        zend_hash_destroy(&processor.strings);
230    }
231    src->size = processor.size;
232
233    IFASSERT(`xc_stack_reverse(&processor.allocsizes);')
234    /* store {{{ */
235    {
236        IFASSERT(`char *oldp;')
237        zend_hash_init(&processor.strings, 0, NULL, NULL, 0);
238        if (processor.reference) {
239            zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0);
240        }
241
242        /* mem :) */
243        processor.p = (char *)xc_mem_malloc(src->cache->mem, processor.size);
244        if (processor.p == NULL) {
245            dst = NULL;
246            goto err_alloc;
247            return NULL;
248        }
249        IFASSERT(`oldp = processor.p;')
250        assert(processor.p == (char *) ALIGN(processor.p));
251
252        /* allocate */
253        dst = (xc_entry_t *) processor.p;
254        processor.p = (char *) ALIGN(processor.p + sizeof(dst[0]));
255
256        xc_store_xc_entry_t(&processor, dst, src TSRMLS_CC);
257        IFASSERT(` {
258            int real = processor.p - oldp;
259            int should = processor.size;
260            if (real != processor.size) {
261                fprintf(stderr, "real %d - should %d = %d\n", real, should, real - should);
262                abort();
263            }
264        }')
265err_alloc:
266        if (processor.reference) {
267            zend_hash_destroy(&processor.zvalptrs);
268        }
269        zend_hash_destroy(&processor.strings);
270    }
271    /* }}} */
272
273    IFASSERT(`xc_stack_destroy(&processor.allocsizes);')
274
275    return dst;
276}
277/* }}} */
278/* export: xc_entry_t *xc_processor_restore_xc_entry_t(xc_entry_t *dst, const xc_entry_t *src, zend_bool readonly_protection TSRMLS_DC); :export {{{ */
279xc_entry_t *xc_processor_restore_xc_entry_t(xc_entry_t *dst, const xc_entry_t *src, zend_bool readonly_protection TSRMLS_DC) {
280    processor_t processor;
281
282    memset(&processor, 0, sizeof(processor));
283    processor.readonly_protection = readonly_protection;
284
285    xc_restore_xc_entry_t(&processor, dst, src TSRMLS_CC);
286    return dst;
287}
288/* }}} */
289/* export: zval *xc_processor_restore_zval(zval *dst, const zval *src TSRMLS_DC); :export {{{ */
290zval *xc_processor_restore_zval(zval *dst, const zval *src TSRMLS_DC) {
291    processor_t processor;
292
293    memset(&processor, 0, sizeof(processor));
294    processor.reference = 1;
295
296    zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0);
297    dnl fprintf(stderr, "mark[%p] = %p\n", src, dst);
298    zend_hash_add(&processor.zvalptrs, (char *)src, sizeof(src), (void*)&dst, sizeof(dst), NULL);
299    xc_restore_zval(&processor, dst, src TSRMLS_CC);
300    zend_hash_destroy(&processor.zvalptrs);
301
302    return dst;
303}
304/* }}} */
305/* export: void xc_dprint(xc_entry_t *src, int indent TSRMLS_DC); :export {{{ */
306#ifdef XCACHE_HAVE_DPRINT
307void xc_dprint(xc_entry_t *src, int indent TSRMLS_DC) {
308    IFDPRINT(`INDENT()`'fprintf(stderr, "xc_entry_t:src");')
309    xc_dprint_xc_entry_t(src, indent TSRMLS_CC);
310}
311#endif
312/* }}} */
Note: See TracBrowser for help on using the repository browser.