xref: /haiku/src/kits/debugger/jobs/ExpressionEvaluationJob.cpp (revision fce4895d1884da5ae6fb299d23c735c598e690b1)
1 /*
2  * Copyright 2014-2016, Rene Gollent, rene@gollent.com.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "Jobs.h"
7 
8 #include <String.h>
9 
10 #include <AutoLocker.h>
11 
12 #include "DebuggerInterface.h"
13 #include "ExpressionInfo.h"
14 #include "model/Thread.h"
15 #include "SourceLanguage.h"
16 #include "StackFrame.h"
17 #include "Team.h"
18 #include "Type.h"
19 #include "Value.h"
20 #include "ValueNode.h"
21 #include "ValueNodeManager.h"
22 #include "Variable.h"
23 
24 
ExpressionEvaluationJob(Team * team,DebuggerInterface * debuggerInterface,SourceLanguage * language,ExpressionInfo * info,StackFrame * frame,::Thread * thread)25 ExpressionEvaluationJob::ExpressionEvaluationJob(Team* team,
26 	DebuggerInterface* debuggerInterface, SourceLanguage* language,
27 	ExpressionInfo* info, StackFrame* frame,
28 	::Thread* thread)
29 	:
30 	fKey(info->Expression(), JOB_TYPE_EVALUATE_EXPRESSION),
31 	fTeam(team),
32 	fDebuggerInterface(debuggerInterface),
33 	fArchitecture(debuggerInterface->GetArchitecture()),
34 	fTypeInformation(team->GetTeamTypeInformation()),
35 	fLanguage(language),
36 	fExpressionInfo(info),
37 	fFrame(frame),
38 	fThread(thread),
39 	fManager(NULL),
40 	fResultValue(NULL)
41 {
42 	fLanguage->AcquireReference();
43 	fExpressionInfo->AcquireReference();
44 
45 	if (fFrame != NULL)
46 		fFrame->AcquireReference();
47 	if (fThread != NULL)
48 		fThread->AcquireReference();
49 }
50 
51 
~ExpressionEvaluationJob()52 ExpressionEvaluationJob::~ExpressionEvaluationJob()
53 {
54 	fLanguage->ReleaseReference();
55 	fExpressionInfo->ReleaseReference();
56 	if (fFrame != NULL)
57 		fFrame->ReleaseReference();
58 	if (fThread != NULL)
59 		fThread->ReleaseReference();
60 	if (fManager != NULL)
61 		fManager->ReleaseReference();
62 	if (fResultValue != NULL)
63 		fResultValue->ReleaseReference();
64 }
65 
66 
67 const JobKey&
Key() const68 ExpressionEvaluationJob::Key() const
69 {
70 	return fKey;
71 }
72 
73 
74 status_t
Do()75 ExpressionEvaluationJob::Do()
76 {
77 	BReference<Value> reference;
78 	status_t result = B_OK;
79 	if (fFrame != NULL && fManager == NULL) {
80 		fManager = new(std::nothrow) ValueNodeManager();
81 		if (fManager == NULL)
82 			result = B_NO_MEMORY;
83 		else
84 			result = fManager->SetStackFrame(fThread, fFrame);
85 	}
86 
87 	if (result != B_OK) {
88 		fExpressionInfo->NotifyExpressionEvaluated(result, NULL);
89 		return result;
90 	}
91 
92 	ValueNode* neededNode = NULL;
93 	result = fLanguage->EvaluateExpression(fExpressionInfo->Expression(),
94 		fManager, fTeam->GetTeamTypeInformation(), fResultValue, neededNode);
95 	if (neededNode != NULL) {
96 		result = ResolveNodeValue(neededNode);
97 		if (State() == JOB_STATE_WAITING)
98 			return B_OK;
99 		// if result != B_OK, fall through
100 	}
101 
102 	fExpressionInfo->NotifyExpressionEvaluated(result, fResultValue);
103 
104 	return B_OK;
105 }
106 
107 
108 status_t
ResolveNodeValue(ValueNode * node)109 ExpressionEvaluationJob::ResolveNodeValue(ValueNode* node)
110 {
111 	AutoLocker<Worker> workerLocker(GetWorker());
112 	SimpleJobKey jobKey(node, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
113 
114 	status_t error = B_OK;
115 	if (GetWorker()->GetJob(jobKey) == NULL) {
116 		workerLocker.Unlock();
117 
118 		// schedule the job
119 		error = GetWorker()->ScheduleJob(
120 			new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
121 				fArchitecture, fThread->GetCpuState(), fTypeInformation,
122 				fManager->GetContainer(), node));
123 		if (error != B_OK) {
124 			// scheduling failed -- set the value to invalid
125 			node->SetLocationAndValue(NULL, NULL, error);
126 			return error;
127 		}
128 	}
129 
130 	// wait for the job to finish
131 	workerLocker.Unlock();
132 
133 
134 	switch (WaitFor(jobKey)) {
135 		case JOB_DEPENDENCY_SUCCEEDED:
136 		case JOB_DEPENDENCY_NOT_FOUND:
137 		case JOB_DEPENDENCY_ACTIVE:
138 			error = B_OK;
139 			break;
140 		case JOB_DEPENDENCY_FAILED:
141 		case JOB_DEPENDENCY_ABORTED:
142 		default:
143 			error = B_ERROR;
144 			break;
145 	}
146 
147 	return error;
148 }
149