python / python/cpython

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

オープン
#142,929 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

interpreter-core type-refactor
主要言語
Python
スター
77.2k
フォーク
35.9k
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. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず _PyFrame_GetBytecode と _PyFrame_SafeGetLasti を見つけ、次にそれらの呼び出し元と、既存の _PyFrame_GetCode および _PyFrame_SafeGetCode の経路を比較します。GIL が有効な場合と無効な場合の両方の動作を維持しながら、共通するバイトコード取得ロジックを抽出し、関連する CPython のテストが成功することを確認します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
c
領域
backend
issue の種類
リファクタリング
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。