Branch data Line data Source code
1 : : #include "parts.h" 2 : : 3 : : static Py_ssize_t 4 : 0 : get_code_extra_index(PyInterpreterState* interp) { 5 : 0 : Py_ssize_t result = -1; 6 : : 7 : : static const char *key = "_testcapi.frame_evaluation.code_index"; 8 : : 9 : 0 : PyObject *interp_dict = PyInterpreterState_GetDict(interp); // borrowed 10 [ # # ]: 0 : assert(interp_dict); // real users would handle missing dict... somehow 11 : : 12 : 0 : PyObject *index_obj = PyDict_GetItemString(interp_dict, key); // borrowed 13 : 0 : Py_ssize_t index = 0; 14 [ # # ]: 0 : if (!index_obj) { 15 [ # # ]: 0 : if (PyErr_Occurred()) { 16 : 0 : goto finally; 17 : : } 18 : 0 : index = PyUnstable_Eval_RequestCodeExtraIndex(NULL); 19 [ # # # # ]: 0 : if (index < 0 || PyErr_Occurred()) { 20 : 0 : goto finally; 21 : : } 22 : 0 : index_obj = PyLong_FromSsize_t(index); // strong ref 23 [ # # ]: 0 : if (!index_obj) { 24 : 0 : goto finally; 25 : : } 26 : 0 : int res = PyDict_SetItemString(interp_dict, key, index_obj); 27 : 0 : Py_DECREF(index_obj); 28 [ # # ]: 0 : if (res < 0) { 29 : 0 : goto finally; 30 : : } 31 : : } 32 : : else { 33 : 0 : index = PyLong_AsSsize_t(index_obj); 34 [ # # # # ]: 0 : if (index == -1 && PyErr_Occurred()) { 35 : 0 : goto finally; 36 : : } 37 : : } 38 : : 39 : 0 : result = index; 40 : 0 : finally: 41 : 0 : return result; 42 : : } 43 : : 44 : : static PyObject * 45 : 0 : test_code_extra(PyObject* self, PyObject *Py_UNUSED(callable)) 46 : : { 47 : 0 : PyObject *result = NULL; 48 : 0 : PyObject *test_module = NULL; 49 : 0 : PyObject *test_func = NULL; 50 : : 51 : : // Get or initialize interpreter-specific code object storage index 52 : 0 : PyInterpreterState *interp = PyInterpreterState_Get(); 53 [ # # ]: 0 : if (!interp) { 54 : 0 : return NULL; 55 : : } 56 : 0 : Py_ssize_t code_extra_index = get_code_extra_index(interp); 57 [ # # ]: 0 : if (PyErr_Occurred()) { 58 : 0 : goto finally; 59 : : } 60 : : 61 : : // Get a function to test with 62 : : // This can be any Python function. Use `test.test_misc.testfunction`. 63 : 0 : test_module = PyImport_ImportModule("test.test_capi.test_misc"); 64 [ # # ]: 0 : if (!test_module) { 65 : 0 : goto finally; 66 : : } 67 : 0 : test_func = PyObject_GetAttrString(test_module, "testfunction"); 68 [ # # ]: 0 : if (!test_func) { 69 : 0 : goto finally; 70 : : } 71 : 0 : PyObject *test_func_code = PyFunction_GetCode(test_func); // borrowed 72 [ # # ]: 0 : if (!test_func_code) { 73 : 0 : goto finally; 74 : : } 75 : : 76 : : // Check the value is initially NULL 77 : : void *extra; 78 : 0 : int res = PyUnstable_Code_GetExtra(test_func_code, code_extra_index, &extra); 79 [ # # ]: 0 : if (res < 0) { 80 : 0 : goto finally; 81 : : } 82 [ # # ]: 0 : assert (extra == NULL); 83 : : 84 : : // Set another code extra value 85 : 0 : res = PyUnstable_Code_SetExtra(test_func_code, code_extra_index, (void*)(uintptr_t)77); 86 [ # # ]: 0 : if (res < 0) { 87 : 0 : goto finally; 88 : : } 89 : : // Assert it was set correctly 90 : 0 : res = PyUnstable_Code_GetExtra(test_func_code, code_extra_index, &extra); 91 [ # # ]: 0 : if (res < 0) { 92 : 0 : goto finally; 93 : : } 94 [ # # ]: 0 : assert ((uintptr_t)extra == 77); 95 : : // Revert to initial code extra value. 96 : 0 : res = PyUnstable_Code_SetExtra(test_func_code, code_extra_index, NULL); 97 [ # # ]: 0 : if (res < 0) { 98 : 0 : goto finally; 99 : : } 100 : 0 : result = Py_NewRef(Py_None); 101 : 0 : finally: 102 : 0 : Py_XDECREF(test_module); 103 : 0 : Py_XDECREF(test_func); 104 : 0 : return result; 105 : : } 106 : : 107 : : static PyMethodDef TestMethods[] = { 108 : : {"test_code_extra", test_code_extra, METH_NOARGS}, 109 : : {NULL}, 110 : : }; 111 : : 112 : : int 113 : 2 : _PyTestCapi_Init_Code(PyObject *m) { 114 [ - + ]: 2 : if (PyModule_AddFunctions(m, TestMethods) < 0) { 115 : 0 : return -1; 116 : : } 117 : : 118 : 2 : return 0; 119 : : }