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; }