--- old/hotspot/src/share/vm/opto/callGenerator.hpp 2013-09-18 21:13:32.769031805 +0400 +++ new/hotspot/src/share/vm/opto/callGenerator.hpp 2013-09-18 21:13:32.669031803 +0400 @@ -65,6 +65,8 @@ virtual bool is_predicted() const { return false; } // is_trap: Does not return to the caller. (E.g., uncommon trap.) virtual bool is_trap() const { return false; } + // is_low_priority: Should try inlining as normal method first. + virtual bool is_low_priority() const { return false; } // is_late_inline: supports conversion of call into an inline virtual bool is_late_inline() const { return false; } --- old/hotspot/src/share/vm/opto/compile.hpp 2013-09-18 21:13:33.249031816 +0400 +++ new/hotspot/src/share/vm/opto/compile.hpp 2013-09-18 21:13:33.089031813 +0400 @@ -815,6 +815,7 @@ // Decide how to build a call. // The profile factor is a discount to apply to this site's interp. profile. CallGenerator* call_generator(ciMethod* call_method, int vtable_index, bool call_does_dispatch, JVMState* jvms, bool allow_inline, float profile_factor, bool allow_intrinsics = true, bool delayed_forbidden = false); + CallGenerator* inline_intrinsic(ciMethod* call_method, int vtable_index, bool call_does_dispatch, JVMState* jvms, bool allow_inline, float profile_factor); bool should_delay_inlining(ciMethod* call_method, JVMState* jvms) { return should_delay_string_inlining(call_method, jvms) || should_delay_boxing_inlining(call_method, jvms); --- old/hotspot/src/share/vm/opto/doCall.cpp 2013-09-18 21:13:33.665031826 +0400 +++ new/hotspot/src/share/vm/opto/doCall.cpp 2013-09-18 21:13:33.561031824 +0400 @@ -61,6 +61,20 @@ } } +CallGenerator* Compile::inline_intrinsic(ciMethod* callee, int vtable_index, bool call_does_dispatch, + JVMState* jvms, bool allow_inline, float prof_factor) { + CallGenerator* cg = find_intrinsic(callee, call_does_dispatch); + if (cg != NULL && cg->is_predicted()) { + // Code without intrinsic but, hopefully, inlined. + CallGenerator* inline_cg = this->call_generator(callee, + vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, false); + if (inline_cg != NULL) { + cg = CallGenerator::for_predicted_intrinsic(cg, inline_cg); + } + } + return cg; +} + CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool call_does_dispatch, JVMState* jvms, bool allow_inline, float prof_factor, bool allow_intrinsics, bool delayed_forbidden) { @@ -111,16 +125,12 @@ // We do this before the strict f.p. check below because the // intrinsics handle strict f.p. correctly. if (allow_inline && allow_intrinsics) { - CallGenerator* cg = find_intrinsic(callee, call_does_dispatch); - if (cg != NULL) { - if (cg->is_predicted()) { - // Code without intrinsic but, hopefully, inlined. - CallGenerator* inline_cg = this->call_generator(callee, - vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, false); - if (inline_cg != NULL) { - cg = CallGenerator::for_predicted_intrinsic(cg, inline_cg); - } - } + CallGenerator* cg = inline_intrinsic(callee, + vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor); + // If intrinsic is marked low priority, then skip inlining until + // other inlining mechanics is in effect. We will retry after everything + // else is tried. + if (cg != NULL && !cg->is_low_priority()) { return cg; } } @@ -266,6 +276,16 @@ } } + // Try intrinsics again. This will inline any low-priority intrinsics, + // if the code above did not take are of them. + if (allow_inline && allow_intrinsics) { + CallGenerator* cg = inline_intrinsic(callee, + vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor); + if (cg != NULL) { + return cg; + } + } + // There was no special inlining tactic, or it bailed out. // Use a more generic tactic, like a simple call. if (call_does_dispatch) { --- old/hotspot/src/share/vm/opto/library_call.cpp 2013-09-18 21:13:34.137031837 +0400 +++ new/hotspot/src/share/vm/opto/library_call.cpp 2013-09-18 21:13:34.029031835 +0400 @@ -46,19 +46,22 @@ private: bool _is_virtual; bool _is_predicted; + bool _is_low_priority; vmIntrinsics::ID _intrinsic_id; public: - LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, vmIntrinsics::ID id) + LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, bool is_low_priority, vmIntrinsics::ID id) : InlineCallGenerator(m), _is_virtual(is_virtual), _is_predicted(is_predicted), + _is_low_priority(is_low_priority), _intrinsic_id(id) { } virtual bool is_intrinsic() const { return true; } virtual bool is_virtual() const { return _is_virtual; } virtual bool is_predicted() const { return _is_predicted; } + virtual bool is_low_priority() const { return _is_low_priority; } virtual JVMState* generate(JVMState* jvms); virtual Node* generate_predicate(JVMState* jvms); vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; } @@ -352,6 +355,7 @@ } bool is_predicted = false; + bool is_low_priority = false; switch (id) { case vmIntrinsics::_compareTo: @@ -378,6 +382,7 @@ break; case vmIntrinsics::_hashCode: if (!InlineObjectHash) return NULL; + is_low_priority = true; break; case vmIntrinsics::_clone: case vmIntrinsics::_copyOf: @@ -529,7 +534,7 @@ if (!InlineUnsafeOps) return NULL; } - return new LibraryIntrinsic(m, is_virtual, is_predicted, (vmIntrinsics::ID) id); + return new LibraryIntrinsic(m, is_virtual, is_predicted, is_low_priority, (vmIntrinsics::ID) id); } //----------------------register_library_intrinsics-----------------------