Annotation of embedaddon/php/Zend/zend_opcode.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>