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();
}