// resolved casts that are not to abstract, interface, or array need a super test bool OMR::TreeEvaluator::instanceOfOrCheckCastNeedSuperTest(TR::Node * node, TR::CodeGenerator *cg) { TR::Node *castClassNode = node->getSecondChild(); TR::MethodSymbol *helperSym = node->getSymbol()->castToMethodSymbol(); TR::SymbolReference *castClassSymRef = castClassNode->getSymbolReference(); if (!TR::TreeEvaluator::isStaticClassSymRef(castClassSymRef)) { // We could theoretically do a super test on something with no sym, but it would require significant // changes to platform code. The benefit is little at this point (shows up from reference arraycopy reductions) if (cg->supportsInliningOfIsInstance() && node->getOpCodeValue() == TR::instanceof && node->getSecondChild()->getOpCodeValue() != TR::loadaddr) return true; else return false; } TR::StaticSymbol *castClassSym = castClassSymRef->getSymbol()->getStaticSymbol(); if (castClassSymRef->isUnresolved()) { return false; } else { TR_OpaqueClassBlock * clazz; // If the class is a regular class (i.e., not an interface nor an array) and // not known to be a final class, an inline superclass test can be generated. // If the helper does not preserve all the registers there will not be // enough registers to do the superclass test inline. // Also, don't generate the superclass test if optimizing for space. // if (castClassSym && (clazz = (TR_OpaqueClassBlock *) castClassSym->getStaticAddress()) && !TR::Compiler->cls.isClassArray(cg->comp(), clazz) && !TR::Compiler->cls.isInterfaceClass(cg->comp(), clazz) && !TR::Compiler->cls.isClassFinal(cg->comp(), clazz) && helperSym->preservesAllRegisters() && !cg->comp()->getOption(TR_OptimizeForSpace)) return true; } return false; }
// unresolved casts or casts to things other than abstract or interface benefit from // an equality test bool OMR::TreeEvaluator::instanceOfOrCheckCastNeedEqualityTest(TR::Node * node, TR::CodeGenerator *cg) { TR::Node *castClassNode = node->getSecondChild(); TR::SymbolReference *castClassSymRef = castClassNode->getSymbolReference(); if (!TR::TreeEvaluator::isStaticClassSymRef(castClassSymRef)) { return true; } TR::StaticSymbol *castClassSym = castClassSymRef->getSymbol()->getStaticSymbol(); if (castClassSymRef->isUnresolved()) { return false; } else { TR_OpaqueClassBlock * clazz; if (castClassSym && (clazz = (TR_OpaqueClassBlock *) castClassSym->getStaticAddress()) && !TR::Compiler->cls.isInterfaceClass(cg->comp(), clazz) && ( !TR::Compiler->cls.isAbstractClass(cg->comp(), clazz) // here be dragons // int.class, char.class, etc are final & abstract // usually instanceOf calls on these classes are ripped out by the optimizer // but in some cases they can persist to codegen which without the following // case causes assertions because we opt out of calling the helper and doing // all inline tests. Really we could just jmp to the failed side, but to reduce // service risk we are going to do an equality test that we know will fail // NOTE final abstract is not enough - all array classes are final abstract // to prevent them being used with new and being extended... || (TR::Compiler->cls.isAbstractClass(cg->comp(), clazz) && TR::Compiler->cls.isClassFinal(cg->comp(), clazz) && TR::Compiler->cls.isPrimitiveClass(cg->comp(), clazz))) ) return true; } return false; }
void TR_Debug::print(TR::FILE *pOutFile, TR::S390CallSnippet * snippet) { uint8_t * bufferPos = snippet->getSnippetLabel()->getCodeLocation(); TR::Node * callNode = snippet->getNode(); TR::SymbolReference * methodSymRef = snippet->getRealMethodSymbolReference(); if(!methodSymRef) methodSymRef = callNode->getSymbolReference(); TR::MethodSymbol * methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol(); TR::SymbolReference * glueRef; int8_t padbytes = snippet->getPadBytes(); printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, methodSymRef->isUnresolved() ? "Unresolved Call Snippet" : "Call Snippet"); bufferPos = printS390ArgumentsFlush(pOutFile, callNode, bufferPos, snippet->getSizeOfArguments()); if (methodSymRef->isUnresolved() || _comp->compileRelocatableCode()) { if (methodSymbol->isSpecial()) { glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedSpecialGlue); } else if (methodSymbol->isStatic()) { glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedStaticGlue); } else { glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedDirectVirtualGlue); } } else { bool synchronised = methodSymbol->isSynchronised(); if ((methodSymbol->isVMInternalNative() || methodSymbol->isJITInternalNative())) { glueRef = _cg->getSymRef(TR_S390nativeStaticHelper); } else { switch (callNode->getDataType()) { case TR::NoType: if (synchronised) { glueRef = _cg->getSymRef(TR_S390interpreterSyncVoidStaticGlue); } else { glueRef = _cg->getSymRef(TR_S390interpreterVoidStaticGlue); } break; case TR::Int8: case TR::Int16: case TR::Int32: if (synchronised) { glueRef = _cg->getSymRef(TR_S390interpreterSyncIntStaticGlue); } else { glueRef = _cg->getSymRef(TR_S390interpreterIntStaticGlue); } break; case TR::Address: if (TR::Compiler->target.is64Bit()) { if (synchronised) { glueRef = _cg->getSymRef(TR_S390interpreterSyncLongStaticGlue); } else { glueRef = _cg->getSymRef(TR_S390interpreterLongStaticGlue); } } else { if (synchronised) { glueRef = _cg->getSymRef(TR_S390interpreterSyncIntStaticGlue); } else { glueRef = _cg->getSymRef(TR_S390interpreterIntStaticGlue); } } break; case TR::Int64: if (synchronised) { glueRef = _cg->getSymRef(TR_S390interpreterSyncLongStaticGlue); } else { glueRef = _cg->getSymRef(TR_S390interpreterLongStaticGlue); } break; case TR::Float: if (synchronised) { glueRef = _cg->getSymRef(TR_S390interpreterSyncFloatStaticGlue); } else { glueRef = _cg->getSymRef(TR_S390interpreterFloatStaticGlue); } break; case TR::Double: if (synchronised) { glueRef = _cg->getSymRef(TR_S390interpreterSyncDoubleStaticGlue); } else { glueRef = _cg->getSymRef(TR_S390interpreterDoubleStaticGlue); } break; default: TR_ASSERT(0, "Bad return data type for a call node. DataType was %s\n", getName(callNode->getDataType())); } } } bufferPos = printRuntimeInstrumentationOnOffInstruction(pOutFile, bufferPos, false); // RIOFF if (snippet->getKind() == TR::Snippet::IsUnresolvedCall) { int lengthOfLoad = (TR::Compiler->target.is64Bit())?6:4; printPrefix(pOutFile, NULL, bufferPos, 6); trfprintf(pOutFile, "LARL \tGPR14, *+%d <%p>\t# Start of Data Const.", 8 + lengthOfLoad + padbytes, bufferPos + 8 + lengthOfLoad + padbytes); bufferPos += 6; if (TR::Compiler->target.is64Bit()) { printPrefix(pOutFile, NULL, bufferPos, 6); trfprintf(pOutFile, "LG \tGPR_EP, 0(,GPR14)"); bufferPos += 6; } else { printPrefix(pOutFile, NULL, bufferPos, 4); trfprintf(pOutFile, "L \tGPR_EP, 0(,GPR14)"); bufferPos += 4; } printPrefix(pOutFile, NULL, bufferPos, 2); trfprintf(pOutFile, "BCR \tGPR_EP"); bufferPos += 2; } else { printPrefix(pOutFile, NULL, bufferPos, 6); trfprintf(pOutFile, "BRASL \tGPR14, <%p>\t# Branch to Helper Method %s", snippet->getSnippetDestAddr(), snippet->usedTrampoline()?"- Trampoline Used.":""); bufferPos += 6; } if (padbytes == 2) { printPrefix(pOutFile, NULL, bufferPos, 2); trfprintf(pOutFile, "DC \t0x0000 \t\t\t# 2-bytes padding for alignment"); bufferPos += 2; } else if (padbytes == 4) { printPrefix(pOutFile, NULL, bufferPos, 4) ; trfprintf(pOutFile, "DC \t0x00000000 \t\t# 4-bytes padding for alignment"); bufferPos += 4; } else if (padbytes == 6) { printPrefix(pOutFile, NULL, bufferPos, 6) ; trfprintf(pOutFile, "DC \t0x000000000000 \t\t# 6-bytes padding for alignment"); bufferPos += 6; } printPrefix(pOutFile, NULL, bufferPos, sizeof(intptrj_t)); trfprintf(pOutFile, "DC \t%p \t\t# Method Address", glueRef->getMethodAddress()); bufferPos += sizeof(intptrj_t); printPrefix(pOutFile, NULL, bufferPos, sizeof(intptrj_t)); trfprintf(pOutFile, "DC \t%p \t\t# Call Site RA", snippet->getCallRA()); bufferPos += sizeof(intptrj_t); if (methodSymRef->isUnresolved()) { printPrefix(pOutFile, NULL, bufferPos, 0); } else { printPrefix(pOutFile, NULL, bufferPos, sizeof(intptrj_t)); } trfprintf(pOutFile, "DC \t%p \t\t# Method Pointer", methodSymRef->isUnresolved() ? 0 : methodSymbol->getMethodAddress()); }
TR::Register *IA32LinkageUtils::pushIntegerWordArg( TR::Node *child, TR::CodeGenerator *cg) { TR::Register *pushRegister; if (child->getRegister() == NULL) { if (child->getOpCode().isLoadConst()) { int32_t value = child->getInt(); TR_X86OpCodes pushOp; if (value >= -128 && value <= 127) { pushOp = PUSHImms; } else { pushOp = PUSHImm4; } generateImmInstruction(pushOp, child, value, cg); cg->decReferenceCount(child); return NULL; } else if (child->getOpCodeValue() == TR::loadaddr) { TR::SymbolReference * symRef = child->getSymbolReference(); TR::StaticSymbol *sym = symRef->getSymbol()->getStaticSymbol(); if (sym) { TR_ASSERT(!symRef->isUnresolved(), "pushIntegerWordArg loadaddr expecting resolved symbol"); generateImmSymInstruction(PUSHImm4, child, (uintptrj_t)sym->getStaticAddress(), symRef, cg); cg->decReferenceCount(child); return NULL; } } else if (child->getOpCodeValue() == TR::fbits2i && !child->normalizeNanValues() && child->getReferenceCount() == 1) { pushRegister = pushFloatArg(child->getFirstChild(), cg); cg->decReferenceCount(child); return pushRegister; } else if (child->getOpCode().isMemoryReference() && (child->getReferenceCount() == 1) && (child->getSymbolReference() != cg->comp()->getSymRefTab()->findVftSymbolRef())) { TR::MemoryReference *tempMR = generateX86MemoryReference(child, cg); generateMemInstruction(PUSHMem, child, tempMR, cg); tempMR->decNodeReferenceCounts(cg); cg->decReferenceCount(child); return NULL; } } pushRegister = cg->evaluate(child); generateRegInstruction(PUSHReg, child, pushRegister, cg); cg->decReferenceCount(child); return pushRegister; }