blob: 7441200b7779b12ae94b08491c6c2eda2b5fcacc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Created on: 17 janv. 2015
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "AvmCoverageDirectiveTraceBuilder.h"
#include <computer/primitive/AvmCommunicationFactory.h>
#include <fml/executable/AvmTransition.h>
#include <fml/expression/StatementTypeChecker.h>
#include <fml/runtime/ExecutionContext.h>
#include <fml/runtime/ExecutionData.h>
#include <fml/runtime/RuntimeForm.h>
#include <fml/runtime/RuntimeID.h>
#include <fam/coverage/AvmCoverageTransitionView.h>
#include <fml/runtime/Message.h>
namespace sep
{
/**
* Utils for TraceSequence
*/
void AvmTraceProperty::checkDecrementation(AvmTransition * aTransition)
{
if( (mTransitionCoverage != NULL) &&
(not mTransitionCoverage->testTransitionCoverage(aTransition)) )
{
--mUncoveredCount;
}
if( aTransition->hasStatementGuardFamily() )
{
--mGuardCount;
}
else if( aTransition->isUnconditionalStatementFamily() )
{
--mUnconditionalCount;
}
if( aTransition->isUnstableSource() )
{
--mUnstableCount;
}
}
void AvmTraceProperty::checkIncrementation(AvmTransition * aTransition)
{
if( (mTransitionCoverage != NULL) &&
(not mTransitionCoverage->testTransitionCoverage(aTransition)) )
{
++mUncoveredCount;
}
if( aTransition->hasStatementGuardFamily() )
{
++mGuardCount;
}
else if( aTransition->isUnconditionalStatementFamily() )
{
++mUnconditionalCount;
}
if( aTransition->isUnstableSource() )
{
++mUnstableCount;
}
}
void AvmTraceProperty::updadeSize()
{
mSize = 0;
mUncoveredCount = 0;
mGuardCount = 0;
mUnconditionalCount = 0;
mUnstableCount = 0;
BFList::const_iterator itPoint = points.begin();
BFList::const_iterator endPoint = points.end();
for( ; itPoint != endPoint ; ++itPoint )
{
++mSize;
checkIncrementation( (*itPoint).to_ptr< TracePoint >()->
object->as< AvmTransition >() );
}
}
bool AvmTraceProperty::compare( bool (* isComp)(avm_size_t, avm_size_t),
const AvmTraceProperty & aTraceElement )
{
return( isComp(xSize(), aTraceElement.xSize()) );
}
/**
* Serialization
*/
void AvmTraceProperty::toStream(OutStream & os, bool verbose) const
{
os << TAB << "trace#" << tid
<< "<xsize:" << xSize() << ", size:" << mSize
<< ", uncovered:" << mUncoveredCount
<< ", guard:" << mGuardCount
<< ", uncondional:" << mUnconditionalCount
<< ", unstable:" << mUnstableCount << ">";
if( mEC != NULL )
{
if( verbose )
{
os << EOL_TAB << AVM_STR_INDENT;
mEC->traceMinimum(os);
os << END_INDENT;
}
else
{
os << "( ctx:" << mEC->getIdNumber() << " )";
}
}
if( points.nonempty() )
{
os << " --> " << backTransition()->getNameID();
}
os << " { " << combinator->strOp() << EOL;
if( verbose )
{
os << INCR_INDENT;
BFList::const_iterator itPoint = points.begin();
BFList::const_iterator endPoint = points.end();
for( AvmTransition * aTransition = NULL ; itPoint != endPoint ; ++itPoint )
{
aTransition = (*itPoint).to_ptr< TracePoint >()->
object->as< AvmTransition >();
(*itPoint).toStream(os);
os << TAB2 << "\t\t\t--> " << aTransition->strTargetId();
os << " \t==> " << aTransition->strStatementFamily() << EOL;
if ( aTransition->hasInternalCommunicationCode() )
{
os << TAB2 << "\t\t\t";
BaseCompiledForm::toStreamStaticCom(os,
aTransition->getInternalCommunicationCode() );
}
}
os << DECR_INDENT;
}
else
{
os << INCR_INDENT << points << DECR_INDENT;
}
os << TAB << "}" << EOL_FLUSH;
}
/**
* CONSTRUCTOR
* Default
*/
AvmCoverageDirectiveTraceBuilder::AvmCoverageDirectiveTraceBuilder(
const ExecutionContext * anEC, TracePoint * tpTransition,
ENUM_HEURISTIC_CLASS anHeuristicClass,
avm_size_t pathCountLimit, avm_size_t pathSizeLimit)
: IHeuristicClass( anHeuristicClass ),
mEC( anEC ),
mED( anEC->getAPExecutionData() ),
mRID( tpTransition->RID ),
mTransition( tpTransition->object->to< AvmTransition >() ),
mTransitionPoint( tpTransition ),
mTraceElement( ),
mComputingPathCountLimit( pathCountLimit ),
mComputingPathSizeLimit( pathSizeLimit ),
mGoalAchievedFlag( false ),
//mTransitionPath( ),
//mExpectedInput( ),
mVirtualBuffer(mTransition, NULL, 0, TYPE_MULTI_LIFO_SPECIFIER, -1),
mEmitOutput( & mVirtualBuffer ),
mTableOfRuntimeStatus( *( mED->getRuntimeFormStateTable() ) ),
// computing variable for method << computePathToTransition >>
anyTransitionPaths( ),
prefixLoopTransitionPaths( ),
outgoingTransitions( ),
aTransitionPath( ),
itTrans( ),
endTrans( ),
tgtInstance( NULL ),
fwdMachine( NULL ),
tgtMachine( NULL )
{
//!! NOTHING
}
AvmCoverageDirectiveTraceBuilder::AvmCoverageDirectiveTraceBuilder(
const ExecutionContext * anEC, const RuntimeID & aRID,
AvmTransition * aTransition, ENUM_HEURISTIC_CLASS anHeuristicClass,
avm_size_t pathCountLimit, avm_size_t pathSizeLimit)
: IHeuristicClass( anHeuristicClass ),
mEC( anEC ),
mED( anEC->getAPExecutionData() ),
mRID( aRID ),
mTransition( aTransition ),
mTransitionPoint( NULL ),
mTraceElement( ),
mComputingPathCountLimit( pathCountLimit ),
mComputingPathSizeLimit( pathSizeLimit ),
mGoalAchievedFlag( false ),
//mTransitionPath( ),
//mExpectedInput( ),
mVirtualBuffer(mTransition, NULL, 0, TYPE_MULTI_LIFO_SPECIFIER, -1),
mEmitOutput( & mVirtualBuffer ),
mTableOfRuntimeStatus( *( mED->getRuntimeFormStateTable() ) ),
// computing variable for method << computePathToTransition >>
anyTransitionPaths( ),
prefixLoopTransitionPaths( ),
outgoingTransitions( ),
aTransitionPath( ),
itTrans( ),
endTrans( ),
tgtInstance( NULL ),
fwdMachine( NULL ),
tgtMachine( NULL )
{
//!! NOTHING
}
////////////////////////////////////////////////////////////////////////////////
// Configure
////////////////////////////////////////////////////////////////////////////////
bool AvmCoverageDirectiveTraceBuilder::configure(
AvmTraceProperty & aTraceElement, const ExecutionContext * anEC,
TracePoint * tpTransition, ENUM_HEURISTIC_CLASS anHeuristicClass,
avm_size_t pathCountLimit, avm_size_t pathSizeLimit)
{
mEC = anEC,
mED = anEC->getAPExecutionData();
mRID = tpTransition->RID;
mTransition = tpTransition->object->to< AvmTransition >();
mTransitionPoint = tpTransition;
mTraceElement.configure( aTraceElement );
mHeuristicClass = anHeuristicClass;
mComputingPathCountLimit = pathCountLimit;
mComputingPathSizeLimit = pathSizeLimit;
mTableOfRuntimeStatus.reset(
*( mED->getRuntimeFormStateTable() ), false);
return( true );
}
bool AvmCoverageDirectiveTraceBuilder::configure(
AvmTraceProperty & aTraceElement, const ExecutionContext * anEC,
const RuntimeID & aRID, AvmTransition * aTransition,
ENUM_HEURISTIC_CLASS anHeuristicClass,
avm_size_t pathCountLimit, avm_size_t pathSizeLimit)
{
mEC = anEC,
mED = anEC->getAPExecutionData();
mRID = aRID;
mTransition = aTransition;
mTransitionPoint = NULL;
mTraceElement.configure( aTraceElement );
mHeuristicClass = anHeuristicClass;
mComputingPathCountLimit = pathCountLimit;
mComputingPathSizeLimit = pathSizeLimit;
mTableOfRuntimeStatus.reset( *( mED->getRuntimeFormStateTable() ), false);
return( true );
}
////////////////////////////////////////////////////////////////////////////////
// API
////////////////////////////////////////////////////////////////////////////////
bool AvmCoverageDirectiveTraceBuilder::initialize()
{
mGoalAchievedFlag = false;
mEmitOutput.clear();
if( mRID.invalid() )
{
if( mED->mRID.getExecutable()->getTransition().contains(mTransition) )
{
mRID = mED->mRID;
}
if( mRID.invalid() )
{
if( mTransitionPoint != NULL )
{
mTransitionPoint->updateRID( (* mED) );
mRID = mTransitionPoint->RID;
}
else
{
mRID = mED->getRuntimeID( mTransition->getExecutable() );
}
}
}
return( mRID.valid() );
}
bool AvmCoverageDirectiveTraceBuilder::computePath()
{
if( initialize() )
{
AvmCommunicationFactory::collectBufferMessage(mED, mEmitOutput);
return( mGoalAchievedFlag = computePath(mRID, mTransition) );
}
return( false );
}
bool AvmCoverageDirectiveTraceBuilder::computePath(
AvmTraceProperty & aTraceElement)
{
if( initialize() )
{
AvmCommunicationFactory::collectBufferMessage(mED, mEmitOutput);
if( computePath(mRID, mTransition) )
{
aTraceElement.copyTrace( mTraceElement );
mGoalAchievedFlag = true;
return( true );
}
}
return( false );
}
bool AvmCoverageDirectiveTraceBuilder::computePath(
AvmTraceProperty & aTraceElement, ExecutionContext * anEC,
const RuntimeID & aRID, AvmTransition * aTransition,
ENUM_HEURISTIC_CLASS anHeuristicClass,
avm_size_t pathCountLimit, avm_size_t pathSizeLimit)
{
if( configure(aTraceElement, anEC, aRID, aTransition,
anHeuristicClass, pathCountLimit, pathSizeLimit) )
{
if( initialize() )
{
AvmCommunicationFactory::collectBufferMessage(mED, mEmitOutput);
if( computePath(mRID, mTransition) )
{
aTraceElement.copyTrace( mTraceElement );
mGoalAchievedFlag = true;
return( true );
}
}
}
return( false );
}
void AvmCoverageDirectiveTraceBuilder::report(OutStream & os)
{
os << DEFAULT_WRAP_DATA;
if( mEC != NULL )
{
os << "from "; mEC->traceMinimum(os);
}
os << "Trace to reach (size:" << mTraceElement.mSize << ") :> "
<< mTransition->strTransitionHeader() << std::endl;
mTraceElement.toStream(os);
// os << "Expected Input :> " << std::endl;
// BaseCompiledForm::toStreamStaticCom(os, mExpectedInput);
// os << TAB << "Emit Output :>"; mEmitOutput.toStream(AVM_OS_TRACE);
os << ( mGoalAchievedFlag ? "NEW" : "NO" ) << " OBJECTIVE !!!"
<< END_WRAP << std::endl;
}
bool AvmCoverageDirectiveTraceBuilder::computePath(
const RuntimeID & aRID, AvmTransition * aTransition)
{
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB << "computePath from :> ";
mEC->traceMinimum(AVM_OS_TRACE);
AVM_OS_TRACE << TAB2 << aRID.strUniqId() << " |==> ";
aTransition->toStreamHeader(AVM_OS_TRACE); AVM_OS_TRACE << std::endl;
if( aTransition->hasInternalCommunicationCode() )
{
AVM_OS_TRACE << TAB2 << "com |==> ";
BaseCompiledForm::toStreamStaticCom(AVM_OS_TRACE,
aTransition->getInternalCommunicationCode());
}
// AVM_OS_TRACE << TAB << "Expected Input :> " << std::endl;
// BaseCompiledForm::toStreamStaticCom(AVM_OS_TRACE, mExpectedInput);
AVM_OS_TRACE << TAB2 << "Emit Output :>"; mEmitOutput.toStream(AVM_OS_TRACE);
AVM_OS_TRACE << TAB << "end //computePath" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
if( mED->isIdleOrRunning(aRID) )
{
return( fireTransition(aRID, aTransition) );
}
else
{
return( computePathToTransition(aRID, aTransition) );
}
return( false );
}
bool AvmCoverageDirectiveTraceBuilder::fireTransition(
const RuntimeID & aRID, AvmTransition * aTransition)
{
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << std::endl
<< TAB << "fireTransition :> " << aRID.strUniqId()
<< " |==> " << aTransition->strTransitionHeader() << std::endl;
// AVM_OS_TRACE << TAB2 << "Expected Input :> " << std::endl;
// BaseCompiledForm::toStreamStaticCom(AVM_OS_TRACE, mExpectedInput);
AVM_OS_TRACE << TAB2 << "Emit Output :>"; mEmitOutput.toStream(AVM_OS_TRACE);
AVM_OS_TRACE << TAB << "end //fireTransition" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
mTableOfRuntimeStatus.stateSet(aRID.getOffset(), PROCESS_SUSPENDED_STATE);
if( aTransition->hasInputCom() )
{
ListOfInstanceOfPort anInputTrace( aTransition->getInputCom() );
if( mEmitOutput.uncontains( anInputTrace /*, aRID*/ ) )
{
// trouver des émetteurs pour les INPUT attendu au regard de ED< SC >
while( anInputTrace.nonempty() )
{
if( computePathToInput(aRID, anInputTrace.front()) )
{
anInputTrace.pop_front();
}
else
{
break;
}
}
if( anInputTrace.empty() )
{
traceTransition(aRID, aTransition);
return( true );
}
return( false );
}
else
{
traceTransition(aRID, aTransition);
}
}
else
{
traceTransition(aRID, aTransition);
}
return( true );
}
void AvmCoverageDirectiveTraceBuilder::traceTransition(
const RuntimeID & aRID, AvmTransition * aTransition)
{
mTraceElement.append(aRID, aTransition);
// Virtual Eval Of aTransition
if( aTransition->hasOutputCom() )
{
ListOfInstanceOfPort::const_iterator itOutput =
aTransition->getOutputCom().begin();
ListOfInstanceOfPort::const_iterator endOutput =
aTransition->getOutputCom().end();
for( ; itOutput != endOutput ; ++itOutput )
{
mEmitOutput.push( Message(aRID, INCR_BF(*itOutput)) );
}
}
}
bool AvmCoverageDirectiveTraceBuilder::computePathToTransition(
const RuntimeID & aRID, AvmTransition * aTransition)
{
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << std::endl
<< TAB << "computePathToTransition using :> " << aRID.strUniqId()
<< " |==> " << aTransition->strTransitionHeader() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
RuntimeID tmpRID = aRID.getPRID();
for( ; tmpRID.valid() ; tmpRID = tmpRID.getPRID() )
{
if( mED->isIdleOrRunning(tmpRID) )
{
break;
}
}
AVM_OS_ASSERT_FATAL_ERROR_EXIT( tmpRID.valid() )
<< "Unfound a Runnable Ancestor Statemachine !!!"
<< SEND_EXIT;
const RuntimeForm & tmpRF = mED->getRuntime(tmpRID);
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB2 << "Runnable Ancestor Statemachine :> "
<< tmpRID.str() << std::endl
<< TAB2 << "Runnable Ancestor State Scheduler :> {";
tmpRF.getOnSchedule()->toStreamRoutine( AVM_OS_TRACE )
<< TAB2 << "}" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
if( tmpRF.getOnSchedule()->isOpCode( AVM_OPCODE_RUN ) &&
tmpRF.getOnSchedule()->first().is< RuntimeID >() )
{
return( computePathFromRunnable(
tmpRF.getOnSchedule()->first().bfRID(), aTransition) );
}
return( false );
}
bool AvmCoverageDirectiveTraceBuilder::computeBasicPathFromRunnable(
const RuntimeID & aRID, AvmTransition * aTransition)
{
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << std::endl
<< TAB << "computeBasicPathFromRunnable using :> " << aRID.strUniqId()
<< " |==> " << aTransition->strTransitionHeader() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
if( not aRID.getExecutable()->
containsForwardReachableTransition(aTransition) )
{
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB2 << "Unreachable transition :> "
<< mTransition->strTransitionHeader() << std::endl
<< TAB2 << "from : " << aRID.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
return( false );
}
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB << "Looking for a path to :> " << aRID.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
ListOfAvmTransition oneTransitionPath;
if( computePathToTransition(aRID, aTransition, oneTransitionPath) )
{
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << INCR_INDENT;
AvmTransition::toStream(AVM_OS_TRACE, oneTransitionPath);
AVM_OS_TRACE << DECR_INDENT << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
// All found path
// ListOfListOfAvmTransition allTransitionPaths;
// computePathToTransition(aRID, aTransition, allTransitionPaths);
RuntimeID tmpRID = aRID;
do
{
aTransition = oneTransitionPath.front();
if( fireTransition(tmpRID, aTransition) )
{
oneTransitionPath.pop_front();
computeTargetMachine(tmpRID, aTransition->getCode());
}
else
{
break;
}
}
while( oneTransitionPath.nonempty() );
return( oneTransitionPath.empty() );
}
return( false );
}
bool AvmCoverageDirectiveTraceBuilder::computeSmartPathFromRunnable(
const RuntimeID & aRID, AvmTransition * aTransition)
{
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << std::endl
<< TAB << "computeSmartPathFromRunnable using :> " << aRID.strUniqId()
<< " |==> " << aTransition->strTransitionHeader() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
if( not aRID.getExecutable()->
containsForwardReachableTransition(aTransition) )
{
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB2 << "Unreachable transition :> "
<< mTransition->strTransitionHeader() << std::endl
<< TAB2 << "from : " << aRID.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
return( false );
}
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB << "Looking for a path to :> " << aRID.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
avm_size_t saveTraceElementSize = mTraceElement.mSize;
if( mComputingPathSizeLimit <= saveTraceElementSize )
{
return( false );
}
// All found path
ListOfListOfAvmTransition allTransitionPaths;
computePathToTransition(aRID, aTransition, allTransitionPaths);
ListOfAvmTransition oneTransitionPath;
RuntimeID tmpRID;
// if( computePathToTransition(aRID, aTransition, oneTransitionPath) )
while( allTransitionPaths.nonempty() )
{
oneTransitionPath.clear();
oneTransitionPath.splice( allTransitionPaths.front() );
allTransitionPaths.pop_front();
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB << "Found Path --> "
<< aTransition->getFullyQualifiedNameID() << std::endl << INCR_INDENT;
AvmTransition::toStream(AVM_OS_TRACE, oneTransitionPath);
AVM_OS_TRACE << DECR_INDENT << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
tmpRID = aRID;
do
{
aTransition = oneTransitionPath.front();
if( fireTransition(tmpRID, aTransition) )
{
oneTransitionPath.pop_front();
computeTargetMachine(tmpRID, aTransition->getCode());
}
else
{
break;
}
}
while( oneTransitionPath.nonempty() );
if( oneTransitionPath.empty() )
{
return( true );
}
else if( allTransitionPaths.empty() )
{
return( false );
}
// BACKTRACK
else
{
mTraceElement.resize( saveTraceElementSize );
}
}
return( false );
}
bool AvmCoverageDirectiveTraceBuilder::computePathToInput(
const RuntimeID & aRID, InstanceOfPort * anInputTrace)
{
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB << "computePathToInput :> " << std::endl;
AVM_OS_TRACE << TAB2 << "Expected Input :> " << anInputTrace->getFullyQualifiedNameID() << std::endl;
AVM_OS_TRACE << TAB2 << "Emit Output :>"; mEmitOutput.toStream(AVM_OS_TRACE);
AVM_OS_TRACE << TAB << "end //computePathToInput" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
ExecutableForm * tmpExecutable = NULL;
RuntimeID srcRID;
// Parcourir tous les états et repérer ceux contenant les bons output/outputTo
TableOfRuntimeT::const_iterator itRF = mED->getTableOfRuntime().begin();
TableOfRuntimeT::const_iterator endRF = mED->getTableOfRuntime().end();
for( ; itRF != endRF ; ++itRF )
{
srcRID = (*itRF)->getRID();
tmpExecutable = srcRID.getExecutable();
if( mTableOfRuntimeStatus.isSuspended(srcRID.getOffset()) )
{
//!! Exclude machine
}
else if( mED->isIdleOrRunning( srcRID ) &&
tmpExecutable->getForwardReachableTransition().nonempty() )
{
ListOfAvmTransition::const_iterator itTrans =
tmpExecutable->getForwardReachableTransition().begin();
ListOfAvmTransition::const_iterator endTrans =
tmpExecutable->getForwardReachableTransition().end();
for( ; itTrans != endTrans ; ++itTrans )
{
if( (*itTrans)->getOutputCom().contains(anInputTrace) )
{
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB << "found Output in :> " << srcRID.strUniqId() << " |==> "
<< (*itTrans)->strTransitionHeader() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
if( tmpExecutable != (*itTrans)->getExecutable() )
{
if( computePathFromRunnable(srcRID, (*itTrans)) )
{
return( true );
}
}
else if( fireTransition(srcRID, (*itTrans)) )
{
return( true );
}
}
}
}
}
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB << "Unfound Input :> " << anInputTrace->getFullyQualifiedNameID() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
return( false );
}
bool AvmCoverageDirectiveTraceBuilder::computePathToTransition(
const RuntimeID & aRID, AvmTransition * aTransition,
ListOfAvmTransition & oneTransitionPath)
{
anyTransitionPaths.clear();
outgoingTransitions.clear();
tgtInstance = NULL;
// Initialization step
fwdMachine = aRID.getExecutable();
fwdMachine->getOutgoingTransition( outgoingTransitions );
tgtMachine = fwdMachine;
itTrans = outgoingTransitions.begin();
endTrans = outgoingTransitions.end();
for( ; itTrans != endTrans ; ++itTrans )
{
if( (tgtInstance = (*itTrans)->getTransitionTarget()) != NULL )
{
tgtMachine = tgtInstance->getExecutable();
if( tgtMachine->containsForwardReachableTransition(aTransition) )
{
anyTransitionPaths.append( ListOfAvmTransition(*itTrans) );
}
}
}
aTransitionPath.clear();
// Iterative step
while( anyTransitionPaths.nonempty() )
{
aTransitionPath.clear();
aTransitionPath.splice( anyTransitionPaths.front() );
anyTransitionPaths.pop_front();
tgtInstance = aTransitionPath.back()->getTransitionTarget();
if( tgtInstance == NULL )
{
continue;
}
fwdMachine = tgtInstance->getExecutable();
if( fwdMachine->getTransition().contains(aTransition) )
{
oneTransitionPath.splice( aTransitionPath );
oneTransitionPath.push_back( aTransition );
return( true );
}
else
{
outgoingTransitions.clear();
fwdMachine->getOutgoingTransition( outgoingTransitions );
itTrans = outgoingTransitions.begin();
endTrans = outgoingTransitions.end();
for( ; itTrans != endTrans ; ++itTrans )
{
if( not aTransitionPath.contains( *itTrans ) )
{
if( (tgtInstance = (*itTrans)->getTransitionTarget()) != NULL )
{
tgtMachine = tgtInstance->getExecutable();
if( tgtMachine->containsForwardReachableTransition(aTransition) )
{
if( (aTransitionPath.size() < mComputingPathSizeLimit) &&
(anyTransitionPaths.size() < mComputingPathCountLimit) )
{
anyTransitionPaths.push_back( aTransitionPath );
anyTransitionPaths.back().push_back( *itTrans );
}
}
}
}
}
}
}
return( false );
}
bool AvmCoverageDirectiveTraceBuilder::computePathToTransition(
const RuntimeID & aRID, AvmTransition * aTransition,
ListOfListOfAvmTransition & allTransitionPaths)
{
anyTransitionPaths.clear();
prefixLoopTransitionPaths.clear();
aTransitionPath.clear();
outgoingTransitions.clear();
tgtInstance = NULL;
// Initialization step
fwdMachine = aRID.getExecutable();
fwdMachine->getOutgoingTransition( outgoingTransitions );
tgtMachine = fwdMachine;
itTrans = outgoingTransitions.begin();
endTrans = outgoingTransitions.end();
for( ; itTrans != endTrans ; ++itTrans )
{
if( (tgtInstance = (*itTrans)->getTransitionTarget()) != NULL )
{
tgtMachine = tgtInstance->getExecutable();
if( tgtMachine->containsForwardReachableTransition(aTransition) )
{
anyTransitionPaths.append( ListOfAvmTransition(*itTrans) );
}
}
}
// Iterative step
while( anyTransitionPaths.nonempty() )
{
// AVM_OS_TRACE << TAB << "TMP found paths :> " << std::endl;
// ListOfListOfAvmTransition::const_iterator itList = allTransitionPaths.begin();
// ListOfListOfAvmTransition::const_iterator endList = allTransitionPaths.end();
// for( avm_size_t number = 0 ; itList != endList ; ++itList , ++number )
// {
// AVM_OS_TRACE << TAB << "Path number :" << number << ">"
// << std::endl << INCR_INDENT;
// AvmTransition::toStream(AVM_OS_TRACE, *itList);
// AVM_OS_TRACE << std::endl << DECR_INDENT;
// }
//
// AVM_OS_TRACE << TAB << "TMP Computing paths :> " << std::endl;
// itList = anyTransitionPaths.begin();
// endList = anyTransitionPaths.end();
// for( avm_size_t number = 0 ; itList != endList ; ++itList , ++number )
// {
// AVM_OS_TRACE << TAB << "Path number :" << number << ">"
// << std::endl << INCR_INDENT;
// AvmTransition::toStream(AVM_OS_TRACE, *itList);
// AVM_OS_TRACE << DECR_INDENT;
// }
// AVM_OS_TRACE << std::endl;
aTransitionPath.clear();
aTransitionPath.splice( anyTransitionPaths.front() );
anyTransitionPaths.pop_front();
tgtInstance = aTransitionPath.back()->getTransitionTarget();
if( tgtInstance == NULL )
{
continue;
}
fwdMachine = tgtInstance->getExecutable();
if( fwdMachine->getTransition().contains(aTransition) )
{
allTransitionPaths.push_back( aTransitionPath );
allTransitionPaths.back().push_back( aTransition );
}
else
{
outgoingTransitions.clear();
fwdMachine->getOutgoingTransition( outgoingTransitions );
itTrans = outgoingTransitions.begin();
endTrans = outgoingTransitions.end();
for( ; itTrans != endTrans ; ++itTrans )
{
if( aTransitionPath.contains( *itTrans ) )
{
prefixLoopTransitionPaths.push_back( aTransitionPath );
prefixLoopTransitionPaths.back().push_back( *itTrans );
}
else
{
if( (tgtInstance = (*itTrans)->getTransitionTarget()) != NULL )
{
tgtMachine = tgtInstance->getExecutable();
if( tgtMachine->containsForwardReachableTransition(aTransition) )
{
if( (aTransitionPath.size() < mComputingPathSizeLimit) &&
(anyTransitionPaths.size() < mComputingPathCountLimit) )
{
anyTransitionPaths.push_back( aTransitionPath );
anyTransitionPaths.back().push_back( *itTrans );
}
}
}
}
}
}
}
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
AVM_OS_TRACE << TAB << "List of found paths :> " << std::endl;
ListOfListOfAvmTransition::const_iterator itList = allTransitionPaths.begin();
ListOfListOfAvmTransition::const_iterator endList = allTransitionPaths.end();
for( avm_size_t number = 0 ; itList != endList ; ++itList , ++number )
{
AVM_OS_TRACE << TAB << "Path number :" << number << " --> "
<< aTransition->getFullyQualifiedNameID() << std::endl << INCR_INDENT;
AvmTransition::toStream(AVM_OS_TRACE, *itList);
AVM_OS_TRACE << std::endl << DECR_INDENT;
}
// AVM_OS_TRACE << TAB << "List of found prefix-paths :> " << std::endl;
// itList = prefixLoopTransitionPaths.begin();
// endList = prefixLoopTransitionPaths.end();
// for( avm_size_t number = 0 ; itList != endList ; ++itList , ++number )
// {
// AVM_OS_TRACE << TAB << "Prefix number :" << number << "> "
// << std::endl << INCR_INDENT;
// AvmTransition::toStream(AVM_OS_TRACE, *itList);
// AVM_OS_TRACE << std::endl << DECR_INDENT;
// }
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , PROCESSOR , TRANSITION )
return( allTransitionPaths.nonempty() );
}
void AvmCoverageDirectiveTraceBuilder::computeTargetMachine(
RuntimeID & aRID, AvmCode * aCode)
{
switch( aCode->getAvmOpCode() )
{
case AVM_OPCODE_ENABLE_INVOKE:
case AVM_OPCODE_ENABLE_SET:
{
const BF & targetMachine = aCode->first();
if( targetMachine.is< InstanceOfMachine >() )
{
if( (targetMachine.to_ptr< InstanceOfMachine >() !=
aRID.getInstance()) && mED->getRuntime(aRID).hasChild() )
{
aRID = mED->getRuntimeFormChild(aRID,
targetMachine.to_ptr< InstanceOfMachine >() );
}
}
else if( targetMachine.is< RuntimeID >() )
{
aRID = targetMachine.bfRID();
}
break;
}
case AVM_OPCODE_DISABLE_SELF:
{
aRID = aRID.getPRID();
break;
}
case AVM_OPCODE_DISABLE_SELVES:
{
if( aCode->first().isInteger() )
{
for( avm_uinteger_t level = aCode->first().toInteger() ;
level > 0 ; --level )
{
aRID = aRID.getPRID();
}
}
else
{
aRID = aRID.getPRID();
}
break;
}
default:
{
if( StatementTypeChecker::isSchedule(aCode) )
{
AvmCode::const_iterator it = aCode->begin();
AvmCode::const_iterator endIt = aCode->end();
for( ; it != endIt ; ++it )
{
if( (*it).is< AvmCode >() )
{
computeTargetMachine(aRID, (*it).to_ptr< AvmCode >());
}
}
}
break;
}
}
}
} /* namespace sep */