예제 #1
0
static bool isSafeToReplaceNode(TR::Node *currentNode, TR::TreeTop *curTreeTop, bool *seenConditionalBranch,
      vcount_t visitCount, TR::Compilation *comp, List<OMR::TreeInfo> *targetTrees, bool &cannotBeEliminated,
      LongestPathMap &longestPaths)
   {
   LexicalTimer tx("safeToReplace", comp->phaseTimer());

   TR::SparseBitVector symbolReferencesInNode(comp->allocator());

   // Collect all symbols that could be killed between here and the next reference
   //
   comp->incVisitCount();
   //////vcount_t visitCount = comp->getVisitCount();
   int32_t numDeadSubNodes = 0;
   bool cantMoveUnderBranch = false;
   bool seenInternalPointer = false;
   bool seenArraylet = false;
   int32_t curMaxHeight = getLongestPathOfDAG(currentNode, longestPaths);
   collectSymbolReferencesInNode(currentNode, symbolReferencesInNode, &numDeadSubNodes, visitCount, comp,
         &seenInternalPointer, &seenArraylet, &cantMoveUnderBranch);

   bool registersScarce = comp->cg()->areAssignableGPRsScarce();
#ifdef J9_PROJECT_SPECIFIC
   bool isBCD = currentNode->getType().isBCD();
#endif

   if (numDeadSubNodes > 1 &&
#ifdef J9_PROJECT_SPECIFIC
       !isBCD &&
#endif
       registersScarce)
      {
      return false;
      }

   OMR::TreeInfo *curTreeInfo = findOrCreateTreeInfo(curTreeTop, targetTrees, comp);
   int32_t curHeight = curTreeInfo->getHeight()+curMaxHeight;
   if (curHeight > MAX_ALLOWED_HEIGHT)
      {
      cannotBeEliminated = true;
      return false;
      }

   // TEMPORARY
   // Don't allow removal of a node containing an unresolved reference if
   // the gcOnResolve option is set
   //
   bool isUnresolvedReference = currentNode->hasUnresolvedSymbolReference();
   if (isUnresolvedReference)
      return false;

   bool mayBeVolatileReference = currentNode->mightHaveVolatileSymbolReference();
   //if (mayBeVolatileReference)
   //   return false;

   // Now scan forwards through the trees looking for the next use and checking
   // to see if any symbols in the subtree are getting modified; if so it is not
   // safe to replace the node at its next use.
   //

   comp->incVisitCount();
   for (TR::TreeTop *treeTop = curTreeTop->getNextTreeTop(); treeTop; treeTop = treeTop->getNextTreeTop())

      {
      TR::Node *node = treeTop->getNode();
      if(node->getOpCodeValue() == TR::treetop)
          node = node->getFirstChild();

      if (node->getOpCodeValue() == TR::BBStart &&
          !node->getBlock()->isExtensionOfPreviousBlock())
         return true;

      if (cantMoveUnderBranch && (node->getOpCode().isBranch()
         || node->getOpCode().isJumpWithMultipleTargets()))
         return false;

      if (node->canGCandReturn() &&
          seenInternalPointer)
         return false;

      int32_t tempHeight = 0;
      int32_t maxHeight = 0;
      bool canMoveIfVolatile = true;
      if (containsNode(node, currentNode, visitCount, comp, &tempHeight, &maxHeight, canMoveIfVolatile))
         {
         // TEMPORARY
         // Disable moving an unresolved reference down to the middle of a
         // JNI call, until the resolve helper is fixed properly
         //
         if (isUnresolvedReference && node->getFirstChild()->getOpCode().isCall() &&
             node->getFirstChild()->getSymbol()->castToMethodSymbol()->isJNI())
            return false;

         if (curTreeInfo)
            {
            OMR::TreeInfo *treeInfo = findOrCreateTreeInfo(treeTop, targetTrees, comp);
            int32_t height = treeInfo->getHeight();
            int32_t maxHeightUsed = maxHeight;
            if (maxHeightUsed < curMaxHeight)
               maxHeightUsed = curMaxHeight;

            if (height < curTreeInfo->getHeight())
               height = curTreeInfo->getHeight();
            height++;
            if ((height+maxHeightUsed) > MAX_ALLOWED_HEIGHT)
               {
               cannotBeEliminated = true;
               return false;
               }
            treeInfo->setHeight(height);
            }

         return true;
         }

      if (mayBeVolatileReference && !canMoveIfVolatile)
         return false;

      if ((node->getOpCode().isBranch() &&
           (node->getOpCodeValue() != TR::Goto)) ||
           (node->getOpCode().isJumpWithMultipleTargets() && node->getOpCode().hasBranchChildren()))
        *seenConditionalBranch = true;

      if (node->getOpCodeValue() == TR::treetop ||
          node->getOpCode().isNullCheck() ||
          node->getOpCode().isResolveCheck() ||
          node->getOpCodeValue() == TR::ArrayStoreCHK ||
          node->getOpCode().isSpineCheck())
         {
         node = node->getFirstChild();
         }

      if (node->getOpCode().isStore())
         {
         // For a store, just the single symbol reference is killed.
         // Resolution of the store symbol is handled by TR::ResolveCHK
         //
         if (symbolReferencesInNode.ValueAt(node->getSymbolReference()->getReferenceNumber()))
            return false;
         }

      // Node Aliasing Changes
      // Check if the definition modifies any symbol in the subtree
      //
      if (node->mayKill(true).containsAny(symbolReferencesInNode, comp))
        return false;
      }
   return true;
   }