php-5.6.26源代码 - opcode处理器,“乘法opcode”处理器

 

// opcode处理器 - 运算符怎么执行: “*” 乘法opcode处理器
static int ZEND_FASTCALL  ZEND_MUL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
    USE_OPLINE


    SAVE_OPLINE();
    fast_mul_function(&EX_T(opline->result.var).tmp_var,
        opline->op1.zv,
        opline->op2.zv TSRMLS_CC);


    CHECK_EXCEPTION();
    ZEND_VM_NEXT_OPCODE();
}

// “*” 乘法opcode处理器  - 展开
static int ZEND_FASTCALL  ZEND_MUL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
    // USE_OPLINE
    zend_op *opline = EX(opline);


    // SAVE_OPLINE();  ---> 空代码
    
    // fast_mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
    fast_mul_function(&EX_T(opline->result.var).tmp_var,
        opline->op1.zv,
        opline->op2.zv TSRMLS_CC);{
        
        if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { // op1是long类型
            if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { // op2是long类型
                long overflow;
    
                ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow);
                Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
                return SUCCESS;
            } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { // op2是double类型
                Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2); // 转成double类型,做乘法
                Z_TYPE_P(result) = IS_DOUBLE;
                return SUCCESS;
            }
        } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { // op1是double类型
            if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {  // op2是double类型
                Z_DVAL_P(result) = Z_DVAL_P(op1) * Z_DVAL_P(op2); // 直接做乘法
                Z_TYPE_P(result) = IS_DOUBLE;
                return SUCCESS;
            } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { // op2是long类型
                Z_DVAL_P(result) = Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)); // 转成double类型,做乘法
                Z_TYPE_P(result) = IS_DOUBLE;
                return SUCCESS;
            }
        }
        return mul_function(result, op1, op2 TSRMLS_CC);{
            zval op1_copy, op2_copy;
            int converted = 0;
        
            while (1) { // 死循环
                switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
                    case TYPE_PAIR(IS_LONG, IS_LONG): {
                        long overflow;
        
                        ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
                        Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
                        return SUCCESS;
        
                    }
                    case TYPE_PAIR(IS_LONG, IS_DOUBLE):
                        ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
                        return SUCCESS;
        
                    case TYPE_PAIR(IS_DOUBLE, IS_LONG):
                        ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
                        return SUCCESS;
        
                    case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
                        ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
                        return SUCCESS;
        
                    default:
                        if (!converted) { // 自动转换类型
                            ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL);
        
                            zendi_convert_scalar_to_number(op1, op1_copy, result); // 转换类型
                            zendi_convert_scalar_to_number(op2, op2_copy, result); // 转换类型
                            converted = 1;
                        } else {
                            zend_error(E_ERROR, "Unsupported operand types");
                            return FAILURE; /* unknown datatype */
                        }
                }
            }
        }
    }

    // CHECK_EXCEPTION() ---> 空代码
    
    // ZEND_VM_NEXT_OPCODE() ---> CHECK_SYMBOL_TABLES()
    zend_hash_apply(&EG(symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC);
    if (&EG(symbol_table)!=EG(active_symbol_table)) {                                
        zend_hash_apply(EG(active_symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC);    
    }
    
    // ZEND_VM_NEXT_OPCODE() ---> ZEND_VM_INC_OPCODE()
    OPLINE++; // 下一个操作行
    
    // ZEND_VM_NEXT_OPCODE() ---> ZEND_VM_CONTINUE()
    return 0;
}

 

posted on 2018-03-23 10:51  周~~  阅读(169)  评论(0编辑  收藏  举报

导航