* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*/
#include "recordfuncobject.h"
#include "../event_trace/python_trace.h"
#include "../event_trace/trace_manager/event_trace_manager.h"
#include "cpython.h"
#include "utils.h"
namespace MemScope {
const size_t MAX_RECORD_FUNCTION_LENGTH = 128;
static PyObject* PyMemScopeNewRecordFunction(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
if (type == nullptr || type->tp_alloc == nullptr) {
return nullptr;
}
static PyObject *self = nullptr;
if (self == nullptr) {
self = type->tp_alloc(type, 0);
}
Py_XINCREF(self);
return self;
}
PyDoc_STRVAR(RecordStartDoc,
"record_start($self, funcname)\n--\n\nEnable debug.");
static PyObject* PyMemScopeRecordStart(PyObject *self, PyObject *arg)
{
if(!EventTraceManager::Instance().IsTracingEnabled()) {
Py_RETURN_NONE;
}
if (!PyUnicode_Check(arg)) {
PyErr_SetString(PyExc_TypeError, "[msmemscope] Error: Expected a string argument");
return nullptr;
}
std::string str = Utility::PythonObject(arg).Cast<std::string>();
if (str.size() > MAX_RECORD_FUNCTION_LENGTH) {
PyErr_Format(PyExc_ValueError, "[msmemscope] Error: Input funcname exceeds maximum allowed length %zu.", MAX_RECORD_FUNCTION_LENGTH);
Py_RETURN_NONE;
}
PythonTrace::GetInstance().RecordFuncPyCall(str, str, 0);
Py_RETURN_NONE;
}
PyDoc_STRVAR(RecordEndDoc,
"record_end($self, funcname)\n--\n\nEnable debug.");
static PyObject* PyMemScopeRecordEnd(PyObject *self, PyObject *arg)
{
if(!EventTraceManager::Instance().IsTracingEnabled()) {
Py_RETURN_NONE;
}
if (!PyUnicode_Check(arg)) {
PyErr_SetString(PyExc_TypeError, "[msmemscope] Error: Expected a string argument");
return nullptr;
}
std::string str = Utility::PythonObject(arg).Cast<std::string>();
if (str.size() > MAX_RECORD_FUNCTION_LENGTH) {
PyErr_Format(PyExc_ValueError, "[msmemscope] Error: Input funcname exceeds maximum allowed length %zu.", MAX_RECORD_FUNCTION_LENGTH);
Py_RETURN_NONE;
}
PythonTrace::GetInstance().RecordFuncReturn(str, str);
Py_RETURN_NONE;
}
static PyMethodDef PyMemScopeRecordFunctionMethods[] = {
{"record_start", reinterpret_cast<PyCFunction>(PyMemScopeRecordStart), METH_O, RecordStartDoc},
{"record_end", reinterpret_cast<PyCFunction>(PyMemScopeRecordEnd), METH_O, RecordEndDoc},
{nullptr, nullptr, 0, nullptr}
};
static PyTypeObject PyMemScopeRecordFunctionType = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"_msmemscope._record_function",
0,
0,
nullptr,
0,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
Py_TPFLAGS_DEFAULT,
nullptr,
nullptr,
nullptr,
nullptr,
0,
nullptr,
nullptr,
PyMemScopeRecordFunctionMethods,
nullptr,
nullptr,
&PyBaseObject_Type,
nullptr,
nullptr,
nullptr,
0,
nullptr,
nullptr,
PyMemScopeNewRecordFunction,
PyObject_Del,
};
PyObject* PyMemScope_GetRecordFunction()
{
if (PyType_Ready(&PyMemScopeRecordFunctionType) < 0) {
return nullptr;
}
return PyObject_New(PyObject, &PyMemScopeRecordFunctionType);
}
}