root/Zend/zend_opcode.c

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

DEFINITIONS

This source file includes following definitions.
  1. zend_extension_op_array_ctor_handler
  2. zend_extension_op_array_dtor_handler
  3. op_array_alloc_ops
  4. init_op_array
  5. destroy_zend_function
  6. zend_function_dtor
  7. zend_cleanup_op_array_data
  8. zend_cleanup_user_class_data
  9. zend_cleanup_internal_class_data
  10. _destroy_zend_class_traits_info
  11. destroy_zend_class
  12. zend_class_add_ref
  13. destroy_op_array
  14. init_op
  15. get_next_op
  16. get_next_op_number
  17. get_next_brk_cont_element
  18. zend_update_extended_info
  19. zend_extension_op_array_handler
  20. zend_check_finally_breakout
  21. zend_resolve_fast_call
  22. zend_resolve_finally_ret
  23. zend_get_brk_cont_target
  24. pass_two
  25. get_unary_op
  26. get_binary_op

   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    |          Dmitry Stogov <dmitry@zend.com>                             |
  18    +----------------------------------------------------------------------+
  19 */
  20 
  21 /* $Id$ */
  22 
  23 #include <stdio.h>
  24 
  25 #include "zend.h"
  26 #include "zend_alloc.h"
  27 #include "zend_compile.h"
  28 #include "zend_extensions.h"
  29 #include "zend_API.h"
  30 
  31 #include "zend_vm.h"
  32 
  33 static void zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array)
  34 {
  35         if (extension->op_array_ctor) {
  36                 extension->op_array_ctor(op_array);
  37         }
  38 }
  39 
  40 static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend_op_array *op_array)
  41 {
  42         if (extension->op_array_dtor) {
  43                 extension->op_array_dtor(op_array);
  44         }
  45 }
  46 
  47 static void op_array_alloc_ops(zend_op_array *op_array, uint32_t size)
  48 {
  49         op_array->opcodes = erealloc(op_array->opcodes, size * sizeof(zend_op));
  50 }
  51 
  52 void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size)
  53 {
  54         op_array->type = type;
  55         op_array->arg_flags[0] = 0;
  56         op_array->arg_flags[1] = 0;
  57         op_array->arg_flags[2] = 0;
  58 
  59         op_array->refcount = (uint32_t *) emalloc(sizeof(uint32_t));
  60         *op_array->refcount = 1;
  61         op_array->last = 0;
  62         op_array->opcodes = NULL;
  63         op_array_alloc_ops(op_array, initial_ops_size);
  64 
  65         op_array->last_var = 0;
  66         op_array->vars = NULL;
  67 
  68         op_array->T = 0;
  69 
  70         op_array->function_name = NULL;
  71         op_array->filename = zend_get_compiled_filename();
  72         op_array->doc_comment = NULL;
  73 
  74         op_array->arg_info = NULL;
  75         op_array->num_args = 0;
  76         op_array->required_num_args = 0;
  77 
  78         op_array->scope = NULL;
  79         op_array->prototype = NULL;
  80 
  81         op_array->brk_cont_array = NULL;
  82         op_array->try_catch_array = NULL;
  83         op_array->last_brk_cont = 0;
  84 
  85         op_array->static_variables = NULL;
  86         op_array->last_try_catch = 0;
  87 
  88         op_array->this_var = -1;
  89 
  90         op_array->fn_flags = 0;
  91 
  92         op_array->early_binding = -1;
  93 
  94         op_array->last_literal = 0;
  95         op_array->literals = NULL;
  96 
  97         op_array->run_time_cache = NULL;
  98         op_array->cache_size = 0;
  99 
 100         memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
 101 
 102         if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_CTOR) {
 103                 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array);
 104         }
 105 }
 106 
 107 ZEND_API void destroy_zend_function(zend_function *function)
 108 {
 109         if (function->type == ZEND_USER_FUNCTION) {
 110                 destroy_op_array(&function->op_array);
 111         } else {
 112                 ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION);
 113                 ZEND_ASSERT(function->common.function_name);
 114                 zend_string_release(function->common.function_name);
 115         }
 116 }
 117 
 118 ZEND_API void zend_function_dtor(zval *zv)
 119 {
 120         zend_function *function = Z_PTR_P(zv);
 121 
 122         if (function->type == ZEND_USER_FUNCTION) {
 123                 ZEND_ASSERT(function->common.function_name);
 124                 destroy_op_array(&function->op_array);
 125                 /* op_arrays are allocated on arena, so we don't have to free them */
 126         } else {
 127                 ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION);
 128                 ZEND_ASSERT(function->common.function_name);
 129                 zend_string_release(function->common.function_name);
 130                 if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) {
 131                         pefree(function, 1);
 132                 }
 133         }
 134 }
 135 
 136 ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array)
 137 {
 138         if (op_array->static_variables &&
 139             !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
 140                 zend_hash_clean(op_array->static_variables);
 141         }
 142 }
 143 
 144 ZEND_API void zend_cleanup_user_class_data(zend_class_entry *ce)
 145 {
 146         /* Clean all parts that can contain run-time data */
 147         /* Note that only run-time accessed data need to be cleaned up, pre-defined data can
 148            not contain objects and thus are not probelmatic */
 149         if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
 150                 zend_function *func;
 151 
 152                 ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
 153                         if (func->type == ZEND_USER_FUNCTION) {
 154                                 zend_cleanup_op_array_data((zend_op_array *) func);
 155                         }
 156                 } ZEND_HASH_FOREACH_END();
 157         }
 158         if (ce->static_members_table) {
 159                 zval *static_members = ce->static_members_table;
 160                 zval *p = static_members;
 161                 zval *end = p + ce->default_static_members_count;
 162 
 163 
 164                 ce->default_static_members_count = 0;
 165                 ce->default_static_members_table = ce->static_members_table = NULL;
 166                 while (p != end) {
 167                         i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
 168                         p++;
 169                 }
 170                 efree(static_members);
 171         }
 172 }
 173 
 174 ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce)
 175 {
 176         if (CE_STATIC_MEMBERS(ce)) {
 177                 zval *static_members = CE_STATIC_MEMBERS(ce);
 178                 zval *p = static_members;
 179                 zval *end = p + ce->default_static_members_count;
 180 
 181 #ifdef ZTS
 182                 CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL;
 183 #else
 184                 ce->static_members_table = NULL;
 185 #endif
 186                 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
 187                 while (p != end) {
 188                         i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
 189                         p++;
 190                 }
 191                 efree(static_members);
 192         }
 193 }
 194 
 195 void _destroy_zend_class_traits_info(zend_class_entry *ce)
 196 {
 197         if (ce->num_traits > 0 && ce->traits) {
 198                 efree(ce->traits);
 199         }
 200 
 201         if (ce->trait_aliases) {
 202                 size_t i = 0;
 203                 while (ce->trait_aliases[i]) {
 204                         if (ce->trait_aliases[i]->trait_method) {
 205                                 if (ce->trait_aliases[i]->trait_method->method_name) {
 206                                         zend_string_release(ce->trait_aliases[i]->trait_method->method_name);
 207                                 }
 208                                 if (ce->trait_aliases[i]->trait_method->class_name) {
 209                                         zend_string_release(ce->trait_aliases[i]->trait_method->class_name);
 210                                 }
 211                                 efree(ce->trait_aliases[i]->trait_method);
 212                         }
 213 
 214                         if (ce->trait_aliases[i]->alias) {
 215                                 zend_string_release(ce->trait_aliases[i]->alias);
 216                         }
 217 
 218                         efree(ce->trait_aliases[i]);
 219                         i++;
 220                 }
 221 
 222                 efree(ce->trait_aliases);
 223         }
 224 
 225         if (ce->trait_precedences) {
 226                 size_t i = 0;
 227 
 228                 while (ce->trait_precedences[i]) {
 229                         zend_string_release(ce->trait_precedences[i]->trait_method->method_name);
 230                         zend_string_release(ce->trait_precedences[i]->trait_method->class_name);
 231                         efree(ce->trait_precedences[i]->trait_method);
 232 
 233                         if (ce->trait_precedences[i]->exclude_from_classes) {
 234                                 size_t j = 0;
 235                                 zend_trait_precedence *cur_precedence = ce->trait_precedences[i];
 236                                 while (cur_precedence->exclude_from_classes[j].class_name) {
 237                                         zend_string_release(cur_precedence->exclude_from_classes[j].class_name);
 238                                         j++;
 239                                 }
 240                                 efree(ce->trait_precedences[i]->exclude_from_classes);
 241                         }
 242                         efree(ce->trait_precedences[i]);
 243                         i++;
 244                 }
 245                 efree(ce->trait_precedences);
 246         }
 247 }
 248 
 249 ZEND_API void destroy_zend_class(zval *zv)
 250 {
 251         zend_property_info *prop_info;
 252         zend_class_entry *ce = Z_PTR_P(zv);
 253 
 254         if (--ce->refcount > 0) {
 255                 return;
 256         }
 257         switch (ce->type) {
 258                 case ZEND_USER_CLASS:
 259                         if (ce->default_properties_table) {
 260                                 zval *p = ce->default_properties_table;
 261                                 zval *end = p + ce->default_properties_count;
 262 
 263                                 while (p != end) {
 264                                         i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
 265                                         p++;
 266                                 }
 267                                 efree(ce->default_properties_table);
 268                         }
 269                         if (ce->default_static_members_table) {
 270                                 zval *p = ce->default_static_members_table;
 271                                 zval *end = p + ce->default_static_members_count;
 272 
 273                                 while (p != end) {
 274                                         i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
 275                                         p++;
 276                                 }
 277                                 efree(ce->default_static_members_table);
 278                         }
 279                         ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
 280                                 if (prop_info->ce == ce || (prop_info->flags & ZEND_ACC_SHADOW)) {
 281                                         zend_string_release(prop_info->name);
 282                                         if (prop_info->doc_comment) {
 283                                                 zend_string_release(prop_info->doc_comment);
 284                                         }
 285                                 }
 286                         } ZEND_HASH_FOREACH_END();
 287                         zend_hash_destroy(&ce->properties_info);
 288                         zend_string_release(ce->name);
 289                         zend_hash_destroy(&ce->function_table);
 290                         zend_hash_destroy(&ce->constants_table);
 291                         if (ce->num_interfaces > 0 && ce->interfaces) {
 292                                 efree(ce->interfaces);
 293                         }
 294                         if (ce->info.user.doc_comment) {
 295                                 zend_string_release(ce->info.user.doc_comment);
 296                         }
 297 
 298                         _destroy_zend_class_traits_info(ce);
 299 
 300                         break;
 301                 case ZEND_INTERNAL_CLASS:
 302                         if (ce->default_properties_table) {
 303                                 zval *p = ce->default_properties_table;
 304                                 zval *end = p + ce->default_properties_count;
 305 
 306                                 while (p != end) {
 307                                         zval_internal_ptr_dtor(p);
 308                                         p++;
 309                                 }
 310                                 free(ce->default_properties_table);
 311                         }
 312                         if (ce->default_static_members_table) {
 313                                 zval *p = ce->default_static_members_table;
 314                                 zval *end = p + ce->default_static_members_count;
 315 
 316                                 while (p != end) {
 317                                         zval_internal_ptr_dtor(p);
 318                                         p++;
 319                                 }
 320                                 free(ce->default_static_members_table);
 321                         }
 322                         zend_hash_destroy(&ce->properties_info);
 323                         zend_string_release(ce->name);
 324                         zend_hash_destroy(&ce->function_table);
 325                         zend_hash_destroy(&ce->constants_table);
 326                         if (ce->num_interfaces > 0) {
 327                                 free(ce->interfaces);
 328                         }
 329                         free(ce);
 330                         break;
 331         }
 332 }
 333 
 334 void zend_class_add_ref(zval *zv)
 335 {
 336         zend_class_entry *ce = Z_PTR_P(zv);
 337 
 338         ce->refcount++;
 339 }
 340 
 341 ZEND_API void destroy_op_array(zend_op_array *op_array)
 342 {
 343         zval *literal = op_array->literals;
 344         zval *end;
 345         uint32_t i;
 346 
 347         if (op_array->static_variables &&
 348             !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
 349                 if (--GC_REFCOUNT(op_array->static_variables) == 0) {
 350                         zend_array_destroy(op_array->static_variables);
 351                 }
 352         }
 353 
 354         if (op_array->run_time_cache && !op_array->function_name) {
 355                 efree(op_array->run_time_cache);
 356                 op_array->run_time_cache = NULL;
 357         }
 358 
 359         if (!op_array->refcount || --(*op_array->refcount) > 0) {
 360                 return;
 361         }
 362 
 363         efree_size(op_array->refcount, sizeof(*(op_array->refcount)));
 364 
 365         if (op_array->vars) {
 366                 i = op_array->last_var;
 367                 while (i > 0) {
 368                         i--;
 369                         zend_string_release(op_array->vars[i]);
 370                 }
 371                 efree(op_array->vars);
 372         }
 373 
 374         if (literal) {
 375                 end = literal + op_array->last_literal;
 376                 while (literal < end) {
 377                         zval_ptr_dtor_nogc(literal);
 378                         literal++;
 379                 }
 380                 efree(op_array->literals);
 381         }
 382         efree(op_array->opcodes);
 383 
 384         if (op_array->function_name) {
 385                 zend_string_release(op_array->function_name);
 386         }
 387         if (op_array->doc_comment) {
 388                 zend_string_release(op_array->doc_comment);
 389         }
 390         if (op_array->brk_cont_array) {
 391                 efree(op_array->brk_cont_array);
 392         }
 393         if (op_array->try_catch_array) {
 394                 efree(op_array->try_catch_array);
 395         }
 396         if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_DTOR) {
 397                 if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
 398                         zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array);
 399                 }
 400         }
 401         if (op_array->arg_info) {
 402                 uint32_t num_args = op_array->num_args;
 403                 zend_arg_info *arg_info = op_array->arg_info;
 404 
 405                 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
 406                         arg_info--;
 407                         num_args++;
 408                 }
 409                 if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
 410                         num_args++;
 411                 }
 412                 for (i = 0 ; i < num_args; i++) {
 413                         if (arg_info[i].name) {
 414                                 zend_string_release(arg_info[i].name);
 415                         }
 416                         if (arg_info[i].class_name) {
 417                                 zend_string_release(arg_info[i].class_name);
 418                         }
 419                 }
 420                 efree(arg_info);
 421         }
 422 }
 423 
 424 void init_op(zend_op *op)
 425 {
 426         memset(op, 0, sizeof(zend_op));
 427         op->lineno = CG(zend_lineno);
 428         SET_UNUSED(op->result);
 429 }
 430 
 431 zend_op *get_next_op(zend_op_array *op_array)
 432 {
 433         uint32_t next_op_num = op_array->last++;
 434         zend_op *next_op;
 435 
 436         if (next_op_num >= CG(context).opcodes_size) {
 437                 CG(context).opcodes_size *= 4;
 438                 op_array_alloc_ops(op_array, CG(context).opcodes_size);
 439         }
 440 
 441         next_op = &(op_array->opcodes[next_op_num]);
 442 
 443         init_op(next_op);
 444 
 445         return next_op;
 446 }
 447 
 448 int get_next_op_number(zend_op_array *op_array)
 449 {
 450         return op_array->last;
 451 }
 452 
 453 zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array)
 454 {
 455         op_array->last_brk_cont++;
 456         op_array->brk_cont_array = erealloc(op_array->brk_cont_array, sizeof(zend_brk_cont_element)*op_array->last_brk_cont);
 457         return &op_array->brk_cont_array[op_array->last_brk_cont-1];
 458 }
 459 
 460 static void zend_update_extended_info(zend_op_array *op_array)
 461 {
 462         zend_op *opline = op_array->opcodes, *end=opline+op_array->last;
 463 
 464         while (opline<end) {
 465                 if (opline->opcode == ZEND_EXT_STMT) {
 466                         if (opline+1<end) {
 467                                 if ((opline+1)->opcode == ZEND_EXT_STMT) {
 468                                         opline->opcode = ZEND_NOP;
 469                                         opline++;
 470                                         continue;
 471                                 }
 472                                 if (opline+1<end) {
 473                                         opline->lineno = (opline+1)->lineno;
 474                                 }
 475                         } else {
 476                                 opline->opcode = ZEND_NOP;
 477                         }
 478                 }
 479                 opline++;
 480         }
 481 }
 482 
 483 static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array)
 484 {
 485         if (extension->op_array_handler) {
 486                 extension->op_array_handler(op_array);
 487         }
 488 }
 489 
 490 static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num, uint32_t dst_num)
 491 {
 492         int i;
 493 
 494         for (i = 0; i < op_array->last_try_catch; i++) {
 495                 if ((op_num < op_array->try_catch_array[i].finally_op ||
 496                                         op_num >= op_array->try_catch_array[i].finally_end)
 497                                 && (dst_num >= op_array->try_catch_array[i].finally_op &&
 498                                          dst_num <= op_array->try_catch_array[i].finally_end)) {
 499                         CG(in_compilation) = 1;
 500                         CG(active_op_array) = op_array;
 501                         CG(zend_lineno) = op_array->opcodes[op_num].lineno;
 502                         zend_error_noreturn(E_COMPILE_ERROR, "jump into a finally block is disallowed");
 503                 } else if ((op_num >= op_array->try_catch_array[i].finally_op
 504                                         && op_num <= op_array->try_catch_array[i].finally_end)
 505                                 && (dst_num > op_array->try_catch_array[i].finally_end
 506                                         || dst_num < op_array->try_catch_array[i].finally_op)) {
 507                         CG(in_compilation) = 1;
 508                         CG(active_op_array) = op_array;
 509                         CG(zend_lineno) = op_array->opcodes[op_num].lineno;
 510                         zend_error_noreturn(E_COMPILE_ERROR, "jump out of a finally block is disallowed");
 511                 }
 512         }
 513 }
 514 
 515 static void zend_resolve_fast_call(zend_op_array *op_array, uint32_t op_num)
 516 {
 517         int i;
 518         uint32_t finally_op_num = 0;
 519 
 520         for (i = 0; i < op_array->last_try_catch; i++) {
 521                 if (op_num >= op_array->try_catch_array[i].finally_op
 522                                 && op_num < op_array->try_catch_array[i].finally_end) {
 523                         finally_op_num = op_array->try_catch_array[i].finally_op;
 524                 }
 525         }
 526 
 527         if (finally_op_num) {
 528                 /* Must be ZEND_FAST_CALL */
 529                 ZEND_ASSERT(op_array->opcodes[finally_op_num - 2].opcode == ZEND_FAST_CALL);
 530                 op_array->opcodes[op_num].extended_value = ZEND_FAST_CALL_FROM_FINALLY;
 531                 op_array->opcodes[op_num].op2.opline_num = finally_op_num - 2;
 532         }
 533 }
 534 
 535 static void zend_resolve_finally_ret(zend_op_array *op_array, uint32_t op_num)
 536 {
 537         int i;
 538         uint32_t catch_op_num = 0, finally_op_num = 0;
 539 
 540         for (i = 0; i < op_array->last_try_catch; i++) {
 541                 if (op_array->try_catch_array[i].try_op > op_num) {
 542                         break;
 543                 }
 544                 if (op_num < op_array->try_catch_array[i].finally_op) {
 545                         finally_op_num = op_array->try_catch_array[i].finally_op;
 546                 }
 547                 if (op_num < op_array->try_catch_array[i].catch_op) {
 548                         catch_op_num = op_array->try_catch_array[i].catch_op;
 549                 }
 550         }
 551 
 552         if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) {
 553                 /* in case of unhandled exception return to upward finally block */
 554                 op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_FINALLY;
 555                 op_array->opcodes[op_num].op2.opline_num = finally_op_num;
 556         } else if (catch_op_num) {
 557                 /* in case of unhandled exception return to upward catch block */
 558                 op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_CATCH;
 559                 op_array->opcodes[op_num].op2.opline_num = catch_op_num;
 560         }
 561 }
 562 
 563 static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const zend_op *opline) {
 564         int nest_levels = opline->op2.num;
 565         int array_offset = opline->op1.num;
 566         zend_brk_cont_element *jmp_to;
 567         do {
 568                 jmp_to = &op_array->brk_cont_array[array_offset];
 569                 if (nest_levels > 1) {
 570                         array_offset = jmp_to->parent;
 571                 }
 572         } while (--nest_levels > 0);
 573 
 574         return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont;
 575 }
 576 
 577 ZEND_API int pass_two(zend_op_array *op_array)
 578 {
 579         zend_op *opline, *end;
 580 
 581         if (!ZEND_USER_CODE(op_array->type)) {
 582                 return 0;
 583         }
 584         if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
 585                 zend_update_extended_info(op_array);
 586         }
 587         if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) {
 588                 if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_HANDLER) {
 589                         zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array);
 590                 }
 591         }
 592 
 593         if (CG(context).vars_size != op_array->last_var) {
 594                 op_array->vars = (zend_string**) erealloc(op_array->vars, sizeof(zend_string*)*op_array->last_var);
 595                 CG(context).vars_size = op_array->last_var;
 596         }
 597         if (CG(context).opcodes_size != op_array->last) {
 598                 op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
 599                 CG(context).opcodes_size = op_array->last;
 600         }
 601         if (CG(context).literals_size != op_array->last_literal) {
 602                 op_array->literals = (zval*)erealloc(op_array->literals, sizeof(zval) * op_array->last_literal);
 603                 CG(context).literals_size = op_array->last_literal;
 604         }
 605         opline = op_array->opcodes;
 606         end = opline + op_array->last;
 607         while (opline < end) {
 608                 switch (opline->opcode) {
 609                         case ZEND_FAST_CALL:
 610                                 opline->op1.opline_num = op_array->try_catch_array[opline->op1.num].finally_op;
 611                                 zend_resolve_fast_call(op_array, opline - op_array->opcodes);
 612                                 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
 613                                 break;
 614                         case ZEND_FAST_RET:
 615                                 zend_resolve_finally_ret(op_array, opline - op_array->opcodes);
 616                                 break;
 617                         case ZEND_DECLARE_ANON_INHERITED_CLASS:
 618                                 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
 619                                 /* break omitted intentionally */
 620                         case ZEND_DECLARE_INHERITED_CLASS:
 621                         case ZEND_DECLARE_INHERITED_CLASS_DELAYED:
 622                                 opline->extended_value = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->extended_value);
 623                                 break;
 624                         case ZEND_BRK:
 625                         case ZEND_CONT:
 626                                 {
 627                                         uint32_t jmp_target = zend_get_brk_cont_target(op_array, opline);
 628 
 629                                         if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
 630                                                 zend_check_finally_breakout(op_array, opline - op_array->opcodes, jmp_target);
 631                                         }
 632                                         opline->opcode = ZEND_JMP;
 633                                         opline->op1.opline_num = jmp_target;
 634                                         opline->op2.num = 0;
 635                                         ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
 636                                 }
 637                                 break;
 638                         case ZEND_GOTO:
 639                                 zend_resolve_goto_label(op_array, opline);
 640                                 if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
 641                                         zend_check_finally_breakout(op_array, opline - op_array->opcodes, opline->op1.opline_num);
 642                                 }
 643                                 /* break omitted intentionally */
 644                         case ZEND_JMP:
 645                         case ZEND_DECLARE_ANON_CLASS:
 646                                 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
 647                                 break;
 648                         case ZEND_JMPZNZ:
 649                                 /* absolute index to relative offset */
 650                                 opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
 651                                 /* break omitted intentionally */
 652                         case ZEND_JMPZ:
 653                         case ZEND_JMPNZ:
 654                         case ZEND_JMPZ_EX:
 655                         case ZEND_JMPNZ_EX:
 656                         case ZEND_JMP_SET:
 657                         case ZEND_COALESCE:
 658                         case ZEND_NEW:
 659                         case ZEND_FE_RESET_R:
 660                         case ZEND_FE_RESET_RW:
 661                         case ZEND_ASSERT_CHECK:
 662                                 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
 663                                 break;
 664                         case ZEND_FE_FETCH_R:
 665                         case ZEND_FE_FETCH_RW:
 666                                 opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
 667                                 break;
 668                         case ZEND_VERIFY_RETURN_TYPE:
 669                                 if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
 670                                         if (opline->op1_type != IS_UNUSED) {
 671                                                 zend_op *ret = opline;
 672                                                 do ret++; while (ret->opcode != ZEND_RETURN);
 673 
 674                                                 ret->op1 = opline->op1;
 675                                                 ret->op1_type = opline->op1_type;
 676                                         }
 677 
 678                                         MAKE_NOP(opline);
 679                                 }
 680                                 break;
 681                         case ZEND_RETURN:
 682                         case ZEND_RETURN_BY_REF:
 683                                 if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
 684                                         opline->opcode = ZEND_GENERATOR_RETURN;
 685                                 }
 686                                 break;
 687                 }
 688                 if (opline->op1_type == IS_CONST) {
 689                         ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1);
 690                 } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
 691                         opline->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op1.var);
 692                 }
 693                 if (opline->op2_type == IS_CONST) {
 694                         ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
 695                 } else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
 696                         opline->op2.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op2.var);
 697                 }
 698                 if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
 699                         opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->result.var);
 700                 }
 701                 ZEND_VM_SET_OPCODE_HANDLER(opline);
 702                 opline++;
 703         }
 704 
 705         op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
 706         return 0;
 707 }
 708 
 709 ZEND_API unary_op_type get_unary_op(int opcode)
 710 {
 711         switch (opcode) {
 712                 case ZEND_BW_NOT:
 713                         return (unary_op_type) bitwise_not_function;
 714                 case ZEND_BOOL_NOT:
 715                         return (unary_op_type) boolean_not_function;
 716                 default:
 717                         return (unary_op_type) NULL;
 718         }
 719 }
 720 
 721 ZEND_API binary_op_type get_binary_op(int opcode)
 722 {
 723         switch (opcode) {
 724                 case ZEND_ADD:
 725                 case ZEND_ASSIGN_ADD:
 726                         return (binary_op_type) add_function;
 727                 case ZEND_SUB:
 728                 case ZEND_ASSIGN_SUB:
 729                         return (binary_op_type) sub_function;
 730                 case ZEND_MUL:
 731                 case ZEND_ASSIGN_MUL:
 732                         return (binary_op_type) mul_function;
 733                 case ZEND_POW:
 734                         return (binary_op_type) pow_function;
 735                 case ZEND_DIV:
 736                 case ZEND_ASSIGN_DIV:
 737                         return (binary_op_type) div_function;
 738                 case ZEND_MOD:
 739                 case ZEND_ASSIGN_MOD:
 740                         return (binary_op_type) mod_function;
 741                 case ZEND_SL:
 742                 case ZEND_ASSIGN_SL:
 743                         return (binary_op_type) shift_left_function;
 744                 case ZEND_SR:
 745                 case ZEND_ASSIGN_SR:
 746                         return (binary_op_type) shift_right_function;
 747                 case ZEND_FAST_CONCAT:
 748                 case ZEND_CONCAT:
 749                 case ZEND_ASSIGN_CONCAT:
 750                         return (binary_op_type) concat_function;
 751                 case ZEND_IS_IDENTICAL:
 752                         return (binary_op_type) is_identical_function;
 753                 case ZEND_IS_NOT_IDENTICAL:
 754                         return (binary_op_type) is_not_identical_function;
 755                 case ZEND_IS_EQUAL:
 756                         return (binary_op_type) is_equal_function;
 757                 case ZEND_IS_NOT_EQUAL:
 758                         return (binary_op_type) is_not_equal_function;
 759                 case ZEND_IS_SMALLER:
 760                         return (binary_op_type) is_smaller_function;
 761                 case ZEND_IS_SMALLER_OR_EQUAL:
 762                         return (binary_op_type) is_smaller_or_equal_function;
 763                 case ZEND_SPACESHIP:
 764                         return (binary_op_type) compare_function;
 765                 case ZEND_BW_OR:
 766                 case ZEND_ASSIGN_BW_OR:
 767                         return (binary_op_type) bitwise_or_function;
 768                 case ZEND_BW_AND:
 769                 case ZEND_ASSIGN_BW_AND:
 770                         return (binary_op_type) bitwise_and_function;
 771                 case ZEND_BW_XOR:
 772                 case ZEND_ASSIGN_BW_XOR:
 773                         return (binary_op_type) bitwise_xor_function;
 774                 case ZEND_BOOL_XOR:
 775                         return (binary_op_type) boolean_xor_function;
 776                 default:
 777                         return (binary_op_type) NULL;
 778         }
 779 }
 780 
 781 /*
 782  * Local variables:
 783  * tab-width: 4
 784  * c-basic-offset: 4
 785  * indent-tabs-mode: t
 786  * End:
 787  */

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