TR::Node *TR_OutlinedInstructions::createOutlinedCallNode(TR::Node *callNode, TR::ILOpCodes callOp) { int32_t i; TR::Node *child; //We pass true for getSymbolReference because TR::Node *newCallNode = TR::Node::createWithSymRef(callNode, callOp, callNode->getNumChildren(), callNode->getSymbolReference()); newCallNode->setReferenceCount(1); for (i=0; i<callNode->getNumChildren(); i++) { child = callNode->getChild(i); if (child->getRegister() != NULL) { // Child has already been evaluated outside this tree. // newCallNode->setAndIncChild(i, child); } else if (child->getOpCode().isLoadConst()) { // Copy unevaluated constant nodes. // child = TR::Node::copy(child); child->setReferenceCount(1); newCallNode->setChild(i, child); } else { if ((child->getOpCodeValue() == TR::loadaddr) && /*(callNode->getOpCodeValue() == TR::instanceof || callNode->getOpCodeValue() == TR::checkcast || callNode->getOpCodeValue() == TR::checkcastAndNULLCHK || callNode->getOpCodeValue() == TR::New || callNode->getOpCodeValue() == TR::anewarray) &&*/ (child->getSymbolReference()->getSymbol()) && (child->getSymbolReference()->getSymbol()->getStaticSymbol())) { child = TR::Node::copy(child); child->setReferenceCount(1); newCallNode->setChild(i, child); } else { // Be very conservative at this point, even though it is possible to make it less so. For example, this will catch // the case of an unevaluated argument not persisting outside of the outlined region even though one of its subtrees will. // (void)_cg->evaluate(child); // Do not decrement the reference count here. It will be decremented when the call node is evaluated // again in the helper instruction stream. // newCallNode->setAndIncChild(i, child); } } } if(callNode->isPreparedForDirectJNI()) { newCallNode->setPreparedForDirectJNI(); } return newCallNode; }