* Copyright 2014-2016, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#include "Jobs.h"
#include <String.h>
#include <AutoLocker.h>
#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<Value> 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;
}
fExpressionInfo->NotifyExpressionEvaluated(result, fResultValue);
return B_OK;
}
status_t
ExpressionEvaluationJob::ResolveNodeValue(ValueNode* node)
{
AutoLocker<Worker> workerLocker(GetWorker());
SimpleJobKey jobKey(node, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
status_t error = B_OK;
if (GetWorker()->GetJob(jobKey) == NULL) {
workerLocker.Unlock();
error = GetWorker()->ScheduleJob(
new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
fArchitecture, fThread->GetCpuState(), fTypeInformation,
fManager->GetContainer(), node));
if (error != B_OK) {
node->SetLocationAndValue(NULL, NULL, error);
return error;
}
}
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;
}