diff --git a/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp b/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp index a508a6bb41d..0220c705f04 100644 --- a/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp +++ b/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp @@ -460,6 +460,14 @@ jdk_internal_misc_Unsafe_compareAndExchangeReference, jdk_internal_misc_Unsafe_copyMemory0, + jdk_internal_misc_Unsafe_getCharUnaligned, + jdk_internal_misc_Unsafe_getShortUnaligned, + jdk_internal_misc_Unsafe_getIntUnaligned, + jdk_internal_misc_Unsafe_getLongUnaligned, + jdk_internal_misc_Unsafe_putCharUnaligned, + jdk_internal_misc_Unsafe_putShortUnaligned, + jdk_internal_misc_Unsafe_putIntUnaligned, + jdk_internal_misc_Unsafe_putLongUnaligned, jdk_internal_loader_NativeLibraries_load, jdk_internal_util_ArraysSupport_vectorizedMismatch, jdk_internal_util_ArraysSupport_vectorizedHashCode, diff --git a/runtime/compiler/env/j9method.cpp b/runtime/compiler/env/j9method.cpp index 3c65db055f6..d0a9482bfd0 100644 --- a/runtime/compiler/env/j9method.cpp +++ b/runtime/compiler/env/j9method.cpp @@ -3010,7 +3010,15 @@ void TR_ResolvedJ9Method::construct() {x(TR::sun_misc_Unsafe_ensureClassInitialized, "ensureClassInitialized", "(Ljava/lang/Class;)V")}, {x(TR::sun_misc_Unsafe_allocateInstance, "allocateInstance", "(Ljava/lang/Class;)Ljava/lang/Object;")}, {x(TR::sun_misc_Unsafe_allocateUninitializedArray0, "allocateUninitializedArray0", "(Ljava/lang/Class;I)Ljava/lang/Object;")}, - {x(TR::jdk_internal_misc_Unsafe_copyMemory0, "copyMemory0", "(Ljava/lang/Object;JLjava/lang/Object;JJ)V")}, + {x(TR::jdk_internal_misc_Unsafe_copyMemory0, "copyMemory0", "(Ljava/lang/Object;JLjava/lang/Object;JJ)V")}, + {x(TR::jdk_internal_misc_Unsafe_getCharUnaligned, "getCharUnaligned", "(Ljava/lang/Object;J)C")}, + {x(TR::jdk_internal_misc_Unsafe_getShortUnaligned, "getShortUnaligned", "(Ljava/lang/Object;J)S")}, + {x(TR::jdk_internal_misc_Unsafe_getIntUnaligned, "getIntUnaligned", "(Ljava/lang/Object;J)I")}, + {x(TR::jdk_internal_misc_Unsafe_getLongUnaligned, "getLongUnaligned", "(Ljava/lang/Object;J)J")}, + {x(TR::jdk_internal_misc_Unsafe_putCharUnaligned, "putCharUnaligned", "(Ljava/lang/Object;JC)V")}, + {x(TR::jdk_internal_misc_Unsafe_putShortUnaligned, "putShortUnaligned", "(Ljava/lang/Object;JS)V")}, + {x(TR::jdk_internal_misc_Unsafe_putIntUnaligned, "putIntUnaligned", "(Ljava/lang/Object;JI)V")}, + {x(TR::jdk_internal_misc_Unsafe_putLongUnaligned, "putLongUnaligned", "(Ljava/lang/Object;JJ)V")}, { TR::unknownMethod} }; @@ -5632,6 +5640,14 @@ TR_J9MethodBase::isUnsafeWithObjectArg() case TR::sun_misc_Unsafe_putFloatOrdered_jlObjectJF_V: case TR::sun_misc_Unsafe_putDoubleOrdered_jlObjectJD_V: case TR::sun_misc_Unsafe_putObjectOrdered_jlObjectJjlObject_V: + case TR::jdk_internal_misc_Unsafe_getCharUnaligned: + case TR::jdk_internal_misc_Unsafe_getShortUnaligned: + case TR::jdk_internal_misc_Unsafe_getIntUnaligned: + case TR::jdk_internal_misc_Unsafe_getLongUnaligned: + case TR::jdk_internal_misc_Unsafe_putCharUnaligned: + case TR::jdk_internal_misc_Unsafe_putShortUnaligned: + case TR::jdk_internal_misc_Unsafe_putIntUnaligned: + case TR::jdk_internal_misc_Unsafe_putLongUnaligned: return true; default: return false; diff --git a/runtime/compiler/optimizer/InlinerTempForJ9.cpp b/runtime/compiler/optimizer/InlinerTempForJ9.cpp index 2a3bcaad29f..3e090cc7a7f 100644 --- a/runtime/compiler/optimizer/InlinerTempForJ9.cpp +++ b/runtime/compiler/optimizer/InlinerTempForJ9.cpp @@ -1386,10 +1386,23 @@ Unsafe.getShort. */ bool -TR_J9InlinerPolicy::createUnsafePutWithOffset(TR::ResolvedMethodSymbol *calleeSymbol, TR::ResolvedMethodSymbol *callerSymbol, TR::TreeTop * callNodeTreeTop, TR::Node * unsafeCall, TR::DataType type, bool isVolatile, bool needNullCheck, bool isOrdered) +TR_J9InlinerPolicy::createUnsafePutWithOffset(TR::ResolvedMethodSymbol *calleeSymbol, + TR::ResolvedMethodSymbol *callerSymbol, + TR::TreeTop * callNodeTreeTop, + TR::Node * unsafeCall, + TR::DataType type, + bool isVolatile, + bool needNullCheck, + bool isOrdered, + bool isUnaligned) { if (isVolatile && type == TR::Int64 && comp()->target().is32Bit() && !comp()->cg()->getSupportsInlinedAtomicLongVolatiles()) return false; + + // In general, Z does not permit unaligned accesses + if (isUnaligned && comp()->target().cpu.isZ()) + return false; + if (debug("traceUnsafe")) printf("createUnsafePutWithOffset %d in %s\n", type.getDataType(), comp()->signature()); @@ -1965,11 +1978,21 @@ TR_J9InlinerPolicy::createUnsafeCASCallDiamond(TR::TreeTop *callNodeTreeTop, TR: bool -TR_J9InlinerPolicy::createUnsafeGetWithOffset(TR::ResolvedMethodSymbol *calleeSymbol, TR::ResolvedMethodSymbol *callerSymbol, TR::TreeTop * callNodeTreeTop, TR::Node * unsafeCall, TR::DataType type, bool isVolatile, bool needNullCheck) +TR_J9InlinerPolicy::createUnsafeGetWithOffset(TR::ResolvedMethodSymbol *calleeSymbol, + TR::ResolvedMethodSymbol *callerSymbol, + TR::TreeTop * callNodeTreeTop, + TR::Node * unsafeCall, + TR::DataType type, + bool isVolatile, + bool needNullCheck, + bool isUnaligned) { if (isVolatile && type == TR::Int64 && comp()->target().is32Bit() && !comp()->cg()->getSupportsInlinedAtomicLongVolatiles()) return false; + if (isUnaligned && comp()->target().cpu.isZ()) + return false; + if (debug("traceUnsafe")) printf("createUnsafeGetWithOffset %s in %s\n", type.toString(), comp()->signature()); @@ -2063,6 +2086,7 @@ TR_J9InlinerPolicy::createUnsafeGetWithOffset(TR::ResolvedMethodSymbol *calleeSy case TR::sun_misc_Unsafe_getChar_jlObjectJ_C: case TR::sun_misc_Unsafe_getCharVolatile_jlObjectJ_C: case TR::sun_misc_Unsafe_getChar_J_C: + case TR::jdk_internal_misc_Unsafe_getCharUnaligned: unsignedType = true; break; //byte and short are signed so we need a signed conversion @@ -2073,6 +2097,7 @@ TR_J9InlinerPolicy::createUnsafeGetWithOffset(TR::ResolvedMethodSymbol *calleeSy case TR::sun_misc_Unsafe_getShort_jlObjectJ_S: case TR::sun_misc_Unsafe_getShortVolatile_jlObjectJ_S: case TR::sun_misc_Unsafe_getShort_J_S: + case TR::jdk_internal_misc_Unsafe_getShortUnaligned: unsignedType = false; break; default: @@ -2578,6 +2603,24 @@ TR_J9InlinerPolicy::inlineUnsafeCall(TR::ResolvedMethodSymbol *calleeSymbol, TR: case TR::sun_misc_Unsafe_putObjectOrdered_jlObjectJjlObject_V: return createUnsafePutWithOffset(calleeSymbol, callerSymbol, callNodeTreeTop, callNode, TR::Address, false, true, true); + // FIXME: Update createUnsafePutWithOffset signature to have isVolatile, isOrdered, isUnaligned as enum + case TR::jdk_internal_misc_Unsafe_getCharUnaligned: + return createUnsafeGetWithOffset(calleeSymbol, callerSymbol, callNodeTreeTop, callNode, TR::Int8, /*needsNullCheck*/false, /*isUnaligned*/true); + case TR::jdk_internal_misc_Unsafe_getShortUnaligned: + return createUnsafeGetWithOffset(calleeSymbol, callerSymbol, callNodeTreeTop, callNode, TR::Int16, /*needsNullCheck*/false, /*isUnaligned*/true); + case TR::jdk_internal_misc_Unsafe_getIntUnaligned: + return createUnsafeGetWithOffset(calleeSymbol, callerSymbol, callNodeTreeTop, callNode, TR::Int32, /*needsNullCheck*/false, /*isUnaligned*/true); + case TR::jdk_internal_misc_Unsafe_getLongUnaligned: + return createUnsafeGetWithOffset(calleeSymbol, callerSymbol, callNodeTreeTop, callNode, TR::Int64, /*needsNullCheck*/false, /*isUnaligned*/true); + case TR::jdk_internal_misc_Unsafe_putCharUnaligned: + return createUnsafePutWithOffset(calleeSymbol, callerSymbol, callNodeTreeTop, callNode, TR::Int16, /*isVolatile*/false, /*needsNullCheck*/false, /*isOrdered*/false, /*isUnaligned*/true); + case TR::jdk_internal_misc_Unsafe_putShortUnaligned: + return createUnsafePutWithOffset(calleeSymbol, callerSymbol, callNodeTreeTop, callNode, TR::Int16, /*isVolatile*/false, /*needsNullCheck*/false, /*isOrdered*/false, /*isUnaligned*/true); + case TR::jdk_internal_misc_Unsafe_putIntUnaligned: + return createUnsafePutWithOffset(calleeSymbol, callerSymbol, callNodeTreeTop, callNode, TR::Int32, /*isVolatile*/false, /*needsNullCheck*/false, /*isOrdered*/false, /*isUnaligned*/true); + case TR::jdk_internal_misc_Unsafe_putLongUnaligned: + return createUnsafePutWithOffset(calleeSymbol, callerSymbol, callNodeTreeTop, callNode, TR::Int64, /*isVolatile*/false, /*needsNullCheck*/false, /*isOrdered*/false, /*isUnaligned*/true); + case TR::sun_misc_Unsafe_getBooleanVolatile_jlObjectJ_Z: return createUnsafeGetWithOffset(calleeSymbol, callerSymbol, callNodeTreeTop, callNode, TR::Int8, true); case TR::sun_misc_Unsafe_getByteVolatile_jlObjectJ_B: diff --git a/runtime/compiler/optimizer/J9Inliner.hpp b/runtime/compiler/optimizer/J9Inliner.hpp index e510766f3d4..fe130e77fe2 100644 --- a/runtime/compiler/optimizer/J9Inliner.hpp +++ b/runtime/compiler/optimizer/J9Inliner.hpp @@ -230,13 +230,13 @@ class TR_J9InlinerPolicy : public OMR_InlinerPolicy * after executing either \c branchTargetTree or \c fallThroughTree */ TR::Block * createUnsafeGetPutCallDiamond(TR::TreeTop* callNodeTreeTop, TR::TreeTop* comparisonTree, TR::TreeTop* branchTargetTree, TR::TreeTop* fallThroughTree); - bool createUnsafePutWithOffset(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *, TR::DataType, bool, bool needNullCheck = false, bool isOrdered = false); + bool createUnsafePutWithOffset(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *, TR::DataType, bool, bool needNullCheck = false, bool isOrdered = false, bool isUnaligned = false); TR::TreeTop* genDirectAccessCodeForUnsafeGetPut(TR::Node* callNode, bool conversionNeeded, bool isUnsafeGet); void createTempsForUnsafePutGet(TR::Node*& unsafeAddress, TR::Node* unsafeCall, TR::TreeTop* callNodeTreeTop, TR::Node*& offset, TR::SymbolReference*& newSymbolReferenceForAddress, bool isUnsafeGet); bool createUnsafeGet(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *, TR::DataType, bool compress = true); bool createUnsafePut(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *, TR::DataType, bool compress = true); TR::Node * createUnsafeAddress(TR::Node *); - bool createUnsafeGetWithOffset(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *, TR::DataType, bool, bool needNullCheck = false); + bool createUnsafeGetWithOffset(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *, TR::DataType, bool, bool needNullCheck = false, bool isUnaligned = false); TR::Node * createUnsafeAddressWithOffset(TR::Node *); bool createUnsafeFence(TR::TreeTop *, TR::Node *, TR::ILOpCodes);