Skip to content

Commit 8382896

Browse files
committed
infra: LoadAttr specialization bridges
2 new bridges for emitLoadAttr specialized opcode paths: - hir_builder_get_attr_cache: read _PyAttrCache version/index from CPython inline cache at bytecode instruction offset - hir_find_type_by_version_tag: tree walk from PyBaseObject_Type to find PyTypeObject by tp_version_tag These unlock LOAD_ATTR_MODULE, LOAD_ATTR_SLOT, LOAD_ATTR_INSTANCE_VALUE conversion in emitLoadAttr.
1 parent a92fa7c commit 8382896

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

Python/jit/hir/hir_c_api.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,4 +2650,39 @@ void *hir_builder_preloader_preloaded_type(void *builder, PyObject *descr,
26502650
return pt.type.get();
26512651
}
26522652

2653+
void hir_builder_get_attr_cache(void *builder, int instr_idx,
2654+
uint32_t *version_out, uint16_t *index_out) {
2655+
auto *b = static_cast<jit::hir::HIRBuilder*>(builder);
2656+
PyCodeObject *code = b->preloader().code();
2657+
_Py_CODEUNIT *code_units = (_Py_CODEUNIT *)code->co_code_adaptive;
2658+
const _PyAttrCache *cache =
2659+
reinterpret_cast<const _PyAttrCache *>(&code_units[instr_idx + 1]);
2660+
*version_out = cache->version[0] | (static_cast<uint32_t>(cache->version[1]) << 16);
2661+
*index_out = cache->index;
2662+
}
2663+
2664+
static PyTypeObject *findTypeByVersionTagWalk(PyTypeObject *type, uint32_t version) {
2665+
if (type->tp_version_tag == version) {
2666+
return type;
2667+
}
2668+
PyObject *subclasses = (PyObject *)type->tp_subclasses;
2669+
if (subclasses == nullptr) {
2670+
return nullptr;
2671+
}
2672+
Py_ssize_t pos = 0;
2673+
PyObject *ref;
2674+
while (PyDict_Next(subclasses, &pos, nullptr, &ref)) {
2675+
PyObject *subtype_obj = PyWeakref_GET_OBJECT(ref);
2676+
if (subtype_obj == Py_None) continue;
2677+
PyTypeObject *subtype = (PyTypeObject *)subtype_obj;
2678+
PyTypeObject *found = findTypeByVersionTagWalk(subtype, version);
2679+
if (found) return found;
2680+
}
2681+
return nullptr;
2682+
}
2683+
2684+
PyTypeObject *hir_find_type_by_version_tag(uint32_t version) {
2685+
return findTypeByVersionTagWalk(&PyBaseObject_Type, version);
2686+
}
2687+
26532688
} /* extern "C" */

Python/jit/hir/hir_c_api.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,14 @@ void hir_instr_expand_into(void *original, void **expansion, size_t count);
784784
/* Get the BasicBlock* for a given bytecode offset from the builder's block map. */
785785
void *hir_builder_get_block_at_off(void *builder, int byte_offset);
786786

787+
/* Read _PyAttrCache inline cache from bytecode at instr_idx.
788+
* Returns version (uint32) and index (uint16). */
789+
void hir_builder_get_attr_cache(void *builder, int instr_idx,
790+
uint32_t *version_out, uint16_t *index_out);
791+
792+
/* Find a PyTypeObject by its tp_version_tag. Returns NULL if not found. */
793+
PyTypeObject *hir_find_type_by_version_tag(uint32_t version);
794+
787795
/* ---- Preloader bridges (Tier 4 emit conversion) ---- */
788796

789797
/* Get the Preloader's annotations (HirAnnotationIndex*). */

0 commit comments

Comments
 (0)