最簡單的物件建立

coder_study發表於2019-11-04
class Student{}

$s = new Student;

https://3v4l.org/RsEDf/vld#output
對應的 opcode:
NOP
NEW
DO_FCALL
ASSIGN
RETURN

列印出的opcodes:

{{handler = 0x555555b4c981 <ZEND_NOP_SPEC_HANDLER>, op1 = {constant = 0, var = 0, num = 0, opline_num = 0, jmp_offset = 0}, op2 = {constant = 0, var = 0, num = 0, opline_num = 0,
      jmp_offset = 0}, result = {constant = 0, var = 0, num = 0, opline_num = 0, jmp_offset = 0}, extended_value = 0, lineno = 3, opcode = 0 '\000', op1_type = 8 '\b', op2_type = 8 '\b',
    result_type = 8 '\b'}, {handler = 0x555555b4fff2 <ZEND_NEW_SPEC_CONST_HANDLER>, op1 = {constant = 0, var = 0, num = 0, opline_num = 0, jmp_offset = 0}, op2 = {constant = 3, var = 3,
      num = 3, opline_num = 3, jmp_offset = 3}, result = {constant = 112, var = 112, num = 112, opline_num = 112, jmp_offset = 112}, extended_value = 0, lineno = 5, opcode = 68 'D',
    op1_type = 1 '\001', op2_type = 8 '\b', result_type = 4 '\004'}, {handler = 0x555555b4a2ac <ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER>, op1 = {constant = 8, var = 8, num = 8, opline_num = 8,
      jmp_offset = 8}, op2 = {constant = 0, var = 0, num = 0, opline_num = 0, jmp_offset = 0}, result = {constant = 2, var = 2, num = 2, opline_num = 2, jmp_offset = 2}, extended_value = 0,
    lineno = 5, opcode = 60 '<', op1_type = 8 '\b', op2_type = 8 '\b', result_type = 8 '\b'}, {handler = 0x555555ba3cd2 <ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER>, op1 = {constant = 80,
      var = 80, num = 80, opline_num = 80, jmp_offset = 80}, op2 = {constant = 112, var = 112, num = 112, opline_num = 112, jmp_offset = 112}, result = {constant = 3, var = 3, num = 3,
      opline_num = 3, jmp_offset = 3}, extended_value = 0, lineno = 5, opcode = 38 '&', op1_type = 16 '\020', op2_type = 4 '\004', result_type = 8 '\b'}, {
    handler = 0x555555b4f852 <ZEND_RETURN_SPEC_CONST_HANDLER>, op1 = {constant = 32, var = 32, num = 32, opline_num = 32, jmp_offset = 32}, op2 = {constant = 0, var = 0, num = 0,
      opline_num = 0, jmp_offset = 0}, result = {constant = 0, var = 0, num = 0, opline_num = 0, jmp_offset = 0}, extended_value = 4294967295, lineno = 6, opcode = 62 '>', op1_type = 1 '\001',
    op2_type = 8 '\b', result_type = 8 '\b'}, {handler = 0xa0, op1 = {constant = 1443046120, var = 1443046120, num = 1443046120, opline_num = 1443046120, jmp_offset = 1443046120}, op2 = {
      constant = 21845, var = 21845, num = 21845, opline_num = 21845, jmp_offset = 21845}, result = {constant = 0, var = 0, num = 0, opline_num = 0, jmp_offset = 0}, extended_value = 0,
    lineno = 570, opcode = 0 '\000', op1_type = 0 '\000', op2_type = 0 '\000', result_type = 0 '\000'}}

ZEND_NOP_SPEC_HANDLER:

static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NOP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
    USE_OPLINE

    ZEND_VM_NEXT_OPCODE();
}
#define ZEND_VM_NEXT_OPCODE() \
    ZEND_VM_NEXT_OPCODE_EX(0, 1)
#define ZEND_VM_NEXT_OPCODE_EX(check_exception, skip) \
    CHECK_SYMBOL_TABLES() \
    if (check_exception) { \
        OPLINE = EX(opline) + (skip); \
    } else { \
        OPLINE = opline + (skip); \
    } \
    ZEND_VM_CONTINUE()

ZEND_NEW_SPEC_CONST_HANDLER:

static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
    USE_OPLINE
    zval *result;
    zend_function *constructor;
    zend_class_entry *ce;
    zend_execute_data *call;

    SAVE_OPLINE();
    if (IS_CONST == IS_CONST) {
        //讀取快取       根據類名查詢zend_class_entry
        ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
        if (UNEXPECTED(ce == NULL)) {
            ////第1步:根據類名查詢zend_class_entry
            ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
            if (UNEXPECTED(ce == NULL)) {
                ZEND_ASSERT(EG(exception));
                HANDLE_EXCEPTION();
            }
            CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
        }
    } else if (IS_CONST == IS_UNUSED) {
        ce = zend_fetch_class(NULL, opline->op1.num);
        if (UNEXPECTED(ce == NULL)) {
            ZEND_ASSERT(EG(exception));
            HANDLE_EXCEPTION();
        }
    } else {
        ce = Z_CE_P(EX_VAR(opline->op1.var));
    }

    result = EX_VAR(opline->result.var);
    //2.建立&初始化一個這個類的物件           建立&初始化一個這個類的物件
    if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) {   //_object_and_properties_init
        HANDLE_EXCEPTION();
    }
    //第3步:獲取構造方法=== 直接取zend_class_entry.constructor
    //get_constructor => zend_std_get_constructor()
    constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
    if (constructor == NULL) {
        if (UNEXPECTED(EG(exception))) {
            zval_ptr_dtor(result);
            HANDLE_EXCEPTION();
        }

        /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
         * opcode is DO_FCALL in case EXT instructions are used. */
        if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
            //此opcode之後還有傳參、呼叫構造方法的操作
            //所以如果沒有定義構造方法則直接跳過這些操作
            ZEND_VM_NEXT_OPCODE_EX(1, 2);
        }

        /* Perform a dummy function call */
        call = zend_vm_stack_push_call_frame(
            ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
            opline->extended_value, NULL, NULL);
    } else {
        if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!constructor->op_array.run_time_cache)) {
            init_func_run_time_cache(&constructor->op_array);
        }
        /* We are not handling overloaded classes right now */
        // 我們現在不處理過載類
        //初始化呼叫建構函式的zend_execute_data
        call = zend_vm_stack_push_call_frame(
            ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
            constructor,
            opline->extended_value,
            ce,
            Z_OBJ_P(result));
        Z_ADDREF_P(result);
    }

    call->prev_execute_data = EX(call);
    EX(call) = call;
    ZEND_VM_NEXT_OPCODE();
}

相關文章