xref: /haiku/src/kits/debugger/debug_managers/ValueNodeManager.cpp (revision 8a6724a0ee3803f1e9f487d8111bb3f6cb8d16db)
1 /*
2  * Copyright 2012-2016, Rene Gollent, rene@gollent.com.
3  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include "ValueNodeManager.h"
8 
9 #include "AutoLocker.h"
10 
11 #include "model/Thread.h"
12 #include "StackFrame.h"
13 #include "Team.h"
14 #include "TypeHandlerRoster.h"
15 #include "ValueNode.h"
16 #include "Variable.h"
17 #include "VariableValueNodeChild.h"
18 
19 
20 ValueNodeManager::ValueNodeManager(bool addFrameNodes)
21 	:
22 	fAddFrameNodes(addFrameNodes),
23 	fContainer(NULL),
24 	fStackFrame(NULL),
25 	fThread(NULL)
26 {
27 	SetStackFrame(NULL, NULL);
28 }
29 
30 
31 ValueNodeManager::~ValueNodeManager()
32 {
33 	SetStackFrame(NULL, NULL);
34 }
35 
36 
37 status_t
38 ValueNodeManager::SetStackFrame(Thread* thread,
39 	StackFrame* stackFrame)
40 {
41 	if (fContainer != NULL) {
42 		AutoLocker<ValueNodeContainer> containerLocker(fContainer);
43 
44 		fContainer->RemoveListener(this);
45 
46 		fContainer->RemoveAllChildren();
47 		containerLocker.Unlock();
48 		fContainer->ReleaseReference();
49 		fContainer = NULL;
50 	}
51 
52 	fStackFrame = stackFrame;
53 	fThread = thread;
54 
55 	fContainer = new(std::nothrow) ValueNodeContainer;
56 	if (fContainer == NULL)
57 		return B_NO_MEMORY;
58 
59 	status_t error = fContainer->Init();
60 	if (error != B_OK) {
61 		delete fContainer;
62 		fContainer = NULL;
63 		return error;
64 	}
65 
66 	AutoLocker<ValueNodeContainer> containerLocker(fContainer);
67 
68 	fContainer->AddListener(this);
69 
70 	if (fStackFrame != NULL && fAddFrameNodes) {
71 		for (int32 i = 0; Variable* variable = fStackFrame->ParameterAt(i);
72 				i++) {
73 			_AddNode(variable);
74 		}
75 
76 		for (int32 i = 0; Variable* variable
77 				= fStackFrame->LocalVariableAt(i); i++) {
78 			_AddNode(variable);
79 		}
80 	}
81 
82 	return B_OK;
83 }
84 
85 
86 bool
87 ValueNodeManager::AddListener(ValueNodeContainer::Listener* listener)
88 {
89 	return fListeners.AddItem(listener);
90 }
91 
92 
93 void
94 ValueNodeManager::RemoveListener(ValueNodeContainer::Listener* listener)
95 {
96 	fListeners.RemoveItem(listener);
97 }
98 
99 
100 void
101 ValueNodeManager::ValueNodeChanged(ValueNodeChild* nodeChild,
102 	ValueNode* oldNode, ValueNode* newNode)
103 {
104 	if (fContainer == NULL)
105 		return;
106 
107 	AutoLocker<ValueNodeContainer> containerLocker(fContainer);
108 
109 	for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
110 		fListeners.ItemAt(i)->ValueNodeChanged(nodeChild, oldNode, newNode);
111 
112 	if (oldNode != NULL)
113 		newNode->CreateChildren(fThread->GetTeam()->GetTeamTypeInformation());
114 
115 }
116 
117 
118 void
119 ValueNodeManager::ValueNodeChildrenCreated(ValueNode* node)
120 {
121 	if (fContainer == NULL)
122 		return;
123 
124 	for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
125 		fListeners.ItemAt(i)->ValueNodeChildrenCreated(node);
126 }
127 
128 
129 void
130 ValueNodeManager::ValueNodeChildrenDeleted(ValueNode* node)
131 {
132 	if (fContainer == NULL)
133 		return;
134 
135 	for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
136 		fListeners.ItemAt(i)->ValueNodeChildrenDeleted(node);
137 }
138 
139 
140 void
141 ValueNodeManager::ValueNodeValueChanged(ValueNode* valueNode)
142 {
143 	if (fContainer == NULL)
144 		return;
145 
146 	AutoLocker<ValueNodeContainer> containerLocker(fContainer);
147 
148 	// check whether we know the node
149 	ValueNodeChild* nodeChild = valueNode->NodeChild();
150 	if (nodeChild == NULL)
151 		return;
152 
153 	if (valueNode->ChildCreationNeedsValue()
154 		&& !valueNode->ChildrenCreated()) {
155 		status_t error = valueNode->CreateChildren(
156 			fThread->GetTeam()->GetTeamTypeInformation());
157 		if (error == B_OK) {
158 			for (int32 i = 0; i < valueNode->CountChildren(); i++) {
159 				ValueNodeChild* child = valueNode->ChildAt(i);
160 				_CreateValueNode(child);
161 				AddChildNodes(child);
162 			}
163 		}
164 	}
165 
166 	for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
167 		fListeners.ItemAt(i)->ValueNodeValueChanged(valueNode);
168 }
169 
170 
171 void
172 ValueNodeManager::_AddNode(Variable* variable)
173 {
174 	// create the node child for the variable
175 	ValueNodeChild* nodeChild = new (std::nothrow) VariableValueNodeChild(
176 		variable);
177 	BReference<ValueNodeChild> nodeChildReference(nodeChild, true);
178 	if (nodeChild == NULL || !fContainer->AddChild(nodeChild)) {
179 		delete nodeChild;
180 		return;
181 	}
182 
183 	// automatically add child nodes for the top level nodes
184 	AddChildNodes(nodeChild);
185 }
186 
187 
188 status_t
189 ValueNodeManager::_CreateValueNode(ValueNodeChild* nodeChild)
190 {
191 	if (nodeChild->Node() != NULL)
192 		return B_OK;
193 
194 	// create the node
195 	ValueNode* valueNode;
196 	status_t error;
197 	if (nodeChild->IsInternal()) {
198 		error = nodeChild->CreateInternalNode(valueNode);
199 	} else {
200 		error = TypeHandlerRoster::Default()->CreateValueNode(nodeChild,
201 			nodeChild->GetType(), valueNode);
202 	}
203 
204 	if (error != B_OK)
205 		return error;
206 
207 	nodeChild->SetNode(valueNode);
208 	valueNode->ReleaseReference();
209 
210 	return B_OK;
211 }
212 
213 
214 status_t
215 ValueNodeManager::AddChildNodes(ValueNodeChild* nodeChild)
216 {
217 	AutoLocker<ValueNodeContainer> containerLocker(fContainer);
218 
219 	// create a value node for the value node child, if doesn't have one yet
220 	ValueNode* valueNode = nodeChild->Node();
221 	if (valueNode == NULL) {
222 		status_t error = _CreateValueNode(nodeChild);
223 		if (error != B_OK)
224 			return error;
225 		valueNode = nodeChild->Node();
226 	}
227 
228 	// check if this node requires child creation
229 	// to be deferred until after its location/value have been resolved
230 	if (valueNode->ChildCreationNeedsValue())
231 		return B_OK;
232 
233 	// create the children, if not done yet
234 	if (valueNode->ChildrenCreated())
235 		return B_OK;
236 
237 	return valueNode->CreateChildren(
238 		fThread->GetTeam()->GetTeamTypeInformation());
239 }
240