in Python/Product/VsPyProf/PythonApi.cpp [128:240]
bool VsPyProf::GetUserToken(PyFrameObject* frameObj, DWORD_PTR& func, DWORD_PTR& module) {
auto codeObj = frameObj->f_code;
if (codeObj->ob_type == PyCode_Type) {
// extract func and module tokens
PyObject *filename = nullptr;
func = (DWORD_PTR)codeObj;
if (PyCodeObject25_27::IsFor(MajorVersion, MinorVersion)) {
filename = ((PyCodeObject25_27*)codeObj)->co_filename;
} else if (PyCodeObject30_32::IsFor(MajorVersion, MinorVersion)) {
filename = ((PyCodeObject30_32*)codeObj)->co_filename;
} else if (PyCodeObject33_35::IsFor(MajorVersion, MinorVersion)) {
filename = ((PyCodeObject33_35*)codeObj)->co_filename;
} else if (PyCodeObject36::IsFor(MajorVersion, MinorVersion)) {
filename = ((PyCodeObject36*)codeObj)->co_filename;
} else if (PyCodeObject37::IsFor(MajorVersion, MinorVersion)) {
filename = ((PyCodeObject37*)codeObj)->co_filename;
} else if (PyCodeObject38::IsFor(MajorVersion, MinorVersion)) {
filename = ((PyCodeObject38*)codeObj)->co_filename;
}
module = (DWORD_PTR)filename;
// see if the function is registered
if (_registeredObjects.find(func) == _registeredObjects.end()) {
// get module name and register it if not already registered
auto moduleIter = _registeredModules.find(module);
wstring moduleName;
if (moduleIter == _registeredModules.end()) {
ReferenceObject(filename);
wstring filenameStr;
GetName(filename, filenameStr);
// make sure we have a fully qualified path so the profiler can find our files...
if ((filenameStr.length() >= 2 && (filenameStr[0] != '\\' || filenameStr[1] != '\\')) &&
(filenameStr.length() >= 3 && (filenameStr[1] != ':' || filenameStr[2] != '\\'))) {
// not a fully qualified path, fully qualify it.
wchar_t buffer[MAX_PATH];
if (GetCurrentDirectory(MAX_PATH, buffer) != 0) {
if (filenameStr[0] != '\\' && wcslen(buffer) > 0 && buffer[wcslen(buffer) - 1] != '\\') {
filenameStr.insert(0, L"\\");
}
filenameStr.insert(0, buffer);
}
}
GetModuleName(filenameStr, moduleName);
_registeredModules[module] = moduleName;
// make sure we only have valid path chars, vsperfreport doesn't like invalid chars
for (size_t i = 0; i < filenameStr.length(); i++) {
if (filenameStr[i] == '<') {
filenameStr[i] = '(';
} else if (filenameStr[i] == '>') {
filenameStr[i] = ')';
} else if (filenameStr[i] == '|' ||
filenameStr[i] == '"' ||
filenameStr[i] == 124 ||
filenameStr[i] < 32) {
filenameStr[i] = '_';
}
}
_nameToken(module, filenameStr.c_str());
} else {
moduleName = (*moduleIter).second;
}
auto className = GetClassNameFromFrame(frameObj, codeObj);
if (className.length() != 0) {
if (moduleName.length() != 0) {
moduleName.append(L".");
moduleName.append(className);
} else {
moduleName = className;
}
}
ReferenceObject(codeObj);
// register function
_registeredObjects.insert(func);
// associate source information
int lineno = 0;
if (PyCodeObject25_27::IsFor(MajorVersion, MinorVersion)) {
RegisterName(func, ((PyCodeObject25_27*)codeObj)->co_name, &moduleName);
lineno = ((PyCodeObject25_27*)codeObj)->co_firstlineno;
} else if (PyCodeObject30_32::IsFor(MajorVersion, MinorVersion)) {
RegisterName(func, ((PyCodeObject30_32*)codeObj)->co_name, &moduleName);
lineno = ((PyCodeObject30_32*)codeObj)->co_firstlineno;
} else if (PyCodeObject33_35::IsFor(MajorVersion, MinorVersion)) {
RegisterName(func, ((PyCodeObject33_35*)codeObj)->co_name, &moduleName);
lineno = ((PyCodeObject33_35*)codeObj)->co_firstlineno;
} else if (PyCodeObject36::IsFor(MajorVersion, MinorVersion)) {
RegisterName(func, ((PyCodeObject36*)codeObj)->co_name, &moduleName);
lineno = ((PyCodeObject36*)codeObj)->co_firstlineno;
} else if (PyCodeObject37::IsFor(MajorVersion, MinorVersion)) {
RegisterName(func, ((PyCodeObject37*)codeObj)->co_name, &moduleName);
lineno = ((PyCodeObject37*)codeObj)->co_firstlineno;
} else if (PyCodeObject38::IsFor(MajorVersion, MinorVersion)) {
RegisterName(func, ((PyCodeObject38*)codeObj)->co_name, &moduleName);
lineno = ((PyCodeObject38*)codeObj)->co_firstlineno;
}
// give the profiler the line number of this function
_sourceLine(func, module, lineno);
}
return true;
}
return false;
}