src/share/vm/opto/library_call.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/vm/opto/library_call.cpp	Tue Jul 14 18:39:24 2015
--- new/src/share/vm/opto/library_call.cpp	Tue Jul 14 18:39:23 2015

*** 302,347 **** --- 302,381 ---- bool inline_profileBoolean(); bool inline_isCompileConstant(); }; //---------------------------make_vm_intrinsic---------------------------- CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { vmIntrinsics::ID id = m->intrinsic_id(); + bool Compile::intrinsic_does_virtual_dispatch_for(vmIntrinsics::ID id) { assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); ! ccstr disable_intr = NULL; if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) || (method_has_option_value("DisableIntrinsic", disable_intr) && strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)) { // disabled by a user request on the command line: // example: -XX:DisableIntrinsic=_hashCode,_getClass return NULL; + switch(id) { ! case vmIntrinsics::_hashCode: + case vmIntrinsics::_clone: + return true; + break; + default: + return false; } + } + int Compile::intrinsic_predicates_needed_for(vmIntrinsics::ID id) { + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); + switch (id) { + case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: + case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: + return 1; + case vmIntrinsics::_digestBase_implCompressMB: + return 3; + default: + return 0; + } + } ! if (!m->is_loaded()) { // do not attempt to inline unloaded methods return NULL; ! bool Compile::is_intrinsic_available_for(Method* method, Method* compilation_context, bool is_virtual) { + vmIntrinsics::ID id = method->intrinsic_id(); + if (id < vmIntrinsics::FIRST_ID || id >= vmIntrinsics::LAST_COMPILER_INLINE) { + return false; + } + + // Check if the intrinsic corresponding to 'method' has been disabled on + // the command line by using the DisableIntrinsic flag (either globally + // or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp + // for details). + // Usually, the compilation context is the caller of the method 'method'. + // The only case when for a non-recursive method 'method' the compilation context + // is not the caller of the 'method' (but it is the method itself) is + // java.lang.ref.Referene::get. + // For java.lang.ref.Reference::get, the intrinsic version is used + // instead of the C2-compiled version so that the value in the referent + // field can be registered by the G1 pre-barrier code. The intrinsified + // version of Reference::get also adds a memory barrier to prevent + // commoning reads from the referent field across safepoint since GC + // can change the referent field's value. See Compile::Compile() + // in src/share/vm/opto/compile.cpp for more details. + ccstr disable_intr = NULL; + if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) || + (compilation_context != NULL && + CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) && + strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL) + ) { + return false; } ! // Only a few intrinsics implement a virtual dispatch. // They are expensive calls which are also frequently overridden. ! // Only Object.hashCode and Object.clone intrinsics implement also a virtual + // dispatch because calling both methods is expensive but both methods are + // frequently overridden. All other intrinsics implement only a non-virtual + // dispatch. if (is_virtual) { switch (id) { case vmIntrinsics::_hashCode: case vmIntrinsics::_clone: // OK, Object.hashCode and Object.clone intrinsics come in both flavors break; default: ! return NULL; ! return false; } } ! // -XX:-InlineNatives disables nearly all intrinsics: ! // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in + // the following switch statement. if (!InlineNatives) { switch (id) { case vmIntrinsics::_indexOf: case vmIntrinsics::_compareTo: case vmIntrinsics::_equals:
*** 352,635 **** --- 386,652 ---- case vmIntrinsics::_getAndSetLong: case vmIntrinsics::_getAndSetObject: case vmIntrinsics::_loadFence: case vmIntrinsics::_storeFence: case vmIntrinsics::_fullFence: break; // InlineNatives does not control String.compareTo case vmIntrinsics::_Reference_get: - break; // InlineNatives does not control Reference.get default: ! return NULL; ! return false; } } int predicates = 0; bool does_virtual_dispatch = false; switch (id) { case vmIntrinsics::_compareTo: ! if (!SpecialStringCompareTo) return NULL; ! if (!Matcher::match_rule_supported(Op_StrComp)) return NULL; ! if (!SpecialStringCompareTo) return false; ! if (!Matcher::match_rule_supported(Op_StrComp)) return false; break; case vmIntrinsics::_indexOf: ! if (!SpecialStringIndexOf) return NULL; ! if (!SpecialStringIndexOf) return false; break; case vmIntrinsics::_equals: ! if (!SpecialStringEquals) return NULL; ! if (!Matcher::match_rule_supported(Op_StrEquals)) return NULL; ! if (!SpecialStringEquals) return false; ! if (!Matcher::match_rule_supported(Op_StrEquals)) return false; break; case vmIntrinsics::_equalsC: ! if (!SpecialArraysEquals) return NULL; ! if (!Matcher::match_rule_supported(Op_AryEq)) return NULL; ! if (!SpecialArraysEquals) return false; ! if (!Matcher::match_rule_supported(Op_AryEq)) return false; break; case vmIntrinsics::_arraycopy: ! if (!InlineArrayCopy) return NULL; ! if (!InlineArrayCopy) return false; break; case vmIntrinsics::_copyMemory: ! if (StubRoutines::unsafe_arraycopy() == NULL) return NULL; ! if (!InlineArrayCopy) return NULL; ! if (!InlineArrayCopy) return false; ! if (StubRoutines::unsafe_arraycopy() == NULL) return false; break; case vmIntrinsics::_hashCode: ! if (!InlineObjectHash) return NULL; does_virtual_dispatch = true; ! if (!InlineObjectHash) return false; break; case vmIntrinsics::_clone: does_virtual_dispatch = true; case vmIntrinsics::_copyOf: case vmIntrinsics::_copyOfRange: if (!InlineObjectCopy) return NULL; // These also use the arraycopy intrinsic mechanism: ! if (!InlineArrayCopy) return NULL; + // These intrinsics use both the objectcopy and the arraycopy + // intrinsic mechanism. ! if (!InlineObjectCopy || !InlineArrayCopy) return false; break; case vmIntrinsics::_encodeISOArray: ! if (!SpecialEncodeISOArray) return NULL; ! if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return NULL; ! if (!SpecialEncodeISOArray) return false; ! if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return false; break; case vmIntrinsics::_checkIndex: // We do not intrinsify this. The optimizer does fine with it. ! return NULL; ! return false; case vmIntrinsics::_getCallerClass: ! if (!InlineReflectionGetCallerClass) return NULL; if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) return NULL; ! if (!InlineReflectionGetCallerClass || + SystemDictionary::reflect_CallerSensitive_klass() == NULL) { + return false; + } break; case vmIntrinsics::_bitCount_i: ! if (!Matcher::match_rule_supported(Op_PopCountI)) return NULL; ! if (!Matcher::match_rule_supported(Op_PopCountI)) return false; break; case vmIntrinsics::_bitCount_l: ! if (!Matcher::match_rule_supported(Op_PopCountL)) return NULL; ! if (!Matcher::match_rule_supported(Op_PopCountL)) return false; break; case vmIntrinsics::_numberOfLeadingZeros_i: ! if (!Matcher::match_rule_supported(Op_CountLeadingZerosI)) return NULL; ! if (!Matcher::match_rule_supported(Op_CountLeadingZerosI)) return false; break; case vmIntrinsics::_numberOfLeadingZeros_l: ! if (!Matcher::match_rule_supported(Op_CountLeadingZerosL)) return NULL; ! if (!Matcher::match_rule_supported(Op_CountLeadingZerosL)) return false; break; case vmIntrinsics::_numberOfTrailingZeros_i: ! if (!Matcher::match_rule_supported(Op_CountTrailingZerosI)) return NULL; ! if (!Matcher::match_rule_supported(Op_CountTrailingZerosI)) return false; break; case vmIntrinsics::_numberOfTrailingZeros_l: ! if (!Matcher::match_rule_supported(Op_CountTrailingZerosL)) return NULL; ! if (!Matcher::match_rule_supported(Op_CountTrailingZerosL)) return false; break; case vmIntrinsics::_reverseBytes_c: ! if (!Matcher::match_rule_supported(Op_ReverseBytesUS)) return NULL; ! if (!Matcher::match_rule_supported(Op_ReverseBytesUS)) return false; break; case vmIntrinsics::_reverseBytes_s: ! if (!Matcher::match_rule_supported(Op_ReverseBytesS)) return NULL; ! if (!Matcher::match_rule_supported(Op_ReverseBytesS)) return false; break; case vmIntrinsics::_reverseBytes_i: ! if (!Matcher::match_rule_supported(Op_ReverseBytesI)) return NULL; ! if (!Matcher::match_rule_supported(Op_ReverseBytesI)) return false; break; case vmIntrinsics::_reverseBytes_l: ! if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return NULL; ! if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return false; break; case vmIntrinsics::_Reference_get: // Use the intrinsic version of Reference.get() so that the value in // the referent field can be registered by the G1 pre-barrier code. // Also add memory barrier to prevent commoning reads from this field // across safepoint since GC can change it value. break; case vmIntrinsics::_compareAndSwapObject: #ifdef _LP64 ! if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return NULL; ! if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return false; #endif - break; case vmIntrinsics::_compareAndSwapLong: ! if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return NULL; ! if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return false; break; case vmIntrinsics::_getAndAddInt: ! if (!Matcher::match_rule_supported(Op_GetAndAddI)) return NULL; ! if (!Matcher::match_rule_supported(Op_GetAndAddI)) return false; break; case vmIntrinsics::_getAndAddLong: ! if (!Matcher::match_rule_supported(Op_GetAndAddL)) return NULL; ! if (!Matcher::match_rule_supported(Op_GetAndAddL)) return false; break; case vmIntrinsics::_getAndSetInt: ! if (!Matcher::match_rule_supported(Op_GetAndSetI)) return NULL; ! if (!Matcher::match_rule_supported(Op_GetAndSetI)) return false; break; case vmIntrinsics::_getAndSetLong: ! if (!Matcher::match_rule_supported(Op_GetAndSetL)) return NULL; ! if (!Matcher::match_rule_supported(Op_GetAndSetL)) return false; break; case vmIntrinsics::_getAndSetObject: #ifdef _LP64 ! if (!UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetP)) return NULL; ! if (UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetN)) return NULL; ! if (!UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetP)) return false; ! if (UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetN)) return false; break; #else ! if (!Matcher::match_rule_supported(Op_GetAndSetP)) return NULL; ! if (!Matcher::match_rule_supported(Op_GetAndSetP)) return false; break; #endif case vmIntrinsics::_aescrypt_encryptBlock: case vmIntrinsics::_aescrypt_decryptBlock: ! if (!UseAESIntrinsics) return NULL; ! if (!UseAESIntrinsics) return false; break; case vmIntrinsics::_multiplyToLen: ! if (!UseMultiplyToLenIntrinsic) return NULL; ! if (!UseMultiplyToLenIntrinsic) return false; break; case vmIntrinsics::_squareToLen: ! if (!UseSquareToLenIntrinsic) return NULL; ! if (!UseSquareToLenIntrinsic) return false; break; case vmIntrinsics::_mulAdd: ! if (!UseMulAddIntrinsic) return NULL; ! if (!UseMulAddIntrinsic) return false; break; case vmIntrinsics::_montgomeryMultiply: ! if (!UseMontgomeryMultiplyIntrinsic) return NULL; ! if (!UseMontgomeryMultiplyIntrinsic) return false; break; case vmIntrinsics::_montgomerySquare: ! if (!UseMontgomerySquareIntrinsic) return NULL; ! if (!UseMontgomerySquareIntrinsic) return false; break; case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: ! if (!UseAESIntrinsics) return NULL; // these two require the predicated logic predicates = 1; ! if (!UseAESIntrinsics) return false; break; case vmIntrinsics::_sha_implCompress: ! if (!UseSHA1Intrinsics) return NULL; ! if (!UseSHA1Intrinsics) return false; break; case vmIntrinsics::_sha2_implCompress: ! if (!UseSHA256Intrinsics) return NULL; ! if (!UseSHA256Intrinsics) return false; break; case vmIntrinsics::_sha5_implCompress: ! if (!UseSHA512Intrinsics) return NULL; ! if (!UseSHA512Intrinsics) return false; break; case vmIntrinsics::_digestBase_implCompressMB: ! if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return NULL; predicates = 3; ! if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return false; break; case vmIntrinsics::_ghash_processBlocks: ! if (!UseGHASHIntrinsics) return NULL; ! if (!UseGHASHIntrinsics) return false; break; case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: ! if (!UseCRC32Intrinsics) return NULL; ! if (!UseCRC32Intrinsics) return false; break; case vmIntrinsics::_updateBytesCRC32C: case vmIntrinsics::_updateDirectByteBufferCRC32C: ! if (!UseCRC32CIntrinsics) return NULL; ! if (!UseCRC32CIntrinsics) return false; break; case vmIntrinsics::_incrementExactI: case vmIntrinsics::_addExactI: ! if (!Matcher::match_rule_supported(Op_OverflowAddI) || !UseMathExactIntrinsics) return NULL; ! if (!UseMathExactIntrinsics || !Matcher::match_rule_supported(Op_OverflowAddI)) return false; break; case vmIntrinsics::_incrementExactL: case vmIntrinsics::_addExactL: ! if (!Matcher::match_rule_supported(Op_OverflowAddL) || !UseMathExactIntrinsics) return NULL; ! if (!UseMathExactIntrinsics || !Matcher::match_rule_supported(Op_OverflowAddL)) return false; break; case vmIntrinsics::_decrementExactI: case vmIntrinsics::_subtractExactI: if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL; + case vmIntrinsics::_negateExactI: + if (!UseMathExactIntrinsics || !Matcher::match_rule_supported(Op_OverflowSubI)) return false; break; case vmIntrinsics::_decrementExactL: case vmIntrinsics::_subtractExactL: if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL; break; case vmIntrinsics::_negateExactI: if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL; break; case vmIntrinsics::_negateExactL: ! if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL; ! if (!UseMathExactIntrinsics || !Matcher::match_rule_supported(Op_OverflowSubL)) return false; break; case vmIntrinsics::_multiplyExactI: ! if (!Matcher::match_rule_supported(Op_OverflowMulI) || !UseMathExactIntrinsics) return NULL; ! if (!UseMathExactIntrinsics || !Matcher::match_rule_supported(Op_OverflowMulI)) return false; break; case vmIntrinsics::_multiplyExactL: ! if (!Matcher::match_rule_supported(Op_OverflowMulL) || !UseMathExactIntrinsics) return NULL; ! if (!Matcher::match_rule_supported(Op_OverflowMulL) || !UseMathExactIntrinsics) return false; break; case vmIntrinsics::_getShortUnaligned: case vmIntrinsics::_getCharUnaligned: case vmIntrinsics::_getIntUnaligned: case vmIntrinsics::_getLongUnaligned: case vmIntrinsics::_putShortUnaligned: case vmIntrinsics::_putCharUnaligned: case vmIntrinsics::_putIntUnaligned: case vmIntrinsics::_putLongUnaligned: ! if (!UseUnalignedAccesses) return NULL; ! if (!UseUnalignedAccesses) return false; break; default: assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility"); assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); break; } + Symbol* method_holder = method->method_holder()->name(); // -XX:-InlineClassNatives disables natives from the Class class. // The flag applies to all reflective calls, notably Array.newArray // (visible to Java programmers as Array.newInstance). ! if (m->holder()->name() == ciSymbol::java_lang_Class() || ! m->holder()->name() == ciSymbol::java_lang_reflect_Array()) { ! if (!InlineClassNatives) return NULL; ! if (method_holder == vmSymbols::java_lang_Class() || ! method_holder == vmSymbols::java_lang_reflect_Array()) { ! if (!InlineClassNatives) return false; } // -XX:-InlineThreadNatives disables natives from the Thread class. ! if (m->holder()->name() == ciSymbol::java_lang_Thread()) { ! if (!InlineThreadNatives) return NULL; ! if (method_holder == vmSymbols::java_lang_Thread()) { ! if (!InlineThreadNatives) return false; } // -XX:-InlineMathNatives disables natives from the Math,Float and Double classes. ! if (m->holder()->name() == ciSymbol::java_lang_Math() || ! m->holder()->name() == ciSymbol::java_lang_Float() || ! m->holder()->name() == ciSymbol::java_lang_Double()) { ! if (!InlineMathNatives) return NULL; ! if (method_holder == vmSymbols::java_lang_Math() || ! method_holder == vmSymbols::java_lang_Float() || ! method_holder == vmSymbols::java_lang_Double()) { ! if (!InlineMathNatives) return false; } // -XX:-InlineUnsafeOps disables natives from the Unsafe class. ! if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) { ! if (!InlineUnsafeOps) return NULL; ! if (method_holder == vmSymbols::sun_misc_Unsafe()) { ! if (!InlineUnsafeOps) return false; + } + + return true; + } + + //---------------------------make_vm_intrinsic---------------------------- + CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { + vmIntrinsics::ID id = m->intrinsic_id(); + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); + + if (!m->is_loaded()) { + // Do not attempt to inline unloaded methods. + return NULL; } ! return new LibraryIntrinsic(m, is_virtual, predicates, does_virtual_dispatch, (vmIntrinsics::ID) id); ! bool is_available = false; + { + // For calling is_intrinsic_available we need to transition to + // the '_thread_in_vm' stat because is_intrinsic_available_for() + // accesses VM-internal data. + VM_ENTRY_MARK; + methodHandle mh(THREAD, m->get_Method()); + methodHandle ct(THREAD, method()->get_Method()); + is_available = is_intrinsic_available_for(mh(), ct(), is_virtual); + } + + if (is_available) { + assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility"); + assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); + return new LibraryIntrinsic(m, is_virtual, + intrinsic_predicates_needed_for(id), + intrinsic_does_virtual_dispatch_for(id), + (vmIntrinsics::ID) id); + } else { + return NULL; + } } //----------------------register_library_intrinsics----------------------- // Initialize this file's data structures, for each Compile instance. void Compile::register_library_intrinsics() {

src/share/vm/opto/library_call.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File