Esempio n. 1
0
void TR::ValidateNodeRefCountWithinBlock::validate(TR::TreeTop *firstTreeTop,
                                                      TR::TreeTop *exitTreeTop)
   {
   _nodeChecklist.empty();
   for (TR::TreeTop *tt = firstTreeTop; tt != exitTreeTop->getNextTreeTop();
        tt = tt->getNextTreeTop())
      {
      TR::Node *node = tt->getNode();
      node->setLocalIndex(node->getReferenceCount());
      validateRefCountPass1(node);
      }

   /**
    * We start again from the start of the block, and check the localIndex to
    * make sure it is 0.
    *
    * NOTE: Walking the tree backwards causes huge stack usage in validateRefCountPass2.
    */
   _nodeChecklist.empty();
   for (TR::TreeTop *tt = firstTreeTop; tt != exitTreeTop->getNextTreeTop();
        tt = tt->getNextTreeTop())
      {
      validateRefCountPass2(tt->getNode());
      }
   }
Esempio n. 2
0
/**
 * In pass_1(validateRefCountPass1), the Local Index (which is set to the Ref
 * Count) for each child is decremented for each visit. The second pass is to
 * make sure that the Local Index is zero by the end of the block. A non-zero
 * Local Index would indicate that the Ref count was wrong at the start
 * of the Validation Process.
 */
void TR::ValidateNodeRefCountWithinBlock::validateRefCountPass1(TR::Node *node)
   {
   /* If this is the first time through this node, verify the children. */
   if (!_nodeChecklist.isSet(node->getGlobalIndex()))
      {
      _nodeChecklist.set(node->getGlobalIndex());
      for (int32_t i = node->getNumChildren() - 1; i >= 0; --i)
         {
         TR::Node *child = node->getChild(i);
         if (_nodeChecklist.isSet(child->getGlobalIndex()))
            {
            /* If the child has already been visited, decrement its verifyRefCount. */
            child->decLocalIndex();
            }
         else
            {
            /* If the child has not yet been visited, set its localIndex and visit it. */
            child->setLocalIndex(child->getReferenceCount() - 1);
            validateRefCountPass1(child);
            }
         }
      }
   }
Esempio n. 3
0
TR_LocalAnalysisInfo::TR_LocalAnalysisInfo(TR::Compilation *c, bool t)
   : _compilation(c), _trace(t), _trMemory(c->trMemory())
   {
   _numNodes = -1;

#if 0  // somehow stops PRE from happening
   // We are going to increment visit count for every tree so can reach max
   // for big methods quickly. Perhaps can improve containsCall() in the future.
   comp()->resetVisitCounts(0);
#endif
   if (comp()->getVisitCount() > HIGH_VISIT_COUNT)
      {
      _compilation->resetVisitCounts(1);
      dumpOptDetails(comp(), "\nResetting visit counts for this method before LocalAnalysisInfo\n");
      }

   TR::CFG *cfg = comp()->getFlowGraph();
   _numBlocks = cfg->getNextNodeNumber();
   TR_ASSERT(_numBlocks > 0, "Local analysis, node numbers not assigned");

   // Allocate information on the stack. It is the responsibility of the user
   // of this class to determine the life of the information by using jitStackMark
   // and jitStackRelease.
   //
   //_blocksInfo = (TR::Block **) trMemory()->allocateStackMemory(_numBlocks*sizeof(TR::Block *));
   //memset(_blocksInfo, 0, _numBlocks*sizeof(TR::Block *));

   TR::TreeTop *currentTree = comp()->getStartTree();

   // Only do this if not done before; typically this would be done in the
   // first call to this method through LocalTransparency and would NOT
   // need to be re-done by LocalAnticipatability.
   //
   if (_numNodes < 0)
      {
      _optimizer = comp()->getOptimizer();

      int32_t numBuckets;
      int32_t numNodes = comp()->getNodeCount();
      if (numNodes < 10)
         numBuckets = 1;
      else if (numNodes < 100)
         numBuckets = 7;
      else if (numNodes < 500)
         numBuckets = 31;
      else if (numNodes < 3000)
         numBuckets = 127;
      else if (numNodes < 6000)
         numBuckets = 511;
      else
         numBuckets = 1023;

      // Allocate hash table for matching expressions
      //
      HashTable hashTable(numBuckets, comp());
      _hashTable = &hashTable;

      // Null checks are handled differently as the criterion for
      // commoning a null check is different than that used for
      // other nodes; for a null check, the null check reference is
      // important (and not the actual indirect access itself)
      //
      _numNullChecks = 0;
      while (currentTree)
         {
         if (currentTree->getNode()->getOpCodeValue() == TR::NULLCHK)
         //////if (currentTree->getNode()->getOpCode().isNullCheck())
            _numNullChecks++;

         currentTree = currentTree->getNextTreeTop();
         }

      if (_numNullChecks == 0)
         _nullCheckNodesAsArray = NULL;
      else
         {
         _nullCheckNodesAsArray = (TR::Node**)trMemory()->allocateStackMemory(_numNullChecks*sizeof(TR::Node*));
         memset(_nullCheckNodesAsArray, 0, _numNullChecks*sizeof(TR::Node*));
         }

      currentTree = comp()->getStartTree();
      int32_t symRefCount = comp()->getSymRefCount();
      _checkSymbolReferences = new (trStackMemory()) TR_BitVector(symRefCount, trMemory(), stackAlloc);

      _numNodes = 1;
      _numNullChecks = 0;

      // This loop counts all the nodes that are going to take part in PRE.
      // This is a computation intensive loop as we check if the node that
      // is syntactically equivalent to a given node has been seen before
      // and if so we use the local index of the original node (that
      // is syntactically equivalent to the given node). Could be improved
      // in complexity with value numbering at some stage.
      //
      _visitCount = comp()->incVisitCount();
      while (currentTree)
         {
         TR::Node *firstNodeInTree = currentTree->getNode();
         TR::ILOpCode *opCode = &firstNodeInTree->getOpCode();

         if (((firstNodeInTree->getOpCodeValue() == TR::treetop) ||
              (comp()->useAnchors() && firstNodeInTree->getOpCode().isAnchor())) &&
             (firstNodeInTree->getFirstChild()->getOpCode().isStore()))
            {
            firstNodeInTree->setLocalIndex(-1);
            if (comp()->useAnchors() && firstNodeInTree->getOpCode().isAnchor())
               firstNodeInTree->getSecondChild()->setLocalIndex(-1);

            firstNodeInTree = firstNodeInTree->getFirstChild();
            opCode = &firstNodeInTree->getOpCode();
            }

         // This call finds nodes with opcodes that are supported by PRE
         // in this subtree; this accounts for all opcodes other than stores/checks
         // which are handled later on below
         //
         bool firstNodeInTreeHasCallsInStoreLhs = false;
         countSupportedNodes(firstNodeInTree, NULL, firstNodeInTreeHasCallsInStoreLhs);

         if ((opCode->isStore() && !firstNodeInTree->getSymbolReference()->getSymbol()->isAutoOrParm()) ||
             opCode->isCheck())
            {
            int32_t oldExpressionOnRhs = hasOldExpressionOnRhs(firstNodeInTree);

            //
            // Return value 0 denotes that the node contains some sub-expression
            // that cannot participate in PRE; e.g. a call or a new
            //
            // Return value -1 denotes that the node can participate in PRE
            // but did not match with any existing expression seen so far
            //
            // Any other return value (should be positive always) denotes that
            // the node can participate in PRE and has been matched with a seen
            // expression having local index == return value
            //
            if (oldExpressionOnRhs == -1)
               {
               if (trace())
                  {
                  traceMsg(comp(), "\nExpression #%d is : \n", _numNodes);
                  comp()->getDebug()->print(comp()->getOutFile(), firstNodeInTree, 6, true);
                  }

               firstNodeInTree->setLocalIndex(_numNodes++);
               }
            else
               firstNodeInTree->setLocalIndex(oldExpressionOnRhs);

            if (opCode->isCheck() &&
                (firstNodeInTree->getFirstChild()->getOpCode().isStore() &&
                 !firstNodeInTree->getFirstChild()->getSymbolReference()->getSymbol()->isAutoOrParm()))
               {
               int oldExpressionOnRhs = hasOldExpressionOnRhs(firstNodeInTree->getFirstChild());

               if (oldExpressionOnRhs == -1)
                  {
                  if (trace())
                     {
                     traceMsg(comp(), "\nExpression #%d is : \n", _numNodes);
                     comp()->getDebug()->print(comp()->getOutFile(), firstNodeInTree->getFirstChild(), 6, true);
                     }

                  firstNodeInTree->getFirstChild()->setLocalIndex(_numNodes++);
                  }
               else
                  firstNodeInTree->getFirstChild()->setLocalIndex(oldExpressionOnRhs);
               }
            }
         else
            firstNodeInTree->setLocalIndex(-1);

         currentTree = currentTree->getNextTreeTop();
         }
      }

   _supportedNodesAsArray = (TR::Node**)trMemory()->allocateStackMemory(_numNodes*sizeof(TR::Node*));
   memset(_supportedNodesAsArray, 0, _numNodes*sizeof(TR::Node*));
   _checkExpressions = new (trStackMemory()) TR_BitVector(_numNodes, trMemory(), stackAlloc);

   //_checkExpressions.init(_numNodes, trMemory(), stackAlloc);

   // This loop goes through the trees and collects the nodes
   // that would take part in PRE. Each node has its local index set to
   // the bit position that it occupies in the bit vector analyses.
   //
   currentTree = comp()->getStartTree();
   _visitCount = comp()->incVisitCount();
   while (currentTree)
      {
      TR::Node *firstNodeInTree = currentTree->getNode();
      TR::ILOpCode *opCode = &firstNodeInTree->getOpCode();

      if (((firstNodeInTree->getOpCodeValue() == TR::treetop) ||
           (comp()->useAnchors() && firstNodeInTree->getOpCode().isAnchor())) &&
          (firstNodeInTree->getFirstChild()->getOpCode().isStore()))
         {
         firstNodeInTree = firstNodeInTree->getFirstChild();
         opCode = &firstNodeInTree->getOpCode();
         }

      collectSupportedNodes(firstNodeInTree, NULL);

      if ((opCode->isStore() && !firstNodeInTree->getSymbolReference()->getSymbol()->isAutoOrParm()) ||
          opCode->isCheck())
         {
        if (opCode->isCheck())
            {
            _checkSymbolReferences->set(firstNodeInTree->getSymbolReference()->getReferenceNumber());
            _checkExpressions->set(firstNodeInTree->getLocalIndex());
            }

         if (!_supportedNodesAsArray[firstNodeInTree->getLocalIndex()])
            _supportedNodesAsArray[firstNodeInTree->getLocalIndex()] = firstNodeInTree;

         if (opCode->isCheck() &&
             firstNodeInTree->getFirstChild()->getOpCode().isStore() &&
             !firstNodeInTree->getFirstChild()->getSymbolReference()->getSymbol()->isAutoOrParm() &&
             !_supportedNodesAsArray[firstNodeInTree->getFirstChild()->getLocalIndex()])
            _supportedNodesAsArray[firstNodeInTree->getFirstChild()->getLocalIndex()] = firstNodeInTree->getFirstChild();
         }

      currentTree = currentTree->getNextTreeTop();
      }

   //initialize(toBlock(cfg->getStart()));
   }