1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
11 : | If you did not receive a copy of the Zend license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@zend.com so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Andi Gutmans <andi@zend.com> |
16 : | Zeev Suraski <zeev@zend.com> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zend_execute.h 288293 2009-09-13 14:42:36Z felipe $ */
21 :
22 : #ifndef ZEND_EXECUTE_H
23 : #define ZEND_EXECUTE_H
24 :
25 : #include "zend_compile.h"
26 : #include "zend_hash.h"
27 : #include "zend_operators.h"
28 : #include "zend_variables.h"
29 :
30 : typedef union _temp_variable {
31 : zval tmp_var;
32 : struct {
33 : zval **ptr_ptr;
34 : zval *ptr;
35 : zend_bool fcall_returned_reference;
36 : } var;
37 : struct {
38 : zval **ptr_ptr;
39 : zval *ptr;
40 : zend_bool fcall_returned_reference;
41 : zval *str;
42 : zend_uint offset;
43 : } str_offset;
44 : struct {
45 : zval **ptr_ptr;
46 : zval *ptr;
47 : zend_bool fcall_returned_reference;
48 : HashPointer fe_pos;
49 : } fe;
50 : zend_class_entry *class_entry;
51 : } temp_variable;
52 :
53 :
54 : BEGIN_EXTERN_C()
55 : ZEND_API extern void (*zend_execute)(zend_op_array *op_array TSRMLS_DC);
56 : ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
57 :
58 : void init_executor(TSRMLS_D);
59 : void shutdown_executor(TSRMLS_D);
60 : void shutdown_destructors(TSRMLS_D);
61 : ZEND_API void execute(zend_op_array *op_array TSRMLS_DC);
62 : ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
63 : ZEND_API int zend_is_true(zval *op);
64 : #define safe_free_zval_ptr(p) safe_free_zval_ptr_rel(p ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
65 : static inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
66 0 : {
67 : TSRMLS_FETCH();
68 :
69 0 : if (p!=EG(uninitialized_zval_ptr)) {
70 0 : FREE_ZVAL_REL(p);
71 : }
72 0 : }
73 : ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
74 : ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC);
75 : ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
76 : ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC);
77 : ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
78 : ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
79 :
80 : static inline int i_zend_is_true(zval *op)
81 6535084 : {
82 : int result;
83 :
84 6535084 : switch (Z_TYPE_P(op)) {
85 : case IS_NULL:
86 36217 : result = 0;
87 36217 : break;
88 : case IS_LONG:
89 : case IS_BOOL:
90 : case IS_RESOURCE:
91 6348205 : result = (Z_LVAL_P(op)?1:0);
92 6348205 : break;
93 : case IS_DOUBLE:
94 19 : result = (Z_DVAL_P(op) ? 1 : 0);
95 19 : break;
96 : case IS_STRING:
97 36010 : if (Z_STRLEN_P(op) == 0
98 : || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
99 407 : result = 0;
100 : } else {
101 35196 : result = 1;
102 : }
103 35603 : break;
104 : case IS_ARRAY:
105 114740 : result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
106 114740 : break;
107 : case IS_OBJECT:
108 300 : if(IS_ZEND_STD_OBJECT(*op)) {
109 : TSRMLS_FETCH();
110 :
111 300 : if (Z_OBJ_HT_P(op)->cast_object) {
112 : zval tmp;
113 300 : if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_BOOL TSRMLS_CC) == SUCCESS) {
114 300 : result = Z_LVAL(tmp);
115 300 : break;
116 : }
117 0 : } else if (Z_OBJ_HT_P(op)->get) {
118 0 : zval *tmp = Z_OBJ_HT_P(op)->get(op TSRMLS_CC);
119 0 : if(Z_TYPE_P(tmp) != IS_OBJECT) {
120 : /* for safety - avoid loop */
121 0 : convert_to_boolean(tmp);
122 0 : result = Z_LVAL_P(tmp);
123 0 : zval_ptr_dtor(&tmp);
124 0 : break;
125 : }
126 : }
127 : }
128 0 : result = 1;
129 0 : break;
130 : default:
131 0 : result = 0;
132 : break;
133 : }
134 6535084 : return result;
135 : }
136 :
137 : ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC);
138 : ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC);
139 :
140 : /* dedicated Zend executor functions - do not use! */
141 : #define ZEND_VM_STACK_PAGE_SIZE ((64 * 1024) - 64)
142 :
143 : struct _zend_vm_stack {
144 : void **top;
145 : void **end;
146 : zend_vm_stack prev;
147 : };
148 :
149 : #define ZEND_VM_STACK_ELEMETS(stack) \
150 : ((void**)(((char*)(stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack))))
151 :
152 : #define ZEND_VM_STACK_GROW_IF_NEEDED(count) \
153 : do { \
154 : if (UNEXPECTED((count) > \
155 : EG(argument_stack)->end - EG(argument_stack)->top)) { \
156 : zend_vm_stack_extend((count) TSRMLS_CC); \
157 : } \
158 : } while (0)
159 :
160 17623 : static inline zend_vm_stack zend_vm_stack_new_page(int count) {
161 17623 : zend_vm_stack page = (zend_vm_stack)emalloc(ZEND_MM_ALIGNED_SIZE(sizeof(*page)) + sizeof(void*) * count);
162 :
163 17623 : page->top = ZEND_VM_STACK_ELEMETS(page);
164 17623 : page->end = page->top + count;
165 17623 : page->prev = NULL;
166 17623 : return page;
167 : }
168 :
169 : static inline void zend_vm_stack_init(TSRMLS_D)
170 17619 : {
171 17619 : EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE);
172 17619 : }
173 :
174 : static inline void zend_vm_stack_destroy(TSRMLS_D)
175 17651 : {
176 17651 : zend_vm_stack stack = EG(argument_stack);
177 :
178 52956 : while (stack != NULL) {
179 17654 : zend_vm_stack p = stack->prev;
180 17654 : efree(stack);
181 17654 : stack = p;
182 : }
183 17651 : }
184 :
185 : static inline void zend_vm_stack_extend(int count TSRMLS_DC)
186 4 : {
187 4 : zend_vm_stack p = zend_vm_stack_new_page(count >= ZEND_VM_STACK_PAGE_SIZE ? count : ZEND_VM_STACK_PAGE_SIZE);
188 4 : p->prev = EG(argument_stack);
189 4 : EG(argument_stack) = p;
190 4 : }
191 :
192 : static inline void **zend_vm_stack_top(TSRMLS_D)
193 41796428 : {
194 41796428 : return EG(argument_stack)->top;
195 : }
196 :
197 : static inline void zend_vm_stack_push(void *ptr TSRMLS_DC)
198 28897945 : {
199 28897945 : ZEND_VM_STACK_GROW_IF_NEEDED(1);
200 28897945 : *(EG(argument_stack)->top++) = ptr;
201 28897945 : }
202 :
203 : static inline void zend_vm_stack_push_nocheck(void *ptr TSRMLS_DC)
204 836581 : {
205 836581 : *(EG(argument_stack)->top++) = ptr;
206 836581 : }
207 :
208 : static inline void *zend_vm_stack_pop(TSRMLS_D)
209 62 : {
210 62 : void *el = *(--EG(argument_stack)->top);
211 :
212 62 : if (UNEXPECTED(EG(argument_stack)->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)))) {
213 0 : zend_vm_stack p = EG(argument_stack);
214 0 : EG(argument_stack) = p->prev;
215 0 : efree(p);
216 : }
217 62 : return el;
218 : }
219 :
220 : static inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
221 1232868 : {
222 : void *ret;
223 :
224 1232868 : size = (size + (sizeof(void*) - 1)) / sizeof(void*);
225 :
226 : /* the following comparison must be optimized out at compile time */
227 : if (ZEND_MM_ALIGNMENT > sizeof(void*)) {
228 : int extra = (ZEND_MM_ALIGNMENT - ((zend_uintptr_t)EG(argument_stack)->top & (ZEND_MM_ALIGNMENT - 1))) / sizeof(void*);
229 :
230 : if (UNEXPECTED(size + extra + ZEND_MM_ALIGNED_SIZE(sizeof(void*)) / sizeof(void*) >
231 : (zend_uintptr_t)EG(argument_stack)->end - (zend_uintptr_t)EG(argument_stack)->top)) {
232 : zend_vm_stack_extend(size TSRMLS_CC);
233 : } else {
234 : void **old_top = EG(argument_stack)->top;
235 :
236 : EG(argument_stack)->top += extra;
237 : /* store old top on the stack */
238 : *EG(argument_stack)->top = (void*)old_top;
239 : EG(argument_stack)->top += ZEND_MM_ALIGNED_SIZE(sizeof(void*)) / sizeof(void*);
240 : }
241 : } else {
242 1232868 : ZEND_VM_STACK_GROW_IF_NEEDED((int)size);
243 : }
244 1232868 : ret = (void*)EG(argument_stack)->top;
245 1232868 : EG(argument_stack)->top += size;
246 1232868 : return ret;
247 : }
248 :
249 : static inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC)
250 16828689 : {
251 16828689 : if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) {
252 0 : zend_vm_stack p = EG(argument_stack);
253 :
254 0 : EG(argument_stack) = p->prev;
255 0 : efree(p);
256 : } else {
257 16828689 : EG(argument_stack)->top = (void**)ptr;
258 : }
259 16828689 : }
260 :
261 : static inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
262 1231630 : {
263 1231630 : if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) {
264 0 : zend_vm_stack p = EG(argument_stack);
265 :
266 0 : EG(argument_stack) = p->prev;
267 0 : efree(p);
268 : } else {
269 : /* the following comparison must be optimized out at compile time */
270 : if (ZEND_MM_ALIGNMENT > sizeof(void*)) {
271 : ptr = (void*)(((char*)ptr) - ZEND_MM_ALIGNED_SIZE(sizeof(void*)));
272 : EG(argument_stack)->top = *(void***)ptr;
273 : } else {
274 1231630 : EG(argument_stack)->top = (void**)ptr;
275 : }
276 : }
277 1231630 : }
278 :
279 : static inline void** zend_vm_stack_push_args(int count TSRMLS_DC)
280 16451852 : {
281 :
282 16451852 : if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count) ||
283 : UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) {
284 1 : zend_vm_stack p = EG(argument_stack);
285 :
286 1 : zend_vm_stack_extend(count + 1 TSRMLS_CC);
287 :
288 1 : EG(argument_stack)->top += count;
289 1 : *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count;
290 65580 : while (count-- > 0) {
291 65578 : void *data = *(--p->top);
292 :
293 65578 : if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) {
294 1 : zend_vm_stack r = p;
295 :
296 1 : EG(argument_stack)->prev = p->prev;
297 1 : p = p->prev;
298 1 : efree(r);
299 : }
300 65578 : *(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count) = data;
301 : }
302 1 : return EG(argument_stack)->top++;
303 : }
304 16451851 : *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count;
305 16451851 : return EG(argument_stack)->top++;
306 : }
307 :
308 : static inline void zend_vm_stack_clear_multiple(TSRMLS_D)
309 16828689 : {
310 16828689 : void **p = EG(argument_stack)->top - 1;
311 16828689 : int delete_count = (int)(zend_uintptr_t) *p;
312 :
313 62931134 : while (--delete_count>=0) {
314 29273756 : zval *q = *(zval **)(--p);
315 29273756 : *p = NULL;
316 29273756 : zval_ptr_dtor(&q);
317 : }
318 16828689 : zend_vm_stack_free_int(p TSRMLS_CC);
319 16828689 : }
320 :
321 : static inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC)
322 3134247 : {
323 3134247 : void **p = EG(current_execute_data)->prev_execute_data->function_state.arguments;
324 3134247 : int arg_count = (int)(zend_uintptr_t) *p;
325 :
326 3134247 : if (UNEXPECTED(requested_arg > arg_count)) {
327 43538 : return NULL;
328 : }
329 3090709 : return (zval**)p - arg_count + requested_arg - 1;
330 : }
331 :
332 : static inline void zend_arg_types_stack_2_pop(zend_ptr_stack *stack, zval **object, zend_function **fbc)
333 19 : {
334 : void *a, *b;
335 :
336 19 : zend_ptr_stack_2_pop(stack, &a, &b);
337 :
338 19 : *object = (zval *) a;
339 19 : *fbc = (zend_function *) b;
340 19 : }
341 :
342 : static inline void zend_arg_types_stack_3_pop(zend_ptr_stack *stack, zend_class_entry **called_scope, zval **object, zend_function **fbc)
343 16451852 : {
344 : void *a, *b, *c;
345 :
346 16451852 : zend_ptr_stack_3_pop(stack, &a, &b, &c);
347 :
348 16451852 : *called_scope = (zend_class_entry *) a;
349 16451852 : *object = (zval *) b;
350 16451852 : *fbc = (zend_function *) c;
351 16451852 : }
352 :
353 : void execute_new_code(TSRMLS_D);
354 :
355 :
356 : /* services */
357 : ZEND_API char *get_active_class_name(char **space TSRMLS_DC);
358 : ZEND_API char *get_active_function_name(TSRMLS_D);
359 : ZEND_API char *zend_get_executed_filename(TSRMLS_D);
360 : ZEND_API uint zend_get_executed_lineno(TSRMLS_D);
361 : ZEND_API zend_bool zend_is_executing(TSRMLS_D);
362 :
363 : ZEND_API void zend_set_timeout(long seconds, int reset_signals);
364 : ZEND_API void zend_unset_timeout(TSRMLS_D);
365 : ZEND_API void zend_timeout(int dummy);
366 : ZEND_API zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC);
367 : void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
368 :
369 : #ifdef ZEND_WIN32
370 : void zend_init_timeout_thread(void);
371 : void zend_shutdown_timeout_thread(void);
372 : #define WM_REGISTER_ZEND_TIMEOUT (WM_USER+1)
373 : #define WM_UNREGISTER_ZEND_TIMEOUT (WM_USER+2)
374 : #endif
375 :
376 : #define zendi_zval_copy_ctor(p) zval_copy_ctor(&(p))
377 : #define zendi_zval_dtor(p) zval_dtor(&(p))
378 :
379 : #define active_opline (*EG(opline_ptr))
380 :
381 : /* The following tries to resolve the classname of a zval of type object.
382 : * Since it is slow it should be only used in error messages.
383 : */
384 : #define Z_OBJ_CLASS_NAME_P(zval) ((zval) && Z_TYPE_P(zval) == IS_OBJECT && Z_OBJ_HT_P(zval)->get_class_entry != NULL && Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC) ? Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC)->name : "")
385 :
386 : ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var);
387 :
388 : #define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */
389 : #define ZEND_USER_OPCODE_RETURN 1 /* exit from executor (return from function) */
390 : #define ZEND_USER_OPCODE_DISPATCH 2 /* call original opcode handler */
391 : #define ZEND_USER_OPCODE_ENTER 3 /* enter into new op_array without recursion */
392 : #define ZEND_USER_OPCODE_LEAVE 4 /* return to calling op_array within the same executor */
393 :
394 : #define ZEND_USER_OPCODE_DISPATCH_TO 0x100 /* call original handler of returned opcode */
395 :
396 : ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler);
397 : ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode);
398 :
399 : /* former zend_execute_locks.h */
400 : typedef struct _zend_free_op {
401 : zval* var;
402 : /* int is_var; */
403 : } zend_free_op;
404 :
405 : ZEND_API zval *zend_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC);
406 : ZEND_API zval **zend_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC);
407 :
408 : ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS);
409 :
410 : END_EXTERN_C()
411 :
412 : #endif /* ZEND_EXECUTE_H */
413 :
414 : /*
415 : * Local variables:
416 : * tab-width: 4
417 : * c-basic-offset: 4
418 : * indent-tabs-mode: t
419 : * End:
420 : */
|