Class MethodModel

java.lang.Object
com.aparapi.internal.model.MethodModel

public class MethodModel extends Object
  • Field Details

    • logger

      private static Logger logger
    • expressionList

      private ExpressionList expressionList
    • method

    • usesDoubles

      private boolean usesDoubles
      True is an indication to use the fp64 pragma
    • usesByteWrites

      private boolean usesByteWrites
      True is an indication to use the byte addressable store pragma
    • methodIsGetter

      private boolean methodIsGetter
    • methodIsSetter

      private boolean methodIsSetter
    • methodIsPrivateMemoryGetter

      private boolean methodIsPrivateMemoryGetter
    • usesPutfield

      private boolean usesPutfield
    • accessorVariableFieldEntry

      private ClassModel.ConstantPool.FieldEntry accessorVariableFieldEntry
    • noCL

      private boolean noCL
    • calledMethods

      private final Set<MethodModel> calledMethods
    • pcTail

      private Instruction pcTail
      After we have folded the top level instructions this root list will contain a list of all of the 'root' instructions (stores/loops/conditionals) We are going to build a linked list. Here we track the head and tail
    • pcHead

      private Instruction pcHead
    • transformers

      InstructionTransformer[] transformers
    • entrypoint

      Entrypoint entrypoint
  • Constructor Details

  • Method Details

    • isGetter

      public boolean isGetter()
    • isSetter

      public boolean isSetter()
    • methodUsesPutfield

      public boolean methodUsesPutfield()
    • isNoCL

      public boolean isNoCL()
    • isPrivateMemoryGetter

      public boolean isPrivateMemoryGetter()
    • getMethod

      public ClassModel.ClassModelMethod getMethod()
    • getAccessorVariableFieldEntry

      public ClassModel.ConstantPool.FieldEntry getAccessorVariableFieldEntry()
    • getCalledMethods

      public Set<MethodModel> getCalledMethods()
    • checkForRecursion

      public void checkForRecursion(Set<MethodModel> transitiveCalledMethods) throws AparapiException
      Throws:
      AparapiException
    • setRequiredPragmas

      public void setRequiredPragmas(Instruction instruction)
      Look at each instruction for use of long/double or byte writes which require pragmas to be used in the OpenCL source
    • requiresDoublePragma

      public boolean requiresDoublePragma()
    • requiresByteAddressableStorePragma

      public boolean requiresByteAddressableStorePragma()
    • createListOfInstructions

      public Map<Integer,Instruction> createListOfInstructions() throws ClassParseException
      Create a linked list of instructions (from pcHead to pcTail). Returns a map of int (pc) to Instruction which to allow us to quickly get from a bytecode offset to the appropriate instruction. Note that not all int values from 0 to code.length values will map to a valid instruction, if pcMap.get(n) == null then this implies that 'n' is not the start of an instruction So either pcMap.get(i)== null or pcMap.get(i).getThisPC()==i
      Returns:
      Mapinvalid input: '<'Integer, Instruction> the returned pc to Instruction map
      Throws:
      ClassParseException
    • buildBranchGraphs

      public void buildBranchGraphs(Map<Integer,Instruction> pcMap)
      Here we connect the branch nodes to the instruction that they branch to.

      Each branch node contains a 'target' field indended to reference the node that the branch targets. Each instruction also contain four seperate lists of branch nodes that reference it. These lists hold forwardConditional, forwardUnconditional, reverseConditional and revereseUnconditional branches that reference it.

      So assuming that we had a branch node at pc offset 100 which represented 'goto 200'.

      Following this call the branch node at pc offset 100 will have a 'target' field which actually references the instruction at pc offset 200, and the instruction at pc offset 200 will have the branch node (at 100) added to it's forwardUnconditional list.

      See Also:
    • deoptimizeReverseBranches

      public void deoptimizeReverseBranches()
      Javac optimizes some branches to avoid goto->goto, branch->goto etc. This method specifically deals with reverse branches which are the result of such optimisations.
       
       
    • txFormDups

      public void txFormDups(ExpressionList _expressionList, Instruction _instruction) throws ClassParseException
      DUP family of instructions break our stack unwind model (whereby we treat instructions like the oeprands they create/consume).

      Here we replace DUP style instructions with a 'mock' instruction which 'clones' the effect of the instruction. This would be invalid to execute but is useful to replace the DUP with a 'pattern' which it simulates. This allows us to later apply transforms to represent the original code.

      An example might be the bytecode for the following sequence.

          results[10]++; 
               return
       
      Which results in the following bytecode
            0:   aload_0       // reference through 'this' to get 
            1:   getfield      // field 'results' which is an array of int
            4:   bipush  10    // push the array index
            6:   dup2          // dreaded dup2 we'll come back here
            7:   iaload        // ignore for the moment.
            8:   iconst_1
            9:   iadd
            10:  iastore
            11:  return
       
      First we need to know what the stack will look like before the dup2 is encountered. Using our folding technique we represent the first two instructions inside ()
      
                 getfield (aload_0     // result in the array field reference on stack
                 bipush  10            // the array index
                 dup2                  // dreaded dup2 we'll come back here
       
      The dup2 essentially copies the top two elements on the stack. So we emulate this by replacing the dup2 with clones of the instructions which would reinstate the same stack state.

      So after the dup2 transform we end up with:-

      
                getfield (aload_0)     // result in the array field reference on stack
                bipush  10             // the array index
                {getfield (aload_0)}   // result in the array field reference on stack
                {bipush 10}            // the array index
       
      So carrying on lets look at the iaload which consumes two operands (the index and the array field reference) and creates one (the result of an array access)
      
                getfield (aload_0)     // result in the array field reference on stack
                bipush  10             // the array index
                {getfield (aload_0)}   // result in the array field reference on stack
                {bipush  10}           // the array index
                iaload 
       
      So we now have
      
                getfield (aload_0)                        // result in the array field reference on stack
                bipush  10                                // the array index
                iaload ({getfield(aload_0), {bipush 10})  // results in the array element on the stack
                iconst
                iadd
       
      And if you are following along the iadd will fold the previous two stack entries essentially pushing the result of results[10]+1 on the stack.
      
                getfield (aload_0)                                        // result in the array field reference on stack
                bipush  10                                                // the array index
                iadd (iaload ({getfield(aload_0), {bipush 10}, iconst_1)  // push of results[10]+1 
       
      Then the final istore instruction which consumes 3 stack operands (the field array reference, the index and the value to assign).

      Which results in

       
                istore (getfield (aload_0), bipush 10,  iadd (iaload ({getfield(aload_0), {bipush 10}, iconst_1)) // results[10] = results[10+1]
       
      Where results[10] = results[10+1] is the long-hand form of the results[10]++ and will be transformed by one of the 'inc' transforms to the more familiar form a little later.
      Parameters:
      _expressionList -
      _instruction -
      Throws:
      ClassParseException
    • foldExpressions

      void foldExpressions() throws ClassParseException
      Try to fold the instructions into higher level structures. At the end we have a folded instruction tree with 'roots' containing the top level branches (stores mostly)
      Throws:
      ClassParseException
    • applyTransformations

      void applyTransformations(ExpressionList _expressionList, Instruction _instruction, Instruction _operandStart) throws ClassParseException
      Throws:
      ClassParseException
    • checkForGetter

      void checkForGetter(Map<Integer,Instruction> pcMap) throws ClassParseException
      Determine if this method is a getter and record the accessed field if so
      Throws:
      ClassParseException
    • setAccessorVariableFieldEntry

      private void setAccessorVariableFieldEntry(ClassModel.ConstantPool.FieldEntry field)
    • checkForSetter

      void checkForSetter(Map<Integer,Instruction> pcMap) throws ClassParseException
      Determine if this method is a setter and record the accessed field if so
      Throws:
      ClassParseException
    • init

      private void init(ClassModel.ClassModelMethod _method) throws AparapiException
      Throws:
      AparapiException
    • getLocalVariableTableEntry

    • getConstantPool

      public ClassModel.ConstantPool getConstantPool()
    • getLocalVariable

      public ClassModel.LocalVariableInfo getLocalVariable(int _pc, int _index)
    • getSimpleName

      public String getSimpleName()
    • getName

      public String getName()
    • getReturnType

      public String getReturnType()
    • getMethodCalls

      public List<InstructionSet.MethodCall> getMethodCalls()
    • getPCHead

      public Instruction getPCHead()
    • getExprHead

      public Instruction getExprHead()
    • toString

      public String toString()
      Overrides:
      toString in class Object