LTP GCOV extension - code coverage report
Current view: directory - Zend - zend_opcode.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 242
Code covered: 71.9 % Executed lines: 174
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | Zend Engine                                                          |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1998-2007 Zend Technologies Ltd. (http://www.zend.com) |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 2.00 of the Zend license,     |
       8                 :    | that is bundled with this package in the file LICENSE, and is        | 
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.zend.com/license/2_00.txt.                                |
      11                 :    | If you did not receive a copy of the Zend license and are unable to  |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@zend.com so we can mail you a copy immediately.              |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16                 :    |          Zeev Suraski <zeev@zend.com>                                |
      17                 :    +----------------------------------------------------------------------+
      18                 : */
      19                 : 
      20                 : /* $Id: zend_opcode.c,v 1.110.2.6.2.2 2007/02/15 10:38:28 dmitry Exp $ */
      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                 : static void zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
      33               0 : {
      34               0 :         if (extension->op_array_ctor) {
      35               0 :                 extension->op_array_ctor(op_array);
      36                 :         }
      37               0 : }
      38                 : 
      39                 : static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
      40               0 : {
      41               0 :         if (extension->op_array_dtor) {
      42               0 :                 extension->op_array_dtor(op_array);
      43                 :         }
      44               0 : }
      45                 : 
      46                 : static void op_array_alloc_ops(zend_op_array *op_array)
      47            1283 : {
      48            1283 :         op_array->opcodes = erealloc(op_array->opcodes, (op_array->size)*sizeof(zend_op));
      49            1283 : }
      50                 : 
      51                 : void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size TSRMLS_DC)
      52            1251 : {
      53            1251 :         op_array->type = type;
      54                 : 
      55            1251 :         op_array->backpatch_count = 0;
      56            1251 :         if (CG(interactive)) {
      57                 :                 /* We must avoid a realloc() on the op_array in interactive mode, since pointers to constants
      58                 :                  * will become invalid
      59                 :                  */
      60               0 :                 initial_ops_size = 8192;
      61                 :         }
      62                 : 
      63            1251 :         op_array->refcount = (zend_uint *) emalloc(sizeof(zend_uint));
      64            1251 :         *op_array->refcount = 1;
      65            1251 :         op_array->size = initial_ops_size;
      66            1251 :         op_array->last = 0;
      67            1251 :         op_array->opcodes = NULL;
      68            1251 :         op_array_alloc_ops(op_array);
      69                 : 
      70            1251 :         op_array->size_var = 0; /* FIXME:??? */
      71            1251 :         op_array->last_var = 0;
      72            1251 :         op_array->vars = NULL;
      73                 : 
      74            1251 :         op_array->T = 0;
      75                 : 
      76            1251 :         op_array->function_name = NULL;
      77            1251 :         op_array->filename = zend_get_compiled_filename(TSRMLS_C);
      78            1251 :         op_array->doc_comment = NULL;
      79            1251 :         op_array->doc_comment_len = 0;
      80                 : 
      81            1251 :         op_array->arg_info = NULL;
      82            1251 :         op_array->num_args = 0;
      83            1251 :         op_array->required_num_args = 0;
      84                 : 
      85            1251 :         op_array->scope = NULL;
      86                 : 
      87            1251 :         op_array->brk_cont_array = NULL;
      88            1251 :         op_array->try_catch_array = NULL;
      89            1251 :         op_array->last_brk_cont = 0;
      90            1251 :         op_array->current_brk_cont = -1;
      91                 : 
      92            1251 :         op_array->static_variables = NULL;
      93            1251 :         op_array->last_try_catch = 0;
      94                 : 
      95            1251 :         op_array->return_reference = 0;
      96            1251 :         op_array->done_pass_two = 0;
      97                 : 
      98            1251 :         op_array->uses_this = 0;
      99                 : 
     100            1251 :         op_array->start_op = NULL;
     101                 : 
     102            1251 :         op_array->fn_flags = CG(interactive)?ZEND_ACC_INTERACTIVE:0;
     103                 : 
     104            1251 :         zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC);
     105            1251 : }
     106                 : 
     107                 : ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC)
     108          414872 : {
     109          414872 :         switch (function->type) {
     110                 :                 case ZEND_USER_FUNCTION:
     111            1822 :                         destroy_op_array((zend_op_array *) function TSRMLS_CC);
     112                 :                         break;
     113                 :                 case ZEND_INTERNAL_FUNCTION:
     114                 :                         /* do nothing */
     115                 :                         break;
     116                 :         }
     117          414872 : }
     118                 : 
     119                 : ZEND_API void zend_function_dtor(zend_function *function)
     120          414872 : {
     121                 :         TSRMLS_FETCH();
     122                 : 
     123          414872 :         destroy_zend_function(function TSRMLS_CC);
     124          414872 : }
     125                 : 
     126                 : static void zend_cleanup_op_array_data(zend_op_array *op_array)
     127             916 : {
     128             916 :         if (op_array->static_variables) {
     129               1 :                 zend_hash_clean(op_array->static_variables);
     130                 :         }
     131             916 : }
     132                 : 
     133                 : ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC)
     134            1125 : {
     135            1125 :         if (function->type == ZEND_USER_FUNCTION) {
     136             906 :                 zend_cleanup_op_array_data((zend_op_array *) function);
     137             906 :                 return ZEND_HASH_APPLY_KEEP;
     138                 :         } else {
     139             219 :                 return ZEND_HASH_APPLY_STOP;
     140                 :         }
     141                 : }
     142                 : 
     143                 : ZEND_API int zend_cleanup_function_data_full(zend_function *function TSRMLS_DC)
     144             212 : {
     145             212 :         if (function->type == ZEND_USER_FUNCTION) {
     146              10 :                 zend_cleanup_op_array_data((zend_op_array *) function);
     147                 :         }
     148             212 :         return 0;
     149                 : }
     150                 : 
     151                 : ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC)
     152           19058 : {
     153           19058 :         if ((*pce)->type == ZEND_USER_CLASS) {
     154                 :                 /* Clean all parts that can contain run-time data */
     155                 :                 /* Note that only run-time accessed data need to be cleaned up, pre-defined data can
     156                 :                    not contain objects and thus are not probelmatic */
     157               5 :                 zend_hash_apply(&(*pce)->function_table, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC);
     158               5 :                 (*pce)->static_members = NULL;
     159           19053 :         } else if (CE_STATIC_MEMBERS(*pce)) {
     160              93 :                 zend_hash_destroy(CE_STATIC_MEMBERS(*pce));
     161              93 :                 FREE_HASHTABLE(CE_STATIC_MEMBERS(*pce));
     162                 : #ifdef ZTS
     163                 :                 CG(static_members)[(long)((*pce)->static_members)] = NULL;
     164                 : #else
     165              93 :                 (*pce)->static_members = NULL;
     166                 : #endif
     167                 :         }
     168           19058 :         return 0;
     169                 : }
     170                 : 
     171                 : ZEND_API void destroy_zend_class(zend_class_entry **pce)
     172           19063 : {
     173           19063 :         zend_class_entry *ce = *pce;
     174                 :         
     175           19063 :         if (--ce->refcount > 0) {
     176               5 :                 return;
     177                 :         }
     178           19058 :         switch (ce->type) {
     179                 :                 case ZEND_USER_CLASS:
     180               5 :                         zend_hash_destroy(&ce->default_properties);
     181               5 :                         zend_hash_destroy(&ce->properties_info);
     182               5 :                         zend_hash_destroy(&ce->default_static_members);
     183               5 :                         efree(ce->name);
     184               5 :                         zend_hash_destroy(&ce->function_table);
     185               5 :                         zend_hash_destroy(&ce->constants_table);
     186               5 :                         if (ce->num_interfaces > 0 && ce->interfaces) {
     187               3 :                                 efree(ce->interfaces);
     188                 :                         }
     189               5 :                         if (ce->doc_comment) {
     190               0 :                                 efree(ce->doc_comment);
     191                 :                         }
     192               5 :                         efree(ce);
     193               5 :                         break;
     194                 :                 case ZEND_INTERNAL_CLASS:
     195           19053 :                         zend_hash_destroy(&ce->default_properties);
     196           19053 :                         zend_hash_destroy(&ce->properties_info);
     197           19053 :                         zend_hash_destroy(&ce->default_static_members);
     198           19053 :                         free(ce->name);
     199           19053 :                         zend_hash_destroy(&ce->function_table);
     200           19053 :                         zend_hash_destroy(&ce->constants_table);
     201           19053 :                         if (ce->num_interfaces > 0) {
     202            8103 :                                 free(ce->interfaces);
     203                 :                         }
     204           19053 :                         if (ce->doc_comment) {
     205               0 :                                 free(ce->doc_comment);
     206                 :                         }
     207           19053 :                         free(ce);
     208                 :                         break;
     209                 :         }
     210                 : }
     211                 : 
     212                 : void zend_class_add_ref(zend_class_entry **ce)
     213               0 : {
     214               0 :         (*ce)->refcount++;
     215               0 : }
     216                 : 
     217                 : ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
     218            2148 : {
     219            2148 :         zend_op *opline = op_array->opcodes;
     220            2148 :         zend_op *end = op_array->opcodes+op_array->last;
     221                 :         zend_uint i;
     222                 : 
     223            2148 :         if (op_array->static_variables) {
     224               1 :                 zend_hash_destroy(op_array->static_variables);
     225               1 :                 FREE_HASHTABLE(op_array->static_variables);
     226                 :         }
     227                 : 
     228            2148 :         if (--(*op_array->refcount)>0) {
     229             906 :                 return;
     230                 :         }
     231                 : 
     232            1242 :         efree(op_array->refcount);
     233                 : 
     234            1242 :         if (op_array->vars) {
     235             852 :                 i = op_array->last_var;
     236            2985 :                 while (i > 0) {
     237            1281 :                         i--;
     238            1281 :                         efree(op_array->vars[i].name);
     239                 :                 }
     240             852 :                 efree(op_array->vars);
     241                 :         }
     242                 : 
     243           26202 :         while (opline<end) {
     244           23718 :                 if (opline->op1.op_type==IS_CONST) {
     245                 : #if DEBUG_ZEND>2
     246                 :                         printf("Reducing refcount for %x 1=>0 (destroying)\n", &opline->op1.u.constant);
     247                 : #endif
     248            8724 :                         zval_dtor(&opline->op1.u.constant);
     249                 :                 }
     250           23718 :                 if (opline->op2.op_type==IS_CONST) {
     251                 : #if DEBUG_ZEND>2
     252                 :                         printf("Reducing refcount for %x 1=>0 (destroying)\n", &opline->op2.u.constant);
     253                 : #endif
     254            4057 :                         zval_dtor(&opline->op2.u.constant);
     255                 :                 }
     256           23718 :                 opline++;
     257                 :         }
     258            1242 :         efree(op_array->opcodes);
     259                 : 
     260            1242 :         if (op_array->function_name) {
     261             916 :                 efree(op_array->function_name);
     262                 :         }
     263            1242 :         if (op_array->doc_comment) {
     264               0 :                 efree(op_array->doc_comment);
     265                 :         }
     266            1242 :         if (op_array->brk_cont_array) {
     267              36 :                 efree(op_array->brk_cont_array);
     268                 :         }
     269            1242 :         if (op_array->try_catch_array) {
     270               7 :                 efree(op_array->try_catch_array);
     271                 :         }
     272            1242 :         if (op_array->done_pass_two) {
     273            1242 :                 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array TSRMLS_CC);
     274                 :         }
     275            1242 :         if (op_array->arg_info) {
     276            1746 :                 for (i=0; i<op_array->num_args; i++) {
     277             948 :                         efree(op_array->arg_info[i].name);
     278             948 :                         if (op_array->arg_info[i].class_name) {
     279               0 :                                 efree(op_array->arg_info[i].class_name);
     280                 :                         }
     281                 :                 }
     282             798 :                 efree(op_array->arg_info);
     283                 :         }
     284                 : }
     285                 : 
     286                 : void init_op(zend_op *op TSRMLS_DC)
     287           26718 : {
     288           26718 :         memset(op, 0, sizeof(zend_op));
     289           26718 :         op->lineno = CG(zend_lineno);
     290           26718 :         SET_UNUSED(op->result);
     291           26718 : }
     292                 : 
     293                 : zend_op *get_next_op(zend_op_array *op_array TSRMLS_DC)
     294           25857 : {
     295           25857 :         zend_uint next_op_num = op_array->last++;
     296                 :         zend_op *next_op;
     297                 : 
     298           25857 :         if (next_op_num >= op_array->size) {
     299              32 :                 if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) {
     300                 :                         /* we messed up */
     301               0 :                         zend_printf("Ran out of opcode space!\n"
     302                 :                                                 "You should probably consider writing this huge script into a file!\n");
     303               0 :                         zend_bailout();
     304                 :                 }
     305              32 :                 op_array->size *= 4;
     306              32 :                 op_array_alloc_ops(op_array);
     307                 :         }
     308                 :         
     309           25857 :         next_op = &(op_array->opcodes[next_op_num]);
     310                 :         
     311           25857 :         init_op(next_op TSRMLS_CC);
     312                 : 
     313           25857 :         return next_op;
     314                 : }
     315                 : 
     316                 : int get_next_op_number(zend_op_array *op_array)
     317            3528 : {
     318            3528 :         return op_array->last;
     319                 : }
     320                 : 
     321                 : zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array)
     322              75 : {
     323              75 :         op_array->last_brk_cont++;
     324              75 :         op_array->brk_cont_array = erealloc(op_array->brk_cont_array, sizeof(zend_brk_cont_element)*op_array->last_brk_cont);
     325              75 :         return &op_array->brk_cont_array[op_array->last_brk_cont-1];
     326                 : }
     327                 : 
     328                 : static void zend_update_extended_info(zend_op_array *op_array TSRMLS_DC)
     329               0 : {
     330               0 :         zend_op *opline = op_array->opcodes, *end=opline+op_array->last;
     331                 : 
     332               0 :         while (opline<end) {
     333               0 :                 if (opline->opcode == ZEND_EXT_STMT) {
     334               0 :                         if (opline+1<end) {
     335               0 :                                 if ((opline+1)->opcode == ZEND_EXT_STMT) {
     336               0 :                                         opline->opcode = ZEND_NOP;
     337               0 :                                         opline++;
     338               0 :                                         continue;
     339                 :                                 }
     340               0 :                                 if (opline+1<end) {
     341               0 :                                         opline->lineno = (opline+1)->lineno;
     342                 :                                 }
     343                 :                         } else {
     344               0 :                                 opline->opcode = ZEND_NOP;
     345                 :                         }
     346                 :                 }
     347               0 :                 opline++;
     348                 :         }
     349               0 : }
     350                 : 
     351                 : static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
     352               0 : {
     353               0 :         if (extension->op_array_handler) {
     354               0 :                 extension->op_array_handler(op_array);
     355                 :         }
     356               0 : }
     357                 : 
     358                 : int pass_two(zend_op_array *op_array TSRMLS_DC)
     359            1251 : {
     360                 :         zend_op *opline, *end;
     361                 : 
     362            1251 :         if (op_array->type!=ZEND_USER_FUNCTION && op_array->type!=ZEND_EVAL_CODE) {
     363               0 :                 return 0;
     364                 :         }
     365            1251 :         if (CG(extended_info)) {
     366               0 :                 zend_update_extended_info(op_array TSRMLS_CC);
     367                 :         }
     368            1251 :         if (CG(handle_op_arrays)) {
     369            1251 :                 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array TSRMLS_CC);
     370                 :         }
     371                 : 
     372            1251 :         if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && op_array->size != op_array->last) {
     373            1251 :                 op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
     374            1251 :                 op_array->size = op_array->last;
     375                 :         }
     376                 : 
     377            1251 :         opline = op_array->opcodes;
     378            1251 :         end = opline + op_array->last;
     379           28351 :         while (opline < end) {
     380           25849 :                 if (opline->op1.op_type == IS_CONST) {
     381            9081 :                         opline->op1.u.constant.is_ref = 1;
     382            9081 :                         opline->op1.u.constant.refcount = 2; /* Make sure is_ref won't be reset */
     383                 :                 }
     384           25849 :                 if (opline->op2.op_type == IS_CONST) {
     385            5122 :                         opline->op2.u.constant.is_ref = 1;
     386            5122 :                         opline->op2.u.constant.refcount = 2;
     387                 :                 }
     388           25849 :                 switch (opline->opcode) {
     389                 :                         case ZEND_JMP:
     390             506 :                                 opline->op1.u.jmp_addr = &op_array->opcodes[opline->op1.u.opline_num];
     391             506 :                                 break;
     392                 :                         case ZEND_JMPZ:
     393                 :                         case ZEND_JMPNZ:
     394                 :                         case ZEND_JMPZ_EX:
     395                 :                         case ZEND_JMPNZ_EX:
     396             625 :                                 opline->op2.u.jmp_addr = &op_array->opcodes[opline->op2.u.opline_num];
     397                 :                                 break;
     398                 :                 }
     399           25849 :                 ZEND_VM_SET_OPCODE_HANDLER(opline);
     400           25849 :                 opline++;
     401                 :         }
     402                 :         
     403            1251 :         op_array->done_pass_two = 1;
     404            1251 :         return 0;
     405                 : }
     406                 : 
     407                 : int print_class(zend_class_entry *class_entry TSRMLS_DC)
     408               0 : {
     409               0 :         printf("Class %s:\n", class_entry->name);
     410               0 :         zend_hash_apply(&class_entry->function_table, (apply_func_t) pass_two TSRMLS_CC);
     411               0 :         printf("End of class %s.\n\n", class_entry->name);
     412               0 :         return 0;
     413                 : }
     414                 : 
     415                 : ZEND_API unary_op_type get_unary_op(int opcode)
     416               0 : {
     417               0 :         switch (opcode) {
     418                 :                 case ZEND_BW_NOT:
     419               0 :                         return (unary_op_type) bitwise_not_function;
     420                 :                         break;
     421                 :                 case ZEND_BOOL_NOT:
     422               0 :                         return (unary_op_type) boolean_not_function;
     423                 :                         break;
     424                 :                 default:
     425               0 :                         return (unary_op_type) NULL;
     426                 :                         break;
     427                 :         }
     428                 : }
     429                 : 
     430                 : ZEND_API void *get_binary_op(int opcode)
     431               0 : {
     432               0 :         switch (opcode) {
     433                 :                 case ZEND_ADD:
     434                 :                 case ZEND_ASSIGN_ADD:
     435               0 :                         return (void *) add_function;
     436                 :                         break;
     437                 :                 case ZEND_SUB:
     438                 :                 case ZEND_ASSIGN_SUB:
     439               0 :                         return (void *) sub_function;
     440                 :                         break;
     441                 :                 case ZEND_MUL:
     442                 :                 case ZEND_ASSIGN_MUL:
     443               0 :                         return (void *) mul_function;
     444                 :                         break;
     445                 :                 case ZEND_DIV:
     446                 :                 case ZEND_ASSIGN_DIV:
     447               0 :                         return (void *) div_function;
     448                 :                         break;
     449                 :                 case ZEND_MOD:
     450                 :                 case ZEND_ASSIGN_MOD:
     451               0 :                         return (void *) mod_function;
     452                 :                         break;
     453                 :                 case ZEND_SL:
     454                 :                 case ZEND_ASSIGN_SL:
     455               0 :                         return (void *) shift_left_function;
     456                 :                         break;
     457                 :                 case ZEND_SR:
     458                 :                 case ZEND_ASSIGN_SR:
     459               0 :                         return (void *) shift_right_function;
     460                 :                         break;
     461                 :                 case ZEND_CONCAT:
     462                 :                 case ZEND_ASSIGN_CONCAT:
     463               0 :                         return (void *) concat_function;
     464                 :                         break;
     465                 :                 case ZEND_IS_IDENTICAL:
     466               0 :                         return (void *) is_identical_function;
     467                 :                         break;
     468                 :                 case ZEND_IS_NOT_IDENTICAL:
     469               0 :                         return (void *) is_not_identical_function;
     470                 :                         break;
     471                 :                 case ZEND_IS_EQUAL:
     472               0 :                         return (void *) is_equal_function;
     473                 :                         break;
     474                 :                 case ZEND_IS_NOT_EQUAL:
     475               0 :                         return (void *) is_not_equal_function;
     476                 :                         break;
     477                 :                 case ZEND_IS_SMALLER:
     478               0 :                         return (void *) is_smaller_function;
     479                 :                         break;
     480                 :                 case ZEND_IS_SMALLER_OR_EQUAL:
     481               0 :                         return (void *) is_smaller_or_equal_function;
     482                 :                         break;
     483                 :                 case ZEND_BW_OR:
     484                 :                 case ZEND_ASSIGN_BW_OR:
     485               0 :                         return (void *) bitwise_or_function;
     486                 :                         break;
     487                 :                 case ZEND_BW_AND:
     488                 :                 case ZEND_ASSIGN_BW_AND:
     489               0 :                         return (void *) bitwise_and_function;
     490                 :                         break;
     491                 :                 case ZEND_BW_XOR:
     492                 :                 case ZEND_ASSIGN_BW_XOR:
     493               0 :                         return (void *) bitwise_xor_function;
     494                 :                         break;
     495                 :                 default:
     496               0 :                         return (void *) NULL;
     497                 :                         break;
     498                 :         }
     499                 : }
     500                 : 
     501                 : /*
     502                 :  * Local variables:
     503                 :  * tab-width: 4
     504                 :  * c-basic-offset: 4
     505                 :  * indent-tabs-mode: t
     506                 :  * End:
     507                 :  */

Generated by: LTP GCOV extension version 1.5