loom

Форк
0
/
ModuleManagement_debug.cpp 
250 строк · 9.3 Кб
1
/*
2
MIT License
3

4
Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
5

6
https://bmstu.codes/lsx/simodo/loom
7
*/
8

9
#include "simodo/module/ModuleManagement.h"
10
#include "simodo/interpret/Interpret.h"
11
#include "simodo/inout/convert/functions.h"
12
#include "simodo/inout/format/fmt.h"
13

14
#include <cstdio>
15
#include <cassert>
16

17
constexpr int BUFFER_SIZE = 1024;
18

19
namespace simodo::module
20
{
21
    bool ModuleManagement::debug(const inout::uri_set_t & files)
22
    {
23
        bool     done    = true;
24

25
        std::unique_lock<std::mutex> locking(_debug_condition_mutex);
26
        if (_timeout > 0)
27
            done = _debug_condition.wait_for(locking, std::chrono::seconds(_timeout)) == std::cv_status::no_timeout;
28
        else
29
            _debug_condition.wait(locking);
30

31
        const loom::Fiber_interface *     causer = _loom.causer();
32
        std::vector<loom::FiberStructure> fibers = _loom.fibers();
33

34
        if (done && !causer) {
35
            _loom.finish();
36
            return true;
37
        }
38

39
        if (causer)
40
            _m.reportInformation(inout::fmt("Остановка программы произошла из-за нити %1")
41
                                 .arg(getFiberName(findFiberStructure(fibers,causer))));
42
        else {
43
            _loom.pause();
44
            assert(_loom.paused());
45
            
46
            _m.reportInformation(inout::fmt("Программа работала дольше %1 сек и была остановлена")
47
                                .arg(_timeout));
48
        }
49
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
50

51
        _m.reportInformation(inout::fmt("Индексы исходных файлов:"));
52
        for(size_t i=0; i < files.size(); ++i)
53
            _m.reportInformation(std::to_string(i) + ". " + files[i]);
54

55
        _m.reportInformation(inout::fmt("Структура нитей (name/no, status, (file,line,host,op), need_delete, waiting_for_no, error? causer?):"));
56

57
        fibers = _loom.fibers();
58

59
        bool errors = false;
60
        for(const loom::FiberStructure & fs : fibers) {
61
            if (fs.p_parent == nullptr)
62
                printFiberBranch(fibers, fs, causer);
63

64
            if (fs.status == loom::FiberStatus::Paused) {
65
                interpret::Interpret_interface * p_interpret = dynamic_cast<interpret::Interpret_interface *>(fs.p_fiber);
66
                if (p_interpret && p_interpret->errors()) {
67
                    errors = true;
68
                    break;
69
                }
70
            }
71
        }
72

73
        if (_resume && !errors) {
74
            _loom.resume();
75
            _loom.finish();
76
            return true;
77
        }
78
        
79
        _loom.stop();
80
        return false;
81
    }
82

83
    ///////////////////////////////////////////////////////////////////////////////
84
    // Private
85

86
    void ModuleManagement::printFiberBranch(
87
                     const std::vector<loom::FiberStructure> & fibers, 
88
                     const loom::FiberStructure & fs, 
89
                     const loom::Fiber_interface * causer,
90
                     int depth) const
91
    {
92
        std::string info, err;
93
        interpret::Interpret_interface * p_interpret = nullptr;
94

95
        if (fs.status == loom::FiberStatus::Flow)
96
            info = "(*)";
97
        else {
98
            p_interpret = dynamic_cast<interpret::Interpret_interface *>(fs.p_fiber);
99

100
            if (p_interpret) {
101
                info = getInfo(p_interpret->lookupOperationNode());
102
                err = p_interpret->errors() ? ", error" : "";
103
            }
104
            else
105
                info = "?";
106
        }
107

108
        if (fs.p_fiber == causer)
109
            err += " causer";
110

111
        char buffer[BUFFER_SIZE];
112

113
        snprintf(buffer, BUFFER_SIZE, 
114
                "%s> %s, %s, %s, %s, %s%s", 
115
                std::string(depth,'-').c_str(), 
116
                getFiberName(fs).c_str(),
117
                loom::getFiberStatusName(fs.status),
118
                info.c_str(),
119
                (fs.need_delete ? "yes" : "no"),
120
                fs.p_waiting_for ? getFiberName(findFiberStructure(fibers,fs.p_waiting_for)).c_str() : "-",
121
                err.c_str());
122

123
        _m.reportInformation(buffer);
124

125
        if (p_interpret)
126
            if (fs.status == loom::FiberStatus::Paused || fs.status == loom::FiberStatus::Delayed)
127
                if (_need_full_debug_info || fs.p_fiber == causer)
128
                    printCallStack(*p_interpret);
129

130
        for(const loom::FiberStructure & child : fibers)
131
            if (child.p_parent == fs.p_fiber)
132
                printFiberBranch(fibers, child, causer, depth+1);
133
    }
134

135
    void ModuleManagement::printCallStack(const interpret::Interpret_interface & interp) const
136
    {
137
        std::vector<interpret::boundary_index_t> frames = interp.stack().getFunctionBounds();
138

139
        for(size_t i=0; i < frames.size(); ++i) {
140
            interpret::boundary_index_t fi                = frames[i];
141
            auto                        [begin, end]      = interp.stack().boundaryLowAndTop(fi);
142
            interpret::name_index_t     function_index    = begin - 1;
143
            const variable::Variable    function_variable = function_index >= interp.stack().index_over_top() 
144
                                                          ? variable::error_variable()
145
                                                          : interp.stack().variable(function_index);
146
            std::string text;
147

148
            if (i > 0) {
149
                    const ast::Node * p_node = interp.lookupOperationNode(0,frames[i]);
150

151
                    if (p_node)
152
                        text = inout::fmt("\tcalled from %1:").arg(getInfo(p_node));
153
                    else if (function_variable.type() == variable::ValueType::Ref) {
154
                        text = inout::fmt("\tcall point is out, formal call location: (f:%1, l:%2):")
155
                                .arg(function_variable.location().uri_index())
156
                                .arg(function_variable.location().range().start().line()+1);
157
                    }
158
                    else
159
                        text = inout::fmt("\tcall point is out");
160

161
                _m.reportInformation(text);
162
                text = {};
163
            }
164

165
            if (function_variable.origin().value().isFunction()) {
166
                variable::FunctionWrapper    function(function_variable);
167
                const variable::Variable &   return_type    = function.getReturnDeclarationVariable();
168
                variable::VariableSetWrapper declarations   = function.getArgumentDeclarationVariables();
169

170
                text += "\tfn " + inout::toU8(function_variable.origin().name())
171
                      + "(";
172
                for(size_t i=0; i < declarations.size(); ++i) {
173
                    if (i > 0)
174
                        text += ", ";
175

176
                    text += variable::getValueTypeName(declarations[i].type());
177

178
                    if (!declarations[i].name().empty())
179
                        text += " " + inout::toU8(declarations[i].name());
180
                }
181
                text += ")";
182
                if (return_type.type() != variable::ValueType::Null)
183
                    text += " -> " + variable::getValueTypeName(return_type.type());
184
            }
185
            else
186
                text += "\t<root module>";
187

188
            _m.reportInformation(text);
189

190
            printLocals(interp, fi);
191
        }
192
    }
193

194
    void ModuleManagement::printLocals(const interpret::Interpret_interface & causer, 
195
                    interpret::boundary_index_t frame_index) const
196
    {
197
        std::vector<interpret::boundary_index_t> frames = causer.stack().getFunctionBounds();
198

199
        assert(!frames.empty());
200

201
        if (frame_index > frames.front())
202
            frame_index = frames.front();
203

204
        std::vector<interpret::name_index_t> locals = causer.stack().getFrameLocals(frame_index);
205

206
        for(interpret::name_index_t i : locals) {
207
            const variable::Variable &   v = causer.stack().variable(i);
208

209
            _m.reportInformation("\t\t" + inout::toU8(v.origin().name()) + " = " + inout::toU8(variable::toString(v.origin().value())));
210
        }
211
    }
212

213
    std::string ModuleManagement::getInfo(const ast::Node * p) const
214
    {
215
        std::string info;
216

217
        if (p)
218
            info = "f:" + std::to_string(int(p->token().location().uri_index())) + ", "
219
                 + "l:" + std::to_string(p->token().location().range().start().line()+1) + ", "
220
                 + "h:" + inout::toU8(p->host()) + ", "
221
                 + "o:" + std::to_string(int(p->operation()));
222
        else
223
            info = "-";
224

225
        return "(" + info + ")";
226
    }
227

228
    std::string ModuleManagement::getFiberName(const loom::FiberStructure & fs) const
229
    {
230
        if (fs.name.empty())
231
            return std::to_string(int(fs.no));
232

233
        return fs.name + "/" + std::to_string(int(fs.no));
234
    }
235

236
    const loom::FiberStructure &ModuleManagement::findFiberStructure(const std::vector<loom::FiberStructure> & fibers, const loom::Fiber_interface * p_fiber) const
237
    {
238
        static const loom::FiberStructure none {nullptr,nullptr,false,loom::FiberStatus::Complete,0,{}};
239

240
        auto const it = std::find_if(fibers.begin(), fibers.end(), [p_fiber](const loom::FiberStructure & fs){
241
                        return fs.p_fiber == p_fiber;                        
242
                    });
243

244
        if (it == fibers.end())
245
            return none;
246

247
        return *it;
248
    }
249

250
}
251

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.