105 lines
4.3 KiB
C++
105 lines
4.3 KiB
C++
// Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <Python.h>
|
|
#include <frameobject.h>
|
|
|
|
#include "paddle/fluid/framework/op_proto_maker.h"
|
|
#include "paddle/fluid/pir/dialect/operator/ir/api_builder.h"
|
|
#include "paddle/fluid/platform/enforce.h"
|
|
#include "paddle/fluid/pybind/op_callstack_utils.h"
|
|
|
|
pir::Attribute CallStackRecorder::GetOpCallstackInfo() {
|
|
PyObject* traceback_str = PyUnicode_FromString("traceback");
|
|
PyObject* traceback_module = PyImport_Import(traceback_str);
|
|
|
|
if (nullptr == traceback_module) {
|
|
Py_DECREF(traceback_str);
|
|
Py_DECREF(traceback_module);
|
|
PADDLE_THROW(common::errors::PreconditionNotMet(
|
|
"Failed to import traceback module while getting callstack information "
|
|
"for %s.",
|
|
api_name_));
|
|
}
|
|
PyObject* tb = PyObject_GetAttrString(traceback_module, "extract_stack");
|
|
PyObject* stack = PyObject_CallObject(tb, nullptr);
|
|
if (nullptr == stack) {
|
|
Py_DECREF(tb);
|
|
Py_DECREF(traceback_str);
|
|
Py_DECREF(traceback_module);
|
|
PADDLE_THROW(common::errors::PreconditionNotMet(
|
|
"Failed to get callstack object while getting callstack information "
|
|
"for "
|
|
"%s.",
|
|
api_name_));
|
|
}
|
|
Py_ssize_t stack_size = PyList_Size(stack);
|
|
std::vector<pir::Attribute> op_callstack_infos;
|
|
for (Py_ssize_t i = 0; i < stack_size; ++i) {
|
|
PyObject* frame_summary = PyList_GetItem(stack, i);
|
|
PyObject* filename = PyObject_GetAttrString(frame_summary, "filename");
|
|
PyObject* lineno = PyObject_GetAttrString(frame_summary, "lineno");
|
|
PyObject* name = PyObject_GetAttrString(frame_summary, "name");
|
|
PyObject* line = PyObject_GetAttrString(frame_summary, "line");
|
|
PyObject* callstack_info = PyUnicode_FromFormat(
|
|
" File \"%S\", line %S, in %S", filename, lineno, name);
|
|
PyObject* callstack_source_line = PyUnicode_FromFormat(" %S", line);
|
|
op_callstack_infos.push_back(
|
|
pir::StrAttribute::get(pir::IrContext::Instance(),
|
|
std::string(PyUnicode_AsUTF8(callstack_info))));
|
|
op_callstack_infos.push_back(pir::StrAttribute::get(
|
|
pir::IrContext::Instance(),
|
|
std::string(PyUnicode_AsUTF8(callstack_source_line))));
|
|
Py_DECREF(callstack_info);
|
|
Py_DECREF(callstack_source_line);
|
|
Py_DECREF(filename);
|
|
Py_DECREF(lineno);
|
|
Py_DECREF(name);
|
|
Py_DECREF(line);
|
|
}
|
|
Py_DECREF(tb);
|
|
Py_DECREF(traceback_str);
|
|
Py_DECREF(traceback_module);
|
|
return pir::ArrayAttribute::get(pir::IrContext::Instance(),
|
|
op_callstack_infos);
|
|
}
|
|
|
|
void CallStackRecorder::Record() {
|
|
auto before_insertion_point =
|
|
paddle::dialect::ApiBuilder::Instance().GetCurrentInsertionPoint();
|
|
before_insertion_iterator_ = (--before_insertion_point.second);
|
|
before_insertion_block_ = before_insertion_point.first;
|
|
}
|
|
|
|
void CallStackRecorder::AttachToOps() {
|
|
before_insertion_iterator_++;
|
|
pir::Attribute callstack_info_attr = GetOpCallstackInfo();
|
|
pir::InsertionPoint after_insertion_point =
|
|
paddle::dialect::ApiBuilder::Instance().GetCurrentInsertionPoint();
|
|
PADDLE_ENFORCE_EQ(before_insertion_block_,
|
|
after_insertion_point.first,
|
|
common::errors::PreconditionNotMet(
|
|
"The block obtained before and after calling the "
|
|
"static API %s is inconsistent.",
|
|
api_name_));
|
|
auto after_insertion_iterator = after_insertion_point.second;
|
|
for (auto block_iterator = before_insertion_iterator_;
|
|
block_iterator != after_insertion_iterator;
|
|
block_iterator++) {
|
|
block_iterator->set_attribute(paddle::framework::OpProtoAndCheckerMaker::
|
|
OpCreationCallstackAttrName(),
|
|
callstack_info_attr);
|
|
}
|
|
}
|