Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify call graphs #40

Merged
merged 3 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Re-enable Call-by-Signature resolution
  • Loading branch information
errt committed Sep 13, 2021
commit 99bde899b6dda77cf735ba3fd167776f8bbf6eb0
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import scala.collection.mutable

import org.opalj.fpcf.EOptionP
import org.opalj.br.Method
import org.opalj.br.ReferenceType
import org.opalj.tac.fpcf.properties.TACAI

/**
Expand All @@ -22,14 +23,20 @@ class CGState[ContextType <: Context](
) extends BaseAnalysisState with TypeProviderState with TACAIBasedAnalysisState[ContextType] {

// maps a definition site to the receiver var
private[this] val _virtualCallSites: mutable.Map[CallSite, V] = mutable.Map.empty
private[this] val _virtualCallSites: mutable.Map[CallSite, (V, Set[ReferenceType])] =
mutable.Map.empty

def receiverForCallSite(callSite: CallSite): V = {
def callSiteData(callSite: CallSite): (V, Set[ReferenceType]) = {
_virtualCallSites(callSite)
}

def addCallSite(callSite: CallSite, receiver: V): Unit = {
_virtualCallSites.put(callSite, receiver)
def addCallSite(callSite: CallSite, receiver: V, cbsTargets: Set[ReferenceType]): Unit = {
if (_virtualCallSites.contains(callSite))
_virtualCallSites.put(
callSite, (receiver, _virtualCallSites(callSite)._2 ++ cbsTargets)
)
else
_virtualCallSites.put(callSite, (receiver, cbsTargets))
}

def hasNonFinalCallSite: Boolean = _virtualCallSites.nonEmpty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import org.opalj.br.analyses.SomeProject
import org.opalj.br.analyses.cg.InitialEntryPointsKey
import org.opalj.br.analyses.DeclaredMethodsKey
import org.opalj.br.analyses.ProjectInformationKeys
import org.opalj.br.analyses.cg.CallBySignatureKey
import org.opalj.br.fpcf.properties.cg.Callees
import org.opalj.br.fpcf.properties.cg.Callers
import org.opalj.br.fpcf.properties.cg.OnlyCallersWithUnknownContext
Expand All @@ -59,9 +60,9 @@ class CallGraphAnalysis private[cg] (
type LocalTypeInformation

private[this] val isMethodOverridable: Method ⇒ Answer = project.get(IsOverridableMethodKey)
/*private[this] lazy val getCBSTargets = project.get(CallBySignatureKey)
private[this] lazy val getCBSTargets = project.get(CallBySignatureKey)
private[this] val resovleCallBySignature =
project.config.getBoolean("org.opalj.br.analyses.cg.callBySignatureResolution")*/
project.config.getBoolean("org.opalj.br.analyses.cg.callBySignatureResolution")

def c(state: CGState[ContextType])(eps: SomeEPS): ProperPropertyComputationResult = {
eps match {
Expand All @@ -81,8 +82,10 @@ class CallGraphAnalysis private[cg] (
val calls = new DirectCalls()

for (cs ← relevantCallSites) {
val receiver = state.receiverForCallSite(cs)
typeProvider.continuation(receiver, eps.asInstanceOf[EPS[Entity, PropertyType]]) {
val (receiver, cbsTargets) = state.callSiteData(cs)
typeProvider.continuation(
receiver, eps.asInstanceOf[EPS[Entity, PropertyType]], cbsTargets
) {
newType ⇒
val CallSite(pc, name, descriptor, declaredType) = cs
val tgtR = project.instanceCall(
Expand Down Expand Up @@ -133,24 +136,20 @@ class CallGraphAnalysis private[cg] (
val callerType = callContext.method.declaringClassType
val callSite = CallSite(pc, call.name, call.descriptor, call.declaringClass)

/*val cbsTargets =
val cbsTargets: Set[ReferenceType] =
if (!isPrecise && resovleCallBySignature && call.isInterface &&
call.declaringClass.isObjectType) {
val cf = project.classFile(call.declaringClass.asObjectType)
cf.flatMap { _.findMethod(call.name, call.descriptor) }.map {
getCBSTargets(_)
}.getOrElse(RefArray.empty)
} else RefArray.empty

val targetTypes = potentialTargets ++ cbsTargets.foreachIterator

var unresolvedTypes = IntTrieSet.empty*/
getCBSTargets(_).toSet[ReferenceType]
}.getOrElse(Set.empty)
} else Set.empty

val actualTypes = typeProvider.typesProperty(
call.receiver.asVar, state.callContext, callSite, state.tac.stmts
)

typeProvider.foreachType(call.receiver.asVar, actualTypes) { possibleTgtType ⇒
typeProvider.foreachType(call.receiver.asVar, actualTypes, cbsTargets) { possibleTgtType ⇒
val tgtR = project.instanceCall(
callerType, possibleTgtType, call.name, call.descriptor
)
Expand All @@ -168,7 +167,7 @@ class CallGraphAnalysis private[cg] (
)
}

state.addCallSite(callSite, call.receiver.asVar)
state.addCallSite(callSite, call.receiver.asVar, cbsTargets)

// Deal with the fact that there may be unknown subtypes of the receiver type that might
// override the method
Expand Down
Loading