zoukankan      html  css  js  c++  java
  • php 生成类的对象 $a=new test();

    程序

     

    <?php
    class test
    {
        ...
    }
    
    $a=new test();

     

     

     

     

     1.BNF 范式

     

    start:
            variable '=' expr ';'
    
    expr:
            new_expr
    ;
    new_expr:
            T_NEW class_name {zend_do_begin_new_class(&$$ , &$2)} ctor_paramer { zend_do_end_new_class() }
    ;
    class_name:
            T_STRING {zend_do_fetch_class(&$$, &$1) }

     

     

     

     

    获取class_name,并生成opcode ZEND_FETCH_CLASS

    void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
    {
        
        zend_op *opline;
    
        fetch_class_op_number = get_next_op_number(CG(active_op_array));
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        opline->opcode = ZEND_FETCH_CLASS;
        SET_UNUSED(opline->op1);
        if (class_name->op_type == IS_CONST) {
            int fetch_type;
            switch (fetch_type) {
                default:
                    zend_resolve_class_name(class_name TSRMLS_CC);
                    opline->op2_type = IS_CONST;
                    opline->op2.constant =
                        zend_add_class_name_literal(CG(active_op_array), &class_name->u.constant TSRMLS_CC);
                    break;
            }
        } 
        opline->result.var = get_temporary_variable(CG(active_op_array));
        opline->result_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
        GET_NODE(result, opline->result);
    }

     

     

    执行 ZEND_FETCH_CLASS

    static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
    {
        USE_OPLINE
        EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
    }

     

     

     

    void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /* {{{ */
    {
        zend_op *opline;
        unsigned char *ptr = NULL;
    
        new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        opline->opcode = ZEND_NEW;
        opline->result_type = IS_VAR;
        opline->result.var = get_temporary_variable(CG(active_op_array));
        SET_NODE(opline->op1, class_type);
        SET_UNUSED(opline->op2);
    
        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *));
    }

     

    void zend_do_end_new_object(znode *result, const znode *new_token, const znode *argument_list TSRMLS_DC) /* {{{ */
    {
        znode ctor_result;
    
        zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
        zend_do_free(&ctor_result TSRMLS_CC);
    
        CG(active_op_array)->opcodes[new_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
        GET_NODE(result, CG(active_op_array)->opcodes[new_token->u.op.opline_num].result);
    }

     

     

    static int ZEND_FASTCALL  ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
    {
        USE_OPLINE
        zval *object_zval;
        zend_function *constructor;
    
        SAVE_OPLINE();
        if (UNEXPECTED((EX_T(opline->op1.var).class_entry->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
            if (EX_T(opline->op1.var).class_entry->ce_flags & ZEND_ACC_INTERFACE) {
                zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", EX_T(opline->op1.var).class_entry->name);
            } else if ((EX_T(opline->op1.var).class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
                zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", EX_T(opline->op1.var).class_entry->name);
            } else {
                zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", EX_T(opline->op1.var).class_entry->name);
            }
        }
        ALLOC_ZVAL(object_zval);
        object_init_ex(object_zval, EX_T(opline->op1.var).class_entry);
        INIT_PZVAL(object_zval);
    
        constructor = Z_OBJ_HT_P(object_zval)->get_constructor(object_zval TSRMLS_CC);
    
        if (constructor == NULL) {
            if (RETURN_VALUE_USED(opline)) {
                AI_SET_PTR(&EX_T(opline->result.var), object_zval);
            } else {
                zval_ptr_dtor(&object_zval);
            }
            ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.opline_num);
        } else {
            if (RETURN_VALUE_USED(opline)) {
                PZVAL_LOCK(object_zval);
                AI_SET_PTR(&EX_T(opline->result.var), object_zval);
            }
    
            zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), ENCODE_CTOR(EX(called_scope), RETURN_VALUE_USED(opline)));
    
            /* We are not handling overloaded classes right now */
            EX(object) = object_zval;
            EX(fbc) = constructor;
            EX(called_scope) = EX_T(opline->op1.var).class_entry;
    
            CHECK_EXCEPTION();
            ZEND_VM_NEXT_OPCODE();
        }
    }

     

     

    #define object_init_ex(arg, ce)    _object_init_ex((arg), (ce) ZEND_FILE_LINE_CC TSRMLS_CC)
    
    ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
    {
        return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
    }
    
    ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
    {
        zend_object *object;
    
        if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
            char *what =   (class_type->ce_flags & ZEND_ACC_INTERFACE)                ? "interface"
                         :((class_type->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) ? "trait"
                         :                                                              "abstract class";
            zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name);
        }
    
        zend_update_class_constants(class_type TSRMLS_CC);
    
        Z_TYPE_P(arg) = IS_OBJECT;
        if (class_type->create_object == NULL) {
            Z_OBJVAL_P(arg) = zend_objects_new(&object, class_type TSRMLS_CC);
    // arg.value.obj=zend_objects_new(...);
    if (properties) { object->properties = properties; object->properties_table = NULL; } else { object_properties_init(object, class_type); } } else { Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC); } return SUCCESS; }

     

     

    ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
    {
        int i;
    
        if (class_type->default_properties_count) {
            object->properties_table = emalloc(sizeof(zval*) * class_type->default_properties_count);
            for (i = 0; i < class_type->default_properties_count; i++) {
                object->properties_table[i] = class_type->default_properties_table[i];
                if (class_type->default_properties_table[i]) {
                    Z_ADDREF_P(object->properties_table[i]);
                }
            }
            object->properties = NULL;
        }
    }

     

     

     

     

    ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type TSRMLS_DC)
    {
        zend_object_value retval;
    
        *object = emalloc(sizeof(zend_object));
        (*object)->ce = class_type;
        (*object)->properties = NULL;
        (*object)->properties_table = NULL;
        (*object)->guards = NULL;
        retval.handle = zend_objects_store_put(*object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_objects_free_object_storage, NULL TSRMLS_CC);
        retval.handlers = &std_object_handlers;
        return retval;
    }
    
    ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_store_dtor_t dtor, zend_objects_free_object_storage_t free_storage, zend_objects_store_clone_t clone TSRMLS_DC)
    {
        zend_object_handle handle;
        struct _store_object *obj;
    
        if (EG(objects_store).free_list_head != -1) {
            handle = EG(objects_store).free_list_head;
            EG(objects_store).free_list_head = EG(objects_store).object_buckets[handle].bucket.free_list.next;
        } else {
            if (EG(objects_store).top == EG(objects_store).size) {
                EG(objects_store).size <<= 1;
                EG(objects_store).object_buckets = (zend_object_store_bucket *) erealloc(EG(objects_store).object_buckets, EG(objects_store).size * sizeof(zend_object_store_bucket));
            }
            handle = EG(objects_store).top++;
        }
        obj = &EG(objects_store).object_buckets[handle].bucket.obj;
        EG(objects_store).object_buckets[handle].destructor_called = 0;
        EG(objects_store).object_buckets[handle].valid = 1;
        EG(objects_store).object_buckets[handle].apply_count = 0;
    
        obj->refcount = 1;
        GC_OBJ_INIT(obj);
        obj->object = object;
        obj->dtor = dtor?dtor:(zend_objects_store_dtor_t)zend_objects_destroy_object;
        obj->free_storage = free_storage;
        obj->clone = clone;
        obj->handlers = NULL;
    
    #if ZEND_DEBUG_OBJECTS
        fprintf(stderr, "Allocated object id #%d
    ", handle);
    #endif
        return handle;
    }

     

     理解版

    static int ZEND_FASTCALL  ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
    {
        zval *zv;
        zv->type=IS_OBJECT;
        zend_object_value object_value;
        ALLOC_ZVAL(zv);
        zend_object *object;
        object->ce=EX_T(opline1->op1.var);
        object->properties=NULL;
        object->properties_table=NULL;
    
        zend_object_handle handle;
        handle=EG(object_store).top++;
    
        object=&EG(object_store).object_buckets[handle].bucket.obj;
        object->object=object;
    
        object_value.handle=handle;
    
        zv.value.obj=object_value;

       EX_T(opline->result.var).var.ptr=zv;
       result->u.op=opline->result;
     

        //#define EX_T(offset) (*EX_TMP_VAR(execute_data, offset))
        //#define EX_TMP_VAR(ex, n) ((temp_variable*)(((char*)(ex)) + ((int)(n))))

    
    }

     

     

  • 相关阅读:
    第十二周作业
    第九周作业
    第八周作业
    第七周作业
    第六周作业
    参考博文地址
    第五周作业
    用例设计思路
    测试方法的四大金刚
    网络模型及访问过程
  • 原文地址:https://www.cnblogs.com/taek/p/4129187.html
Copyright © 2011-2022 走看看