/* * Copyright 2014-2016, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #include "Jobs.h" #include #include #include "DebuggerInterface.h" #include "ExpressionInfo.h" #include "model/Thread.h" #include "SourceLanguage.h" #include "StackFrame.h" #include "Team.h" #include "Type.h" #include "Value.h" #include "ValueNode.h" #include "ValueNodeManager.h" #include "Variable.h" ExpressionEvaluationJob::ExpressionEvaluationJob(Team* team, DebuggerInterface* debuggerInterface, SourceLanguage* language, ExpressionInfo* info, StackFrame* frame, ::Thread* thread) : fKey(info->Expression(), JOB_TYPE_EVALUATE_EXPRESSION), fTeam(team), fDebuggerInterface(debuggerInterface), fArchitecture(debuggerInterface->GetArchitecture()), fTypeInformation(team->GetTeamTypeInformation()), fLanguage(language), fExpressionInfo(info), fFrame(frame), fThread(thread), fManager(NULL), fResultValue(NULL) { fLanguage->AcquireReference(); fExpressionInfo->AcquireReference(); if (fFrame != NULL) fFrame->AcquireReference(); if (fThread != NULL) fThread->AcquireReference(); } ExpressionEvaluationJob::~ExpressionEvaluationJob() { fLanguage->ReleaseReference(); fExpressionInfo->ReleaseReference(); if (fFrame != NULL) fFrame->ReleaseReference(); if (fThread != NULL) fThread->ReleaseReference(); if (fManager != NULL) fManager->ReleaseReference(); if (fResultValue != NULL) fResultValue->ReleaseReference(); } const JobKey& ExpressionEvaluationJob::Key() const { return fKey; } status_t ExpressionEvaluationJob::Do() { BReference reference; status_t result = B_OK; if (fFrame != NULL && fManager == NULL) { fManager = new(std::nothrow) ValueNodeManager(); if (fManager == NULL) result = B_NO_MEMORY; else result = fManager->SetStackFrame(fThread, fFrame); } if (result != B_OK) { fExpressionInfo->NotifyExpressionEvaluated(result, NULL); return result; } ValueNode* neededNode = NULL; result = fLanguage->EvaluateExpression(fExpressionInfo->Expression(), fManager, fTeam->GetTeamTypeInformation(), fResultValue, neededNode); if (neededNode != NULL) { result = ResolveNodeValue(neededNode); if (State() == JOB_STATE_WAITING) return B_OK; // if result != B_OK, fall through } fExpressionInfo->NotifyExpressionEvaluated(result, fResultValue); return B_OK; } status_t ExpressionEvaluationJob::ResolveNodeValue(ValueNode* node) { AutoLocker workerLocker(GetWorker()); SimpleJobKey jobKey(node, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE); status_t error = B_OK; if (GetWorker()->GetJob(jobKey) == NULL) { workerLocker.Unlock(); // schedule the job error = GetWorker()->ScheduleJob( new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface, fArchitecture, fThread->GetCpuState(), fTypeInformation, fManager->GetContainer(), node)); if (error != B_OK) { // scheduling failed -- set the value to invalid node->SetLocationAndValue(NULL, NULL, error); return error; } } // wait for the job to finish workerLocker.Unlock(); switch (WaitFor(jobKey)) { case JOB_DEPENDENCY_SUCCEEDED: case JOB_DEPENDENCY_NOT_FOUND: case JOB_DEPENDENCY_ACTIVE: error = B_OK; break; case JOB_DEPENDENCY_FAILED: case JOB_DEPENDENCY_ABORTED: default: error = B_ERROR; break; } return error; }