1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
#pragma once
#include "Array.h"
namespace storm {
STORM_PKG(core);
/**
* Represents a stack trace from some point in the execution.
*
* Internally, the trace is stored as a list of pointers to locations inside the functions that
* were executed when the trace was captured. This class contains facilities to resolve the
* pointers into symbolic names to make the trace more easily readable. This is not done
* automatically, however, since many stack traces captured for exceptions do not need to be
* resolved if the exception is caught and never shown to the user.
*/
class StackTrace {
STORM_VALUE;
public:
// Create an empty stack trace.
StackTrace(Engine &e);
// Deep copy.
void STORM_FN deepCopy(CloneEnv *env);
/**
* A single stack frame.
*
* This is basically a pointer, but due to GC constraints, we need to keep a pointer to the
* start of each function and an offset rather than a pointer into the object.
*/
class Frame {
STORM_VALUE;
public:
Frame(void *base, Nat offset, Nat id);
// Pointer to the start of the function.
UNKNOWN(PTR_GC) void *base;
// Offset into the function (bytes).
Nat offset;
// ID of the backend producing this frame.
// If the ID is 'nextThread', this frame indicates that the remainder of the stack trace
// indicates the frames of the thread that waits for the initial thread to complete.
// This is to make it easier to trace the execution through thread switches. This data
// is added after the fact by the Future implementation.
Nat id;
// ID to use for "next thread":
static Nat STORM_FN nextThread() { return Nat(-1); }
// Compute the pointer.
inline void *ptr() const {
return (byte *)base + offset;
}
};
// Add an element to the trace (to the bottom).
inline void push(Frame frame) { frames->push(frame); }
// Reserve space.
inline void reserve(Nat size) { frames->reserve(size); }
// Get elements.
inline Nat STORM_FN count() const { return frames->count(); }
inline Frame STORM_FN operator[] (Nat i) const { return frames->at(i); }
// Empty?
inline Bool STORM_FN empty() const { return frames->empty(); }
inline Bool STORM_FN any() const { return frames->any(); }
// Format into a string.
Str *STORM_FN format() const;
void STORM_FN format(StrBuf *to) const;
// Output.
void STORM_FN toS(StrBuf *to) const;
private:
// Data.
Array<Frame> *frames;
};
// Output the stack trace.
wostream &operator <<(wostream &to, const StackTrace &trace);
// Collect a stack trace.
StackTrace STORM_FN collectStackTrace(EnginePtr e);
// Collect a stack trace, ignore the topmost `ignore` frames.
StackTrace STORM_FN collectStackTrace(EnginePtr e, Nat ignore);
// Collect a stack trace, passing a pointer to previously collected stack state.
StackTrace collectStackTrace(EnginePtr e, void *state);
// Append a stack trace to 'StackTrace' from the current thread. Inserts a "next thread" frame in between.
void appendStackTrace(StackTrace &to, Nat ignore);
}
|