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 UChar u_main[sizeof("main")];
56 : ZEND_API extern UChar u_return[sizeof("return ")];
57 : ZEND_API extern UChar u_doublecolon[sizeof("::")];
58 :
59 : ZEND_API extern void (*zend_execute)(zend_op_array *op_array TSRMLS_DC);
60 : ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
61 :
62 : void init_executor(TSRMLS_D);
63 : void shutdown_executor(TSRMLS_D);
64 : void shutdown_destructors(TSRMLS_D);
65 : ZEND_API void execute(zend_op_array *op_array TSRMLS_DC);
66 : ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
67 : ZEND_API int zend_is_true(zval *op);
68 : #define safe_free_zval_ptr(p) safe_free_zval_ptr_rel(p ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
69 : static inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
70 0 : {
71 : TSRMLS_FETCH();
72 :
73 0 : if (p!=EG(uninitialized_zval_ptr)) {
74 0 : FREE_ZVAL_REL(p);
75 : }
76 0 : }
77 : ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
78 : ZEND_API int zend_lookup_class_ex(char *name, int name_length, char *autoload_name, zend_class_entry ***ce TSRMLS_DC);
79 : ZEND_API int zend_u_lookup_class(zend_uchar type, zstr name, int name_length, zend_class_entry ***ce TSRMLS_DC);
80 : ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, zstr autoload_name, int do_normalize, zend_class_entry ***ce TSRMLS_DC);
81 : ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
82 : ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC);
83 : ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
84 : ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
85 : ZEND_API int zend_u_eval_string(zend_uchar type, zstr str, zval *retval_ptr, char *string_name TSRMLS_DC);
86 : ZEND_API int zend_u_eval_stringl(zend_uchar type, zstr str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC);
87 : ZEND_API int zend_u_eval_string_ex(zend_uchar type, zstr str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
88 : ZEND_API int zend_u_eval_stringl_ex(zend_uchar type, zstr str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
89 :
90 : static inline int i_zend_is_true(zval *op)
91 34610641 : {
92 : int result;
93 :
94 34610641 : switch (Z_TYPE_P(op)) {
95 : case IS_NULL:
96 35273 : result = 0;
97 35273 : break;
98 : case IS_LONG:
99 : case IS_BOOL:
100 : case IS_RESOURCE:
101 34405585 : result = (Z_LVAL_P(op)?1:0);
102 34405585 : break;
103 : case IS_DOUBLE:
104 19 : result = (Z_DVAL_P(op) ? 1 : 0);
105 19 : break;
106 : case IS_STRING:
107 25835 : if (Z_STRLEN_P(op) == 0
108 : || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
109 56 : result = 0;
110 : } else {
111 25723 : result = 1;
112 : }
113 25779 : break;
114 : case IS_UNICODE:
115 35258 : if (Z_USTRLEN_P(op) == 0
116 : || (Z_USTRLEN_P(op)==1 && Z_USTRVAL_P(op)[0]=='0')) {
117 279 : result = 0;
118 : } else {
119 34700 : result = 1;
120 : }
121 34979 : break;
122 : case IS_ARRAY:
123 108700 : result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
124 108700 : break;
125 : case IS_OBJECT:
126 306 : if(IS_ZEND_STD_OBJECT(*op)) {
127 : TSRMLS_FETCH();
128 :
129 306 : if (Z_OBJ_HT_P(op)->cast_object) {
130 : zval tmp;
131 306 : if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_BOOL, NULL TSRMLS_CC) == SUCCESS) {
132 306 : result = Z_LVAL(tmp);
133 306 : break;
134 : }
135 0 : } else if (Z_OBJ_HT_P(op)->get) {
136 0 : zval *tmp = Z_OBJ_HT_P(op)->get(op TSRMLS_CC);
137 0 : if(Z_TYPE_P(tmp) != IS_OBJECT) {
138 : /* for safety - avoid loop */
139 0 : convert_to_boolean(tmp);
140 0 : result = Z_LVAL_P(tmp);
141 0 : zval_ptr_dtor(&tmp);
142 0 : break;
143 : }
144 : }
145 : }
146 0 : result = 1;
147 0 : break;
148 : default:
149 0 : result = 0;
150 : break;
151 : }
152 34610641 : return result;
153 : }
154 :
155 : ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC);
156 : ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC);
157 :
158 : /* dedicated Zend executor functions - do not use! */
159 : #define ZEND_VM_STACK_PAGE_SIZE ((64 * 1024) - 64)
160 :
161 : struct _zend_vm_stack {
162 : void **top;
163 : void **end;
164 : zend_vm_stack prev;
165 : };
166 :
167 : #define ZEND_VM_STACK_ELEMETS(stack) \
168 : ((void**)(((char*)(stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack))))
169 :
170 : #define ZEND_VM_STACK_GROW_IF_NEEDED(count) \
171 : do { \
172 : if (UNEXPECTED((count) > \
173 : EG(argument_stack)->end - EG(argument_stack)->top)) { \
174 : zend_vm_stack_extend((count) TSRMLS_CC); \
175 : } \
176 : } while (0)
177 :
178 16997 : static inline zend_vm_stack zend_vm_stack_new_page(int count) {
179 16997 : zend_vm_stack page = (zend_vm_stack)emalloc(ZEND_MM_ALIGNED_SIZE(sizeof(*page)) + sizeof(void*) * count);
180 :
181 16997 : page->top = ZEND_VM_STACK_ELEMETS(page);
182 16997 : page->end = page->top + count;
183 16997 : page->prev = NULL;
184 16997 : return page;
185 : }
186 :
187 : static inline void zend_vm_stack_init(TSRMLS_D)
188 16993 : {
189 16993 : EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE);
190 16993 : }
191 :
192 : static inline void zend_vm_stack_destroy(TSRMLS_D)
193 17025 : {
194 17025 : zend_vm_stack stack = EG(argument_stack);
195 :
196 51078 : while (stack != NULL) {
197 17028 : zend_vm_stack p = stack->prev;
198 17028 : efree(stack);
199 17028 : stack = p;
200 : }
201 17025 : }
202 :
203 : static inline void zend_vm_stack_extend(int count TSRMLS_DC)
204 4 : {
205 4 : zend_vm_stack p = zend_vm_stack_new_page(count >= ZEND_VM_STACK_PAGE_SIZE ? count : ZEND_VM_STACK_PAGE_SIZE);
206 4 : p->prev = EG(argument_stack);
207 4 : EG(argument_stack) = p;
208 4 : }
209 :
210 : static inline void **zend_vm_stack_top(TSRMLS_D)
211 81065150 : {
212 81065150 : return EG(argument_stack)->top;
213 : }
214 :
215 : static inline void zend_vm_stack_push(void *ptr TSRMLS_DC)
216 113701533 : {
217 113701533 : ZEND_VM_STACK_GROW_IF_NEEDED(1);
218 113701533 : *(EG(argument_stack)->top++) = ptr;
219 113701533 : }
220 :
221 : static inline void zend_vm_stack_push_nocheck(void *ptr TSRMLS_DC)
222 963871 : {
223 963871 : *(EG(argument_stack)->top++) = ptr;
224 963871 : }
225 :
226 : static inline void *zend_vm_stack_pop(TSRMLS_D)
227 62 : {
228 62 : void *el = *(--EG(argument_stack)->top);
229 :
230 62 : if (UNEXPECTED(EG(argument_stack)->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)))) {
231 0 : zend_vm_stack p = EG(argument_stack);
232 0 : EG(argument_stack) = p->prev;
233 0 : efree(p);
234 : }
235 62 : return el;
236 : }
237 :
238 : static inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
239 13542532 : {
240 : void *ret;
241 :
242 13542532 : size = (size + (sizeof(void*) - 1)) / sizeof(void*);
243 :
244 : /* the following comparison must be optimized out at compile time */
245 : if (ZEND_MM_ALIGNMENT > sizeof(void*)) {
246 : int extra = (ZEND_MM_ALIGNMENT - ((zend_uintptr_t)EG(argument_stack)->top & (ZEND_MM_ALIGNMENT - 1))) / sizeof(void*);
247 :
248 : if (UNEXPECTED(size + extra + ZEND_MM_ALIGNED_SIZE(sizeof(void*)) / sizeof(void*) >
249 : (zend_uintptr_t)EG(argument_stack)->end - (zend_uintptr_t)EG(argument_stack)->top)) {
250 : zend_vm_stack_extend(size TSRMLS_CC);
251 : } else {
252 : void **old_top = EG(argument_stack)->top;
253 :
254 : EG(argument_stack)->top += extra;
255 : /* store old top on the stack */
256 : *EG(argument_stack)->top = (void*)old_top;
257 : EG(argument_stack)->top += ZEND_MM_ALIGNED_SIZE(sizeof(void*)) / sizeof(void*);
258 : }
259 : } else {
260 13542532 : ZEND_VM_STACK_GROW_IF_NEEDED((int)size);
261 : }
262 13542532 : ret = (void*)EG(argument_stack)->top;
263 13542532 : EG(argument_stack)->top += size;
264 13542532 : return ret;
265 : }
266 :
267 : static inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC)
268 36063726 : {
269 36063726 : if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) {
270 0 : zend_vm_stack p = EG(argument_stack);
271 :
272 0 : EG(argument_stack) = p->prev;
273 0 : efree(p);
274 : } else {
275 36063726 : EG(argument_stack)->top = (void**)ptr;
276 : }
277 36063726 : }
278 :
279 : static inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
280 13541147 : {
281 13541147 : if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) {
282 0 : zend_vm_stack p = EG(argument_stack);
283 :
284 0 : EG(argument_stack) = p->prev;
285 0 : efree(p);
286 : } else {
287 : /* the following comparison must be optimized out at compile time */
288 : if (ZEND_MM_ALIGNMENT > sizeof(void*)) {
289 : ptr = (void*)(((char*)ptr) - ZEND_MM_ALIGNED_SIZE(sizeof(void*)));
290 : EG(argument_stack)->top = *(void***)ptr;
291 : } else {
292 13541147 : EG(argument_stack)->top = (void**)ptr;
293 : }
294 : }
295 13541147 : }
296 :
297 : static inline void** zend_vm_stack_push_args(int count TSRMLS_DC)
298 35644152 : {
299 :
300 35644152 : if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count) ||
301 : UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) {
302 1 : zend_vm_stack p = EG(argument_stack);
303 :
304 1 : zend_vm_stack_extend(count + 1 TSRMLS_CC);
305 :
306 1 : EG(argument_stack)->top += count;
307 1 : *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count;
308 65580 : while (count-- > 0) {
309 65578 : void *data = *(--p->top);
310 :
311 65578 : if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) {
312 1 : zend_vm_stack r = p;
313 :
314 1 : EG(argument_stack)->prev = p->prev;
315 1 : p = p->prev;
316 1 : efree(r);
317 : }
318 65578 : *(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count) = data;
319 : }
320 1 : return EG(argument_stack)->top++;
321 : }
322 35644151 : *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count;
323 35644151 : return EG(argument_stack)->top++;
324 : }
325 :
326 : static inline void zend_vm_stack_clear_multiple(TSRMLS_D)
327 36063726 : {
328 36063726 : void **p = EG(argument_stack)->top - 1;
329 36063726 : int delete_count = (int)(zend_uintptr_t) *p;
330 :
331 186289909 : while (--delete_count>=0) {
332 114162457 : zval *q = *(zval **)(--p);
333 114162457 : *p = NULL;
334 114162457 : zval_ptr_dtor(&q);
335 : }
336 36063726 : zend_vm_stack_free_int(p TSRMLS_CC);
337 36063726 : }
338 :
339 : static inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC)
340 74153406 : {
341 74153406 : void **p = EG(current_execute_data)->prev_execute_data->function_state.arguments;
342 74153406 : int arg_count = (int)(zend_uintptr_t) *p;
343 :
344 74153406 : if (UNEXPECTED(requested_arg > arg_count)) {
345 41091 : return NULL;
346 : }
347 74112315 : return (zval**)p - arg_count + requested_arg - 1;
348 : }
349 :
350 : static inline void zend_arg_types_stack_2_pop(zend_ptr_stack *stack, zval **object, zend_function **fbc)
351 19 : {
352 : void *a, *b;
353 :
354 19 : zend_ptr_stack_2_pop(stack, &a, &b);
355 :
356 19 : *object = (zval *) a;
357 19 : *fbc = (zend_function *) b;
358 19 : }
359 :
360 : static inline void zend_arg_types_stack_3_pop(zend_ptr_stack *stack, zend_class_entry **called_scope, zval **object, zend_function **fbc)
361 35644152 : {
362 : void *a, *b, *c;
363 :
364 35644152 : zend_ptr_stack_3_pop(stack, &a, &b, &c);
365 :
366 35644152 : *called_scope = (zend_class_entry *) a;
367 35644152 : *object = (zval *) b;
368 35644152 : *fbc = (zend_function *) c;
369 35644152 : }
370 :
371 : void execute_new_code(TSRMLS_D);
372 :
373 :
374 : /* services */
375 : ZEND_API zstr get_active_class_name(char **space TSRMLS_DC);
376 : ZEND_API zstr get_active_function_name(TSRMLS_D);
377 : ZEND_API char *zend_get_executed_filename(TSRMLS_D);
378 : ZEND_API uint zend_get_executed_lineno(TSRMLS_D);
379 : ZEND_API zend_bool zend_is_executing(TSRMLS_D);
380 :
381 : ZEND_API void zend_set_timeout(long seconds, int reset_signals);
382 : ZEND_API void zend_unset_timeout(TSRMLS_D);
383 : ZEND_API void zend_timeout(int dummy);
384 : ZEND_API zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC);
385 : ZEND_API zend_class_entry *zend_u_fetch_class(zend_uchar type, zstr class_name, uint class_name_len, int fetch_type TSRMLS_DC);
386 : void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
387 :
388 : #ifdef ZEND_WIN32
389 : void zend_init_timeout_thread(void);
390 : void zend_shutdown_timeout_thread(void);
391 : #define WM_REGISTER_ZEND_TIMEOUT (WM_USER+1)
392 : #define WM_UNREGISTER_ZEND_TIMEOUT (WM_USER+2)
393 : #endif
394 :
395 : #define zendi_zval_copy_ctor(p) zval_copy_ctor(&(p))
396 : #define zendi_zval_dtor(p) zval_dtor(&(p))
397 :
398 : #define active_opline (*EG(opline_ptr))
399 :
400 : /* The following tries to resolve the classname of a zval of type object.
401 : * Since it is slow it should be only used in error messages.
402 : */
403 : #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 : EMPTY_ZSTR)
404 :
405 : ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var);
406 :
407 : void init_unicode_strings(void);
408 :
409 : #define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */
410 : #define ZEND_USER_OPCODE_RETURN 1 /* exit from executor (return from function) */
411 : #define ZEND_USER_OPCODE_DISPATCH 2 /* call original opcode handler */
412 : #define ZEND_USER_OPCODE_ENTER 3 /* enter into new op_array without recursion */
413 : #define ZEND_USER_OPCODE_LEAVE 4 /* return to calling op_array within the same executor */
414 :
415 : #define ZEND_USER_OPCODE_DISPATCH_TO 0x100 /* call original handler of returned opcode */
416 :
417 : ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler);
418 : ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode);
419 :
420 : /* former zend_execute_locks.h */
421 : typedef struct _zend_free_op {
422 : zval* var;
423 : /* int is_var; */
424 : } zend_free_op;
425 :
426 : ZEND_API zval *zend_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC);
427 : ZEND_API zval **zend_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC);
428 :
429 : ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS);
430 :
431 : END_EXTERN_C()
432 :
433 : #endif /* ZEND_EXECUTE_H */
434 :
435 : /*
436 : * Local variables:
437 : * tab-width: 4
438 : * c-basic-offset: 4
439 : * indent-tabs-mode: t
440 : * End:
441 : */
|