# An Automatic Transformer from Sequential to Parallel Java Code
## 4 Method Call Analysis
### Method Context Analysis  
The context of the method call has crucial significance when evaluating whether there is a gain when running the method call in parallel. The context is the statement where the method call is retrieved; it could be the method call itself, or a more complex statement containing it. For the former case, further analysis of the same statement is not needed since the method call is the only instruction in the statement; hence, we can check further conditions to determine whether parallel execution is possible and desired. Conversely, for the latter cases, i.e., the method call is found within another statement. There could be some cases where parallel execution is unsuitable; hence, we avoid further analysis aimed at parallelization. Algorithm 2 shows the instructions executed when having to analyze the context of a method call. The context is extracted by obtaining the ancestor of the method call. The ancestor is the parent node on the AST of the node containing the analyzed method call. If the method call is part of a more complex statement, the ancestor will be the instruction containing it; otherwise, the ancestor will be the statement containing the block of instructions with the method call, e.g., the body of the method declaration, or the body of a for statement. Once the ancestor is retrieved, it is compared to a set of feasible contexts, which was defined beforehand. The function returns true if the context of the method call taken as input satisfies the feasible contexts, and false otherwise. ```
functionContextAnalysis(mCall) \(context\gets getAncestor(mCall)\) \(suitableContexts\gets defineSuitableContext()\) return\(suitableContexts.contains(context)\) endfunction
```  
Listing 1 shows some examples of method calls that are unsuitable for parallel execution, i.e., method calls that are a part of the condition expression in _if_, _while_, and _do_ constructs (examples 1 and 2 in Listing 1), and statements, such as _switch_, _for_, _throw_, _assert_, and _synchronized_ (example 3). Parallel execution is unsuitable in such cases because the returned value of the method call is immediately used to determine whether to execute the following statements. Similarly, all the method calls that are in a return statement cannot give any advantage when running in parallel as the need for the return value would just make the calling thread wait for the result. ```
//MethodcallcheckForFileAndPatternCollisions()inaconditionstatement
1.if(checkForFileAndPatternCollisions()){addError(\"FilepropertycollideswithfileNamePattern.Aborting.\");addError(NORE_INFO_REFIX+COLLISTION_URL);return;} //MethodcallisRunning()inabuisherstatement
2.while(isRunning()t=state){runningCondition.await(delay,TimeUnit.MILLISECONDS); } //MethodcallgetCopyOfStatusListenerList()asiterableinaforeschstatement
3.for(StatusListeners1:sm.getCopyOfStatusListenerList()){ if(!sl.isResetResistant()){ sm.remove(s1); } }
```  
Listing 2 shows six examples of method calls that can be transformed to run in parallel. Line 1 shows a method call used as the value for an assignment expression; line 2 shows a method call used as the value for an assignment in a variable declaration expression; line 3 shows a method call chained with other calls; line 4 shows a method call passed as the argument for other method calls; line 5 shows a method call without any other instruction; and line 6 shows a method call passed as the argument for an object creation expression. In such cases, the result of the method call is not used to determine whether to execute the following statements. Indeed, our aim is to evaluate whether the whole statement (which could consist of several expressions) could run in a thread parallel to the thread that runs the following statements. ```
// Assign expression using a method call
1. le - makeloggingEvent(aMessage, null);) // Variable declaration expression using a method call
2.