python / python/cpython

Extract common bytecode retrieval logic from `_PyFrame_GetBytecode` and `_PyFrame_SafeGetLasti`

未關閉
#142,929 3 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

interpreter-core type-refactor
主要語言
Python
星號
77.2k
分支
36k
PR 合併指標
PR 指標待擷取

描述

Both _PyFrame_GetBytecode and _PyFrame_SafeGetLasti inline functions currently duplicate the same logic for retrieving the bytecode, differing only in whether they call _PyFrame_GetCode or _PyFrame_SafeGetCode.

static inline _Py_CODEUNIT *
_PyFrame_GetBytecode(_PyInterpreterFrame *f)
{
#ifdef Py_GIL_DISABLED
    PyCodeObject *co = _PyFrame_GetCode(f);
    _PyCodeArray *tlbc = _PyCode_GetTLBCArray(co);
    assert(f->tlbc_index >= 0 && f->tlbc_index < tlbc->size);
    return (_Py_CODEUNIT *)tlbc->entries[f->tlbc_index];
#else
    return _PyCode_CODE(_PyFrame_GetCode(f));
#endif
}

static inline int
_PyFrame_SafeGetLasti(struct _PyInterpreterFrame *f)
{
    // Code based on _PyFrame_GetBytecode() but replace _PyFrame_GetCode()
    // with _PyFrame_SafeGetCode().
    PyCodeObject *co = _PyFrame_SafeGetCode(f);
    if (co == NULL) {
        return -1;
    }

    _Py_CODEUNIT *bytecode;
#ifdef Py_GIL_DISABLED
    _PyCodeArray *tlbc = _PyCode_GetTLBCArray(co);
    assert(f->tlbc_index >= 0 && f->tlbc_index < tlbc->size);
    bytecode = (_Py_CODEUNIT *)tlbc->entries[f->tlbc_index];
#else
    bytecode = _PyCode_CODE(co);
#endif

    return (int)(f->instr_ptr - bytecode) * sizeof(_Py_CODEUNIT);
}

However, I think we should extract the bytecode retrieving logic into another helper, let's say, _PyFrame_GetBytecodeFromCodeObject, as:

static inline _Py_CODEUNIT *
_PyFrame_GetBytecodeFromCodeObject(_PyInterpreterFrame *f, PyCodeObject *co)
{
#ifdef Py_GIL_DISABLED
     _PyCodeArray *tlbc = _PyCode_GetTLBCArray(co);
    assert(f->tlbc_index >= 0 && f->tlbc_index < tlbc->size);
    return (_Py_CODEUNIT *)tlbc->entries[f->tlbc_index];
#else
    return _PyCode_CODE(co);
#endif
}

So we can use that helper as:

static inline _Py_CODEUNIT *
_PyFrame_GetBytecode(_PyInterpreterFrame *f)
{
    PyCodeObject *co = _PyFrame_GetCode(f);
    return _PyFrame_GetBytecodeFromCodeObject(f, co);
}

static inline int
_PyFrame_SafeGetLasti(_PyInterpreterFrame *f)
{
    PyCodeObject *co = _PyFrame_SafGetCode(f);
    if(co == NULL){
        return -1;
    }

    _Py_CODEUNIT *bytecode = _PyFrame_GetBytecodeFromCodeObject(f, co);
    return (int)(f->insert_ptr - bytecode) * sizeof(_Py_CODEUNIT);
}

However, we can use different types of helpers such as inline helper with a function pointer or a macro wrapper. My point here is not about the implementation of the helper itself, but about extracting the bytecode retrieving logic into another helper regardless of the helper name and the method used to implement that helper.

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

研究方向

先定位 _PyFrame_GetBytecode 和 _PyFrame_SafeGetLasti,然後比較它們的呼叫者以及現有的 _PyFrame_GetCode 和 _PyFrame_SafeGetCode 路徑。在保留啟用 GIL 和停用 GIL 兩種情況下的行為的同時,擷取它們共用的位元組碼取得邏輯,並確認相關的 CPython 測試通過。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
c
領域
backend
Issue 類型
重構
難度
4/5
預估耗時
3-5 天
活躍度
停滯
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。