PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - Zend - zend_opcode.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 368 417 88.2 %
Date: 2015-08-29 Functions: 23 26 88.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 29 Aug 2015 10:22:10 +0000 (25 hours ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.