root/Zend/zend_execute.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. BEGIN_EXTERN_C
  2. i_zval_ptr_dtor_nogc
  3. i_zend_is_true
  4. zend_vm_stack_new_page
  5. zend_vm_stack_init
  6. zend_vm_stack_destroy
  7. zend_vm_stack_extend
  8. zend_vm_stack_top
  9. zend_vm_stack_push
  10. zend_vm_stack_pop
  11. zend_vm_stack_alloc
  12. zend_vm_stack_frame_base
  13. zend_vm_stack_free_int
  14. zend_vm_stack_free
  15. zend_vm_stack_clear_multiple
  16. zend_vm_stack_get_args_count_ex
  17. zend_vm_stack_get_arg_ex
  18. zend_vm_stack_get_args_count
  19. zend_vm_stack_get_arg

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend Engine                                                          |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 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$ */
  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; /* shared with var.ptr_ptr */
  39                 zval *str;
  40                 zend_uint offset;
  41         } str_offset;
  42         struct {
  43                 zval **ptr_ptr; /* shared with var.ptr_ptr */
  44                 zval *ptr;      /* shared with var.ptr */
  45                 HashPointer fe_pos;
  46         } fe;
  47         zend_class_entry *class_entry;
  48 } temp_variable;
  49 
  50 
  51 BEGIN_EXTERN_C()
  52 struct _zend_fcall_info;
  53 ZEND_API extern void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC);
  54 ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_value_used TSRMLS_DC);
  55 
  56 void init_executor(TSRMLS_D);
  57 void shutdown_executor(TSRMLS_D);
  58 void shutdown_destructors(TSRMLS_D);
  59 ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC);
  60 ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC);
  61 ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC);
  62 ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_value_used TSRMLS_DC);
  63 ZEND_API int zend_is_true(zval *op);
  64 ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
  65 ZEND_API int zend_lookup_class_ex(const char *name, int name_length, const zend_literal *key, int use_autoload, zend_class_entry ***ce TSRMLS_DC);
  66 ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
  67 ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC);
  68 ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
  69 ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
  70 
  71 ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, const char **class_name, zend_class_entry **pce TSRMLS_DC);
  72 ZEND_API int zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC);
  73 
  74 static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
  75 {
  76         if (!Z_DELREF_P(zval_ptr)) {
  77                 ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval));
  78                 GC_REMOVE_ZVAL_FROM_BUFFER(zval_ptr);
  79                 zval_dtor(zval_ptr);
  80                 efree_rel(zval_ptr);
  81         } else {
  82                 if (Z_REFCOUNT_P(zval_ptr) == 1) {
  83                         Z_UNSET_ISREF_P(zval_ptr);
  84                 }
  85 
  86                 GC_ZVAL_CHECK_POSSIBLE_ROOT(zval_ptr);
  87         }
  88 }
  89 
  90 static zend_always_inline void i_zval_ptr_dtor_nogc(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
  91 {
  92         if (!Z_DELREF_P(zval_ptr)) {
  93                 ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval));
  94                 GC_REMOVE_ZVAL_FROM_BUFFER(zval_ptr);
  95                 zval_dtor(zval_ptr);
  96                 efree_rel(zval_ptr);
  97         } else {
  98                 if (Z_REFCOUNT_P(zval_ptr) == 1) {
  99                         Z_UNSET_ISREF_P(zval_ptr);
 100                 }
 101         }
 102 }
 103 
 104 static zend_always_inline int i_zend_is_true(zval *op)
 105 {
 106         int result;
 107 
 108         switch (Z_TYPE_P(op)) {
 109                 case IS_NULL:
 110                         result = 0;
 111                         break;
 112                 case IS_LONG:
 113                 case IS_BOOL:
 114                 case IS_RESOURCE:
 115                         result = (Z_LVAL_P(op)?1:0);
 116                         break;
 117                 case IS_DOUBLE:
 118                         result = (Z_DVAL_P(op) ? 1 : 0);
 119                         break;
 120                 case IS_STRING:
 121                         if (Z_STRLEN_P(op) == 0
 122                                 || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
 123                                 result = 0;
 124                         } else {
 125                                 result = 1;
 126                         }
 127                         break;
 128                 case IS_ARRAY:
 129                         result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
 130                         break;
 131                 case IS_OBJECT:
 132                         if(IS_ZEND_STD_OBJECT(*op)) {
 133                                 TSRMLS_FETCH();
 134 
 135                                 if (Z_OBJ_HT_P(op)->cast_object) {
 136                                         zval tmp;
 137                                         if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_BOOL TSRMLS_CC) == SUCCESS) {
 138                                                 result = Z_LVAL(tmp);
 139                                                 break;
 140                                         }
 141                                 } else if (Z_OBJ_HT_P(op)->get) {
 142                                         zval *tmp = Z_OBJ_HT_P(op)->get(op TSRMLS_CC);
 143                                         if(Z_TYPE_P(tmp) != IS_OBJECT) {
 144                                                 /* for safety - avoid loop */
 145                                                 convert_to_boolean(tmp);
 146                                                 result = Z_LVAL_P(tmp);
 147                                                 zval_ptr_dtor(&tmp);
 148                                                 break;
 149                                         }
 150                                 }
 151                         }
 152                         result = 1;
 153                         break;
 154                 default:
 155                         result = 0;
 156                         break;
 157         }
 158         return result;
 159 }
 160 
 161 ZEND_API int zval_update_constant(zval **pp, zend_bool inline_change TSRMLS_DC);
 162 ZEND_API int zval_update_constant_inline_change(zval **pp, zend_class_entry *scope TSRMLS_DC);
 163 ZEND_API int zval_update_constant_no_inline_change(zval **pp, zend_class_entry *scope TSRMLS_DC);
 164 ZEND_API int zval_update_constant_ex(zval **pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC);
 165 
 166 /* dedicated Zend executor functions - do not use! */
 167 #define ZEND_VM_STACK_PAGE_SIZE ((16 * 1024) - 16)
 168 
 169 struct _zend_vm_stack {
 170         void **top;
 171         void **end;
 172         zend_vm_stack prev;
 173 };
 174 
 175 #define ZEND_VM_STACK_ELEMETS(stack) \
 176         ((void**)(((char*)(stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack))))
 177 
 178 #define ZEND_VM_STACK_GROW_IF_NEEDED(count)                                                     \
 179         do {                                                                                                                    \
 180                 if (UNEXPECTED((count) >                                                                        \
 181                     EG(argument_stack)->end - EG(argument_stack)->top)) {       \
 182                         zend_vm_stack_extend((count) TSRMLS_CC);                                \
 183                 }                                                                                                                       \
 184         } while (0)
 185 
 186 static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
 187         zend_vm_stack page = (zend_vm_stack)emalloc(ZEND_MM_ALIGNED_SIZE(sizeof(*page)) + sizeof(void*) * count);
 188 
 189         page->top = ZEND_VM_STACK_ELEMETS(page);
 190         page->end = page->top + count;
 191         page->prev = NULL;
 192         return page;
 193 }
 194 
 195 static zend_always_inline void zend_vm_stack_init(TSRMLS_D)
 196 {
 197         EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE);
 198 }
 199 
 200 static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
 201 {
 202         zend_vm_stack stack = EG(argument_stack);
 203 
 204         while (stack != NULL) {
 205                 zend_vm_stack p = stack->prev;
 206                 efree(stack);
 207                 stack = p;
 208         }
 209 }
 210 
 211 static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC)
 212 {
 213         zend_vm_stack p = zend_vm_stack_new_page(count >= ZEND_VM_STACK_PAGE_SIZE ? count : ZEND_VM_STACK_PAGE_SIZE);
 214         p->prev = EG(argument_stack);
 215         EG(argument_stack) = p;
 216 }
 217 
 218 static zend_always_inline void **zend_vm_stack_top(TSRMLS_D)
 219 {
 220         return EG(argument_stack)->top;
 221 }
 222 
 223 static zend_always_inline void zend_vm_stack_push(void *ptr TSRMLS_DC)
 224 {
 225         *(EG(argument_stack)->top++) = ptr;
 226 }
 227 
 228 static zend_always_inline void *zend_vm_stack_pop(TSRMLS_D)
 229 {
 230         void *el = *(--EG(argument_stack)->top);
 231 
 232         return el;
 233 }
 234 
 235 static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
 236 {
 237         void *ret;
 238 
 239         size = (size + (sizeof(void*) - 1)) / sizeof(void*);
 240 
 241         /* the following comparison must be optimized out at compile time */
 242         if (ZEND_MM_ALIGNMENT > sizeof(void*)) {
 243                 int extra = (ZEND_MM_ALIGNMENT - ((zend_uintptr_t)EG(argument_stack)->top & (ZEND_MM_ALIGNMENT - 1))) / sizeof(void*);
 244 
 245                 if (UNEXPECTED(size + extra + ZEND_MM_ALIGNED_SIZE(sizeof(void*)) / sizeof(void*) >
 246                     (zend_uintptr_t)(EG(argument_stack)->end - EG(argument_stack)->top))) {
 247                         zend_vm_stack_extend(size TSRMLS_CC);
 248                 } else {
 249                         void **old_top = EG(argument_stack)->top;
 250 
 251                         EG(argument_stack)->top += extra;
 252                         /* store old top on the stack */
 253                         *EG(argument_stack)->top = (void*)old_top;
 254                         EG(argument_stack)->top += ZEND_MM_ALIGNED_SIZE(sizeof(void*)) / sizeof(void*);
 255                 }
 256         } else {
 257                 ZEND_VM_STACK_GROW_IF_NEEDED((int)size);
 258         }
 259         ret = (void*)EG(argument_stack)->top;
 260         EG(argument_stack)->top += size;
 261         return ret;
 262 }
 263 
 264 static zend_always_inline void** zend_vm_stack_frame_base(zend_execute_data *ex)
 265 {
 266         return (void**)((char*)ex->call_slots +
 267                 ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * ex->op_array->nested_calls);
 268 }
 269 
 270 static zend_always_inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC)
 271 {
 272         if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) {
 273                 zend_vm_stack p = EG(argument_stack);
 274 
 275                 EG(argument_stack) = p->prev;
 276                 efree(p);
 277         } else {
 278                 EG(argument_stack)->top = (void**)ptr;
 279         }
 280 }
 281 
 282 static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
 283 {
 284         if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) {
 285                 zend_vm_stack p = EG(argument_stack);
 286 
 287                 EG(argument_stack) = p->prev;
 288                 efree(p);
 289         } else {
 290                 /* the following comparison must be optimized out at compile time */
 291                 if (ZEND_MM_ALIGNMENT > sizeof(void*)) {
 292                         ptr = (void*)(((char*)ptr) - ZEND_MM_ALIGNED_SIZE(sizeof(void*)));
 293                         EG(argument_stack)->top = *(void***)ptr;
 294                 } else {
 295                         EG(argument_stack)->top = (void**)ptr;
 296                 }
 297         }
 298 }
 299 
 300 static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC)
 301 {
 302         void **p = EG(argument_stack)->top - 1;
 303         void **end = p - (int)(zend_uintptr_t)*p;
 304 
 305         while (p != end) {
 306                 zval *q = (zval *) *(--p);
 307                 *p = NULL;
 308                 i_zval_ptr_dtor(q ZEND_FILE_LINE_CC TSRMLS_CC);
 309         }
 310         if (nested) {
 311                 EG(argument_stack)->top = p;
 312         } else {
 313                 zend_vm_stack_free_int(p TSRMLS_CC);
 314         }
 315 }
 316 
 317 static zend_always_inline int zend_vm_stack_get_args_count_ex(zend_execute_data *ex)
 318 {
 319         if (ex) {
 320                 void **p = ex->function_state.arguments;
 321                 return (int)(zend_uintptr_t) *p;
 322         } else {
 323                 return 0;                       
 324         }
 325 }
 326 
 327 static zend_always_inline zval** zend_vm_stack_get_arg_ex(zend_execute_data *ex, int requested_arg)
 328 {
 329         void **p = ex->function_state.arguments;
 330         int arg_count = (int)(zend_uintptr_t) *p;
 331 
 332         if (UNEXPECTED(requested_arg > arg_count)) {
 333                 return NULL;
 334         }
 335         return (zval**)p - arg_count + requested_arg - 1;
 336 }
 337 
 338 static zend_always_inline int zend_vm_stack_get_args_count(TSRMLS_D)
 339 {
 340         return zend_vm_stack_get_args_count_ex(EG(current_execute_data)->prev_execute_data);
 341 }
 342 
 343 static zend_always_inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC)
 344 {
 345         return zend_vm_stack_get_arg_ex(EG(current_execute_data)->prev_execute_data, requested_arg);
 346 }
 347 
 348 void execute_new_code(TSRMLS_D);
 349 
 350 
 351 /* services */
 352 ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC);
 353 ZEND_API const char *get_active_function_name(TSRMLS_D);
 354 ZEND_API const char *zend_get_executed_filename(TSRMLS_D);
 355 ZEND_API uint zend_get_executed_lineno(TSRMLS_D);
 356 ZEND_API zend_bool zend_is_executing(TSRMLS_D);
 357 
 358 ZEND_API void zend_set_timeout(long seconds, int reset_signals);
 359 ZEND_API void zend_unset_timeout(TSRMLS_D);
 360 ZEND_API void zend_timeout(int dummy);
 361 ZEND_API zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC);
 362 ZEND_API zend_class_entry *zend_fetch_class_by_name(const char *class_name, uint class_name_len, const zend_literal *key, int fetch_type TSRMLS_DC);
 363 void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
 364 
 365 ZEND_API void zend_fetch_dimension_by_zval(zval **result, zval *container, zval *dim TSRMLS_DC);
 366 
 367 #define zendi_zval_copy_ctor(p) zval_copy_ctor(&(p))
 368 #define zendi_zval_dtor(p) zval_dtor(&(p))
 369 
 370 #define active_opline (*EG(opline_ptr))
 371 
 372 /* The following tries to resolve the classname of a zval of type object.
 373  * Since it is slow it should be only used in error messages.
 374  */
 375 #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 : "")
 376 
 377 ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var);
 378 
 379 #define ZEND_USER_OPCODE_CONTINUE   0 /* execute next opcode */
 380 #define ZEND_USER_OPCODE_RETURN     1 /* exit from executor (return from function) */
 381 #define ZEND_USER_OPCODE_DISPATCH   2 /* call original opcode handler */
 382 #define ZEND_USER_OPCODE_ENTER      3 /* enter into new op_array without recursion */
 383 #define ZEND_USER_OPCODE_LEAVE      4 /* return to calling op_array within the same executor */
 384 
 385 #define ZEND_USER_OPCODE_DISPATCH_TO 0x100 /* call original handler of returned opcode */
 386 
 387 ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler);
 388 ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode);
 389 
 390 /* former zend_execute_locks.h */
 391 typedef struct _zend_free_op {
 392         zval* var;
 393 /*      int   is_var; */
 394 } zend_free_op;
 395 
 396 ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC);
 397 ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC);
 398 
 399 ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS);
 400 
 401 void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC);
 402 void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC);
 403 
 404 #define CACHED_PTR(num) \
 405         EG(active_op_array)->run_time_cache[(num)]
 406 
 407 #define CACHE_PTR(num, ptr) do { \
 408                 EG(active_op_array)->run_time_cache[(num)] = (ptr); \
 409         } while (0)
 410 
 411 #define CACHED_POLYMORPHIC_PTR(num, ce) \
 412         ((EG(active_op_array)->run_time_cache[(num)] == (ce)) ? \
 413                 EG(active_op_array)->run_time_cache[(num) + 1] : \
 414                 NULL)
 415 
 416 #define CACHE_POLYMORPHIC_PTR(num, ce, ptr) do { \
 417                 EG(active_op_array)->run_time_cache[(num)] = (ce); \
 418                 EG(active_op_array)->run_time_cache[(num) + 1] = (ptr); \
 419         } while (0)
 420 
 421 END_EXTERN_C()
 422 
 423 #endif /* ZEND_EXECUTE_H */
 424 
 425 /*
 426  * Local variables:
 427  * tab-width: 4
 428  * c-basic-offset: 4
 429  * indent-tabs-mode: t
 430  * End:
 431  */

/* [<][>][^][v][top][bottom][index][help] */