zoukankan      html  css  js  c++  java
  • php类 静态变量赋值 static $name="abc"

     

    <?php
    class test
    {
       static $name="abc";
    }
    
    echo test::$name;

     

    1.巴斯科范式

    class_statement:
            variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';'
    ;
    
    member_modifier:
            T_PUBLIC                { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
        |    T_PROTECTED                { Z_LVAL($$.u.constant) = ZEND_ACC_PROTECTED; }
        |    T_PRIVATE                { Z_LVAL($$.u.constant) = ZEND_ACC_PRIVATE; }
        |    T_STATIC                { Z_LVAL($$.u.constant) = ZEND_ACC_STATIC; }
        |    T_ABSTRACT                { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; }
        |    T_FINAL                    { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; }
    ;
    
    class_variable_declaration:
            class_variable_declaration ',' T_VARIABLE                    { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); }
        |    class_variable_declaration ',' T_VARIABLE '=' static_scalar    { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); }
        |    T_VARIABLE                        { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); }
        |    T_VARIABLE '=' static_scalar    { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); }
    ;
    
    variable:
        T_STRING T_PAAMAYIM_NEKUDOTAYIM base_variable { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
    ;
    
    base_variable:
        T_VARIABLE            {  fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }    
    ;

     

     

    理解版

    class_statement:
            variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';'
    ;
    
    member_modifier:
            T_PUBLIC                { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
        |    T_PROTECTED                { Z_LVAL($$.u.constant) = ZEND_ACC_PROTECTED; }
        |    T_PRIVATE                { Z_LVAL($$.u.constant) = ZEND_ACC_PRIVATE; }
        |    T_STATIC                { Z_LVAL($$.u.constant) = ZEND_ACC_STATIC; }
        |    T_ABSTRACT                { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; }
        |    T_FINAL                    { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; }
    ;
    
    class_variable_declaration:
            class_variable_declaration ',' T_VARIABLE                    { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); }
        |    class_variable_declaration ',' T_VARIABLE '=' static_scalar    { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); }
        |    T_VARIABLE                        { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); }
        |    T_VARIABLE '=' static_scalar    { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); }
    ;
    
    variable:
        T_STRING T_PAAMAYIM_NEKUDOTAYIM T_VARIABLE { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
    ;

     

     

    2.对于 static $name="abc" 

    组织propert_info结构体,将其存于为类中的property_info 这个HashTable中,

    注意: value 这个值是存在类中的property_table中,其中key 为property_info中的offset

    void zend_do_declare_property(const znode *var_name, const znode *value, zend_uint access_type TSRMLS_DC) /* {{{ */
    {
        zval *property;
        ALLOC_ZVAL(property);
        if (value) {
            *property = value->u.constant;
        } else {
            INIT_PZVAL(property);
            Z_TYPE_P(property) = IS_NULL;
        }
        zend_declare_property_ex(CG(active_class_entry), zend_new_interned_string(Z_STRVAL(var_name->u.constant), Z_STRLEN(var_name->u.constant) + 1, 0 TSRMLS_CC), Z_STRLEN(var_name->u.constant), property, access_type, comment, comment_len TSRMLS_CC);
    }

     

    ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, const char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */
    {
        zend_property_info property_info, *property_info_ptr;
        const char *interned_name;
        ulong h = zend_get_hash_value(name, name_length+1);
    
        if (access_type & ZEND_ACC_STATIC) {
            //如果是静态成员变量,就使用relloc分配需要的内存,size(zval*)*ce->default_static_member_count是总共的内存
            property_info.offset = ce->default_static_members_count++;
            ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
            
            ce->default_static_members_table[property_info.offset] = property;
            if (ce->type == ZEND_USER_CLASS) {
                ce->static_members_table = ce->default_static_members_table;
            }
        } else {
            property_info.offset = ce->default_properties_count++;
            ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
            ce->default_properties_table[property_info.offset] = property;
        }
    
        interned_name = zend_new_interned_string(property_info.name, property_info.name_length+1, 0 TSRMLS_CC);
        if (interned_name != property_info.name) {
            if (ce->type == ZEND_USER_CLASS) {
                efree((char*)property_info.name);
            } else {
                free((char*)property_info.name);
            }
            property_info.name = interned_name;
        }
    
        property_info.flags = access_type;
        property_info.h = (access_type & ZEND_ACC_PUBLIC) ? h : zend_get_hash_value(property_info.name, property_info.name_length+1);
    
        property_info.ce = ce;
        zend_hash_quick_update(&ce->properties_info, name, name_length+1, h, &property_info, sizeof(zend_property_info), NULL);
        return SUCCESS;
    }
    void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
    {
        znode class_node;
        zend_llist *fetch_list_ptr;
        zend_llist_element *le;
        zend_op *opline_ptr;
        zend_op opline;
    
        zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
        
        if (result->op_type == IS_CV) {
            init_op(&opline TSRMLS_CC);
    
            opline.opcode = ZEND_FETCH_W;
            opline.result_type = IS_VAR;
            opline.result.var = get_temporary_variable(CG(active_op_array));
            opline.op1_type = IS_CONST;

    //opline->op1为 成员变量的值,result->u.op.var为fetch_simple_variable所获得的值 LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)
    ->vars[result->u.op.var].name), CG(active_op_array)->vars[result->u.op.var].name_len, 0); CALCULATE_LITERAL_HASH(opline.op1.constant); GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);

    //class_node.op_type此时为IS_VAR
    if (class_node.op_type == IS_CONST) { opline.op2_type = IS_CONST; opline.op2.constant = zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC); } else { SET_NODE(opline.op2, &class_node); } GET_NODE(result,opline.result); opline.extended_value |= ZEND_FETCH_STATIC_MEMBER; opline_ptr = &opline; zend_llist_add_element(fetch_list_ptr, &opline); }

    zend_do_fetch_class 函数的运行

    static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
    {
        USE_OPLINE
        zval *class_name = opline->op2.zv;
        if (CACHED_PTR(opline->op2.literal->cache_slot)) {
            EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
        } else {
            EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
            CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
    //记住 这里被缓存住了
    } }
    static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
    {
        USE_OPLINE
        zend_free_op free_op1;
        zval *varname;
        zval **retval;
    
        SAVE_OPLINE();
        varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
    
        zend_class_entry *ce;
        ce = CACHED_PTR(opline->op2.literal->cache_slot);
        retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);    
        
    }

     找到成员变量

    ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, zend_bool silent, const zend_literal *key TSRMLS_DC) /* {{{ */
    {
        zend_property_info *property_info;
        ulong hash_value;
    
        
        hash_value = zend_hash_func(property_name, property_name_len+1);
            
       //即使这里的类是子类,子类的ce->properties_info的数据复制于父类的properties_info这个hash table
        if (UNEXPECTED(zend_hash_quick_find(&ce->properties_info, property_name, property_name_len+1, hash_value, (void **) &property_info)==FAILURE)) {
            if (!silent) {
                zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
            }
            return NULL;
        }
    
    
        if (UNEXPECTED(!zend_verify_property_access(property_info, ce TSRMLS_CC))) {
            if (!silent) {
                zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
            }
            return NULL;
        }
    
        if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
            if (!silent) {
                zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
            }
            return NULL;
        }
    
        if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL) ||
            UNEXPECTED(CE_STATIC_MEMBERS(ce)[property_info->offset] == NULL)) {
            if (!silent) {
                zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
            }
            return NULL;
        }
        
        return &CE_STATIC_MEMBERS(ce)[property_info->offset];
    }

     

  • 相关阅读:
    qt中使用dll库的方法
    41. wait notify 方法
    40.方式二的练习
    39.线程的实现方式二
    38. 死锁
    37. 解决线程问题方式二(同步函数)
    36. 解决线程问题方式一(同步代码块synchronized)
    35.线程问题
    34. Thread类的常用方法
    33. 自定义线程
  • 原文地址:https://www.cnblogs.com/taek/p/4298097.html
Copyright © 2011-2022 走看看