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 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 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& 68 ExpressionEvaluationJob::Key() const 69 { 70 return fKey; 71 } 72 73 74 status_t 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 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