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))))

    
    }

     

     

  • 相关阅读:
    Session的使用与Session的生命周期
    Long-Polling, Websockets, SSE(Server-Sent Event), WebRTC 之间的区别与使用
    十九、详述 IntelliJ IDEA 之 添加 jar 包
    十八、IntelliJ IDEA 常用快捷键 之 Windows 版
    十七、IntelliJ IDEA 中的 Maven 项目初体验及搭建 Spring MVC 框架
    十六、详述 IntelliJ IDEA 创建 Maven 项目及设置 java 源目录的方法
    十五、详述 IntelliJ IDEA 插件的安装及使用方法
    十四、详述 IntelliJ IDEA 提交代码前的 Code Analysis 机制
    十三、IntelliJ IDEA 中的版本控制介绍(下)
    十二、IntelliJ IDEA 中的版本控制介绍(中)
  • 原文地址:https://www.cnblogs.com/taek/p/4129187.html
Copyright © 2011-2022 走看看