File: thread.bs

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (205 lines) | stat: -rw-r--r-- 4,560 bytes parent folder | download
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
use ui;
use progvis:program;
use core:lang;

/**
 * Data for a thread in the program.
 */
class Thread extends Data {
	// Original thread.
	ProgThread src;

	// Stack frames.
	Frame[] frames;

	// Mirrorred data from the thread.
	Bool alive;
	Bool sleeping;
	Bool crashed;
	Bool afterReturn;
	Bool barriersAvailable;

	// Create.
	init(ProgThread thread) {
		init {
			src = thread;
		}
	}

	// Copy.
	init(Thread original) {
		init {
			src = original.src;
			frames = Frame[](original.frames);
			alive = original.alive;
			sleeping = original.sleeping;
			crashed = original.crashed;
			afterReturn = original.afterReturn;
		}
	}

	// Get current position.
	SrcPos? pos() {
		if (frames.any)
			return frames.last.pos;
		null;
	}

	// Get thread id.
	Nat id() { src.threadId; }

	// Traverse stack frames and find individual values.
	void update(World:Traversal t, unsafe:RawPtr object, Nat offset) : override {
		alive = src.alive;
		sleeping = src.sleeping;
		crashed = src.crashed;
		afterReturn = false;
		// In some cases, we can be executed before the thread has started properly.
		if (src.frames.any)
			afterReturn = src.frames.last.returned;
		barriersAvailable = src.barriersAvailable;

		if (!alive & !crashed) {
			// Remove frames, but not if we crashed (makes it easier to find the crash).
			frames.clear();
			return;
		}

		for (k, v in src.frames) {
			if (k >= frames.count)
				frames.push(Frame(v));
			if (frames[k].src !is v)
				frames[k] = Frame(v);
			frames[k].update(t, object, 0);
		}

		while (frames.count > src.frames.count)
			frames.pop();
	}

	// Traverse pointers.
	void traverse(World:Traversal t, unsafe:RawPtr object, Nat offset) : override {
		for (f in frames)
			f.traverse(t, object, 0);
	}

	// Title.
	Str title(World world) : override {
		"Thread " + src.threadId.toS;
	}

	// Type.
	Type? type() : override {
		null;
	}

	// Visit.
	void visit(DataVisitor v) : override {
		super:visit(v);
		for (f in frames)
			f.visit(v);
	}

	// Summary.
	protected void putSummary(StrBuf to, SummaryData data) : override {
		// Stack frames. We don't need a delimiter.
		for (f in frames) {
			f.summary(to, data);
		}
	}

	// Copy.
	protected Data copyObject() : override {
		Thread(this);
	}
	protected void copyData(Data->Data data) : override {
		for (Nat i = 0; i < frames.count; i++)
			if (x = frames[i].copy(data) as Frame)
				frames[i] = x;
	}

	// Stack frame.
	class Frame extends Composite {
		// Original stack frame.
		StackFrame src;

		// Source position for this stack frame.
		SrcPos pos;

		// Current offset in the function.
		Nat offset;

		// Create.
		init(StackFrame src) {
			init(null) {
				src = src;
			}
		}

		// Copy.
		init(Frame original) {
			init(original) {
				src = original.src;
				pos = original.pos;
			}
		}

		Str title(World world) : override {
			// This is safe: the same stack frame object does not modify its title.
			src.function;
		}

		void update(World:Traversal t, unsafe:RawPtr object, Nat offset) : override {
			pos = src.pos;
			offset = src.lastOffset;

			for (k, v in src.variables) {
				var ptr = unsafe:RawPtr(v.value);
				if (k >= parts.count) {
					parts << Part(v.name, 0, t.createStack(ptr), false);
				} else if (parts[k].name != v.name) {
					parts[k] = Part(v.name, 0, t.createStack(ptr), false);
				} else {
					var oldType = parts[k].value.type;
					var newType = ptr.type;
					if (oldType.empty | newType.empty) {
						// No need to replace if any of them said null.
					} else if (newType !is oldType) {
						parts[k].value = t.createStack(ptr);
					}
				}

				parts[k].value.update(t, ptr, 0);

				// Don't add the object if it is represented as a StackPointer object. The
				// StackPointer object treats the data as a pointer to the data, and not the value
				// itself. If we add that, all StackData objects will simply point to themselves.
				if (parts[k].value as StackPointer)
					;
				else
					t.addData(ptr, parts[k].value);
			}
			while (parts.count > src.variables.count)
				parts.pop();
		}

		void traverse(World:Traversal t, unsafe:RawPtr object, Nat offset) : override {
			for (k, v in src.variables) {
				var ptr = unsafe:RawPtr(v.value);
				parts[k].value.traverse(t, ptr, 0);
			}
		}

		protected Data copyObject() : override {
			Frame(this);
		}

		protected void putSummary(StrBuf to, SummaryData data) : override {
			// Put the location first:
			if (file = pos.file)
				to << file.title << ":" << pos.start << "-" << pos.end << "@" << offset << ".";
			super:putSummary(to, data);
		}
	}

}