mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			122 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "parts.h"
 | 
						|
#include "util.h"
 | 
						|
 | 
						|
static Py_ssize_t
 | 
						|
get_code_extra_index(PyInterpreterState* interp) {
 | 
						|
    Py_ssize_t result = -1;
 | 
						|
 | 
						|
    static const char *key = "_testcapi.frame_evaluation.code_index";
 | 
						|
 | 
						|
    PyObject *interp_dict = PyInterpreterState_GetDict(interp); // borrowed
 | 
						|
    assert(interp_dict);  // real users would handle missing dict... somehow
 | 
						|
 | 
						|
    PyObject *index_obj;
 | 
						|
    if (PyDict_GetItemStringRef(interp_dict, key, &index_obj) < 0) {
 | 
						|
        goto finally;
 | 
						|
    }
 | 
						|
    Py_ssize_t index = 0;
 | 
						|
    if (!index_obj) {
 | 
						|
        index = PyUnstable_Eval_RequestCodeExtraIndex(NULL);
 | 
						|
        if (index < 0 || PyErr_Occurred()) {
 | 
						|
            goto finally;
 | 
						|
        }
 | 
						|
        index_obj = PyLong_FromSsize_t(index); // strong ref
 | 
						|
        if (!index_obj) {
 | 
						|
            goto finally;
 | 
						|
        }
 | 
						|
        int res = PyDict_SetItemString(interp_dict, key, index_obj);
 | 
						|
        Py_DECREF(index_obj);
 | 
						|
        if (res < 0) {
 | 
						|
            goto finally;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        index = PyLong_AsSsize_t(index_obj);
 | 
						|
        Py_DECREF(index_obj);
 | 
						|
        if (index == -1 && PyErr_Occurred()) {
 | 
						|
            goto finally;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    result = index;
 | 
						|
finally:
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
test_code_extra(PyObject* self, PyObject *Py_UNUSED(callable))
 | 
						|
{
 | 
						|
    PyObject *result = NULL;
 | 
						|
    PyObject *test_module = NULL;
 | 
						|
    PyObject *test_func = NULL;
 | 
						|
 | 
						|
    // Get or initialize interpreter-specific code object storage index
 | 
						|
    PyInterpreterState *interp = PyInterpreterState_Get();
 | 
						|
    if (!interp) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
    Py_ssize_t code_extra_index = get_code_extra_index(interp);
 | 
						|
    if (PyErr_Occurred()) {
 | 
						|
        goto finally;
 | 
						|
    }
 | 
						|
 | 
						|
    // Get a function to test with
 | 
						|
    // This can be any Python function. Use `test.test_misc.testfunction`.
 | 
						|
    test_module = PyImport_ImportModule("test.test_capi.test_misc");
 | 
						|
    if (!test_module) {
 | 
						|
        goto finally;
 | 
						|
    }
 | 
						|
    test_func = PyObject_GetAttrString(test_module, "testfunction");
 | 
						|
    if (!test_func) {
 | 
						|
        goto finally;
 | 
						|
    }
 | 
						|
    PyObject *test_func_code = PyFunction_GetCode(test_func);  // borrowed
 | 
						|
    if (!test_func_code) {
 | 
						|
        goto finally;
 | 
						|
    }
 | 
						|
 | 
						|
    // Check the value is initially NULL
 | 
						|
    void *extra = UNINITIALIZED_PTR;
 | 
						|
    int res = PyUnstable_Code_GetExtra(test_func_code, code_extra_index, &extra);
 | 
						|
    if (res < 0) {
 | 
						|
        goto finally;
 | 
						|
    }
 | 
						|
    assert (extra == NULL);
 | 
						|
 | 
						|
    // Set another code extra value
 | 
						|
    res = PyUnstable_Code_SetExtra(test_func_code, code_extra_index, (void*)(uintptr_t)77);
 | 
						|
    if (res < 0) {
 | 
						|
        goto finally;
 | 
						|
    }
 | 
						|
    // Assert it was set correctly
 | 
						|
    extra = UNINITIALIZED_PTR;
 | 
						|
    res = PyUnstable_Code_GetExtra(test_func_code, code_extra_index, &extra);
 | 
						|
    if (res < 0) {
 | 
						|
        goto finally;
 | 
						|
    }
 | 
						|
    assert ((uintptr_t)extra == 77);
 | 
						|
    // Revert to initial code extra value.
 | 
						|
    res = PyUnstable_Code_SetExtra(test_func_code, code_extra_index, NULL);
 | 
						|
    if (res < 0) {
 | 
						|
        goto finally;
 | 
						|
    }
 | 
						|
    result = Py_NewRef(Py_None);
 | 
						|
finally:
 | 
						|
    Py_XDECREF(test_module);
 | 
						|
    Py_XDECREF(test_func);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
static PyMethodDef TestMethods[] = {
 | 
						|
    {"test_code_extra", test_code_extra, METH_NOARGS},
 | 
						|
    {NULL},
 | 
						|
};
 | 
						|
 | 
						|
int
 | 
						|
_PyTestCapi_Init_Code(PyObject *m) {
 | 
						|
    if (PyModule_AddFunctions(m, TestMethods) < 0) {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 |