--- old/src/cpu/ppc/vm/vm_version_ppc.cpp 2016-01-25 21:56:17.000000000 +0300 +++ new/src/cpu/ppc/vm/vm_version_ppc.cpp 2016-01-25 21:56:17.000000000 +0300 @@ -173,6 +173,12 @@ FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); } + if (UseOnSpinWaitIntrinsic) { + if (!FLAG_IS_DEFAULT(UseOnSpinWaitIntrinsic)) + warning("onSpinWait intrinsic is not available on this CPU"); + FLAG_SET_DEFAULT(UseOnSpinWaitIntrinsic, false); + } + // The AES intrinsic stubs require AES instruction support. if (UseAES) { warning("AES instructions are not available on this CPU"); --- old/src/cpu/sparc/vm/vm_version_sparc.cpp 2016-01-25 21:56:17.000000000 +0300 +++ new/src/cpu/sparc/vm/vm_version_sparc.cpp 2016-01-25 21:56:17.000000000 +0300 @@ -356,6 +356,12 @@ FLAG_SET_DEFAULT(UseCRC32Intrinsics, false); } + if (UseOnSpinWaitIntrinsic) { + if (!FLAG_IS_DEFAULT(UseOnSpinWaitIntrinsic)) + warning("onSpinWait intrinsic is not available on this CPU"); + FLAG_SET_DEFAULT(UseOnSpinWaitIntrinsic, false); + } + if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && (cache_line_size > ContendedPaddingWidth)) ContendedPaddingWidth = cache_line_size; --- old/src/cpu/x86/vm/x86_64.ad 2016-01-25 21:56:18.000000000 +0300 +++ new/src/cpu/x86/vm/x86_64.ad 2016-01-25 21:56:18.000000000 +0300 @@ -6336,6 +6336,25 @@ ins_pipe(empty); %} +instruct onspinwait() +%{ + match(OnSpinWait); + ins_cost(200); + + format %{ + $$template + if (os::is_MP()) { + $$emit$$"pause\t! membar_onspinwait" + } else { + $$emit$$"MEMBAR-onspinwait ! (empty encoding)" + } + %} + ins_encode %{ + __ pause(); + %} + ins_pipe(pipe_slow); +%} + instruct membar_volatile(rFlagsReg cr) %{ match(MemBarVolatile); effect(KILL cr); --- old/src/share/vm/classfile/vmSymbols.cpp 2016-01-25 21:56:18.000000000 +0300 +++ new/src/share/vm/classfile/vmSymbols.cpp 2016-01-25 21:56:18.000000000 +0300 @@ -355,6 +355,7 @@ case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: + case vmIntrinsics::_onSpinWait: return true; default: return false; @@ -386,6 +387,7 @@ case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: + case vmIntrinsics::_onSpinWait: return false; default: return true; @@ -681,6 +683,9 @@ case vmIntrinsics::_montgomerySquare: if (!UseMontgomerySquareIntrinsic) return true; break; + case vmIntrinsics::_onSpinWait: + if (!UseOnSpinWaitIntrinsic) return true; + break; case vmIntrinsics::_addExactI: case vmIntrinsics::_addExactL: case vmIntrinsics::_decrementExactI: --- old/src/share/vm/classfile/vmSymbols.hpp 2016-01-25 21:56:19.000000000 +0300 +++ new/src/share/vm/classfile/vmSymbols.hpp 2016-01-25 21:56:19.000000000 +0300 @@ -76,6 +76,7 @@ template(java_lang_Integer_IntegerCache, "java/lang/Integer$IntegerCache") \ template(java_lang_Long, "java/lang/Long") \ template(java_lang_Long_LongCache, "java/lang/Long$LongCache") \ + template(java_lang_Runtime, "java/lang/Runtime") \ template(java_lang_Shutdown, "java/lang/Shutdown") \ template(java_lang_ref_Reference, "java/lang/ref/Reference") \ template(java_lang_ref_SoftReference, "java/lang/ref/SoftReference") \ @@ -863,6 +864,10 @@ do_name( newArray_name, "newArray") \ do_signature(newArray_signature, "(Ljava/lang/Class;I)Ljava/lang/Object;") \ \ + do_intrinsic(_onSpinWait, java_lang_Runtime, onSpinWait_name, onSpinWait_signature, F_S) \ + do_name( onSpinWait_name, "onSpinWait") \ + do_alias( onSpinWait_signature, void_method_signature) \ + \ do_intrinsic(_copyOf, java_util_Arrays, copyOf_name, copyOf_signature, F_S) \ do_name( copyOf_name, "copyOf") \ do_signature(copyOf_signature, "([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object;") \ --- old/src/share/vm/opto/c2compiler.cpp 2016-01-25 21:56:19.000000000 +0300 +++ new/src/share/vm/opto/c2compiler.cpp 2016-01-25 21:56:19.000000000 +0300 @@ -399,6 +399,7 @@ case vmIntrinsics::_fullFence: case vmIntrinsics::_currentThread: case vmIntrinsics::_isInterrupted: + case vmIntrinsics::_onSpinWait: #ifdef TRACE_HAVE_INTRINSICS case vmIntrinsics::_classID: case vmIntrinsics::_threadID: --- old/src/share/vm/opto/classes.hpp 2016-01-25 21:56:20.000000000 +0300 +++ new/src/share/vm/opto/classes.hpp 2016-01-25 21:56:20.000000000 +0300 @@ -170,6 +170,7 @@ macro(Mach) macro(MachProj) macro(MaxI) +macro(OnSpinWait) macro(MemBarAcquire) macro(LoadFence) macro(MemBarAcquireLock) --- old/src/share/vm/opto/library_call.cpp 2016-01-25 21:56:20.000000000 +0300 +++ new/src/share/vm/opto/library_call.cpp 2016-01-25 21:56:20.000000000 +0300 @@ -279,6 +279,7 @@ bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind); bool inline_unsafe_ordered_store(BasicType type); bool inline_unsafe_fence(vmIntrinsics::ID id); + bool inline_onspinwait(); bool inline_fp_conversions(vmIntrinsics::ID id); bool inline_number_methods(vmIntrinsics::ID id); bool inline_reference_get(); @@ -634,6 +635,8 @@ case vmIntrinsics::_storeFence: case vmIntrinsics::_fullFence: return inline_unsafe_fence(intrinsic_id()); + case vmIntrinsics::_onSpinWait: return inline_onspinwait(); + case vmIntrinsics::_currentThread: return inline_native_currentThread(); case vmIntrinsics::_isInterrupted: return inline_native_isInterrupted(); @@ -3113,6 +3116,11 @@ } } +bool LibraryCallKit::inline_onspinwait() { + insert_mem_bar(Op_OnSpinWait); + return true; +} + bool LibraryCallKit::klass_needs_init_guard(Node* kls) { if (!kls->is_Con()) { return true; @@ -3495,6 +3503,9 @@ // nothing is an instance of a primitive type query_value = gen_instanceof(obj, kls, safe_for_replace); break; + + case vmIntrinsics::_onSpinWait: + break; case vmIntrinsics::_getModifiers: p = basic_plus_adr(kls, in_bytes(Klass::modifier_flags_offset())); --- old/src/share/vm/opto/matcher.cpp 2016-01-25 21:56:21.000000000 +0300 +++ new/src/share/vm/opto/matcher.cpp 2016-01-25 21:56:21.000000000 +0300 @@ -943,6 +943,7 @@ case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type? case Op_StrInflatedCopy: case Op_StrCompressedCopy: + case Op_OnSpinWait: case Op_EncodeISOArray: nidx = Compile::AliasIdxTop; nat = NULL; --- old/src/share/vm/opto/memnode.cpp 2016-01-25 21:56:22.000000000 +0300 +++ new/src/share/vm/opto/memnode.cpp 2016-01-25 21:56:21.000000000 +0300 @@ -2928,6 +2928,7 @@ case Op_MemBarReleaseLock: return new MemBarReleaseLockNode(C, atp, pn); case Op_MemBarVolatile: return new MemBarVolatileNode(C, atp, pn); case Op_MemBarCPUOrder: return new MemBarCPUOrderNode(C, atp, pn); + case Op_OnSpinWait: return new OnSpinWaitNode(C, atp, pn); case Op_Initialize: return new InitializeNode(C, atp, pn); case Op_MemBarStoreStore: return new MemBarStoreStoreNode(C, atp, pn); default: ShouldNotReachHere(); return NULL; --- old/src/share/vm/opto/memnode.hpp 2016-01-25 21:56:22.000000000 +0300 +++ new/src/share/vm/opto/memnode.hpp 2016-01-25 21:56:22.000000000 +0300 @@ -1086,6 +1086,13 @@ virtual uint ideal_reg() const { return 0; } // not matched in the AD file }; +class OnSpinWaitNode: public MemBarNode { +public: + OnSpinWaitNode(Compile* C, int alias_idx, Node* precedent) + : MemBarNode(C, alias_idx, precedent) {} + virtual int Opcode() const; +}; + // Isolation of object setup after an AllocateNode and before next safepoint. // (See comment in memnode.cpp near InitializeNode::InitializeNode for semantics.) class InitializeNode: public MemBarNode { --- old/src/share/vm/runtime/globals.hpp 2016-01-25 21:56:23.000000000 +0300 +++ new/src/share/vm/runtime/globals.hpp 2016-01-25 21:56:23.000000000 +0300 @@ -860,6 +860,9 @@ diagnostic(ccstrlist, DisableIntrinsic, "", \ "do not expand intrinsics whose (internal) names appear here") \ \ + product(bool, UseOnSpinWaitIntrinsic, false, \ + "Use intrinsic for onSpinWait") \ + \ develop(bool, TraceCallFixup, false, \ "Trace all call fixups") \ \ --- old/src/share/vm/runtime/vmStructs.cpp 2016-01-25 21:56:24.000000000 +0300 +++ new/src/share/vm/runtime/vmStructs.cpp 2016-01-25 21:56:24.000000000 +0300 @@ -1922,6 +1922,7 @@ declare_c2_type(StoreFenceNode, MemBarNode) \ declare_c2_type(MemBarVolatileNode, MemBarNode) \ declare_c2_type(MemBarCPUOrderNode, MemBarNode) \ + declare_c2_type(OnSpinWaitNode, MemBarNode) \ declare_c2_type(InitializeNode, MemBarNode) \ declare_c2_type(ThreadLocalNode, Node) \ declare_c2_type(Opaque1Node, Node) \ --- /dev/null 2016-01-25 21:56:25.000000000 +0300 +++ new/test/compiler/onSpinWait/TestOnSpinWait.java 2016-01-25 21:56:25.000000000 +0300 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright 2016 Azul Systems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test TestOnSpinWait + * @summary C2: (x86 only) checks that java.lang.Runtime.onSpinWait is intrinsified + * @bug 8147844 + * @library /testlibrary + * @requires os.arch=="x86" | os.arch=="amd64" | os.arch=="x86_64" + * @run main/othervm TestOnSpinWait + */ + +import java.lang.invoke.*; +import jdk.test.lib.*; +import static jdk.test.lib.Asserts.*; + +public class TestOnSpinWait { + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", "-showversion", + "-server", "-XX:-TieredCompilation", "-Xbatch", + "-XX:+UseOnSpinWaitIntrinsic", "-Xcomp", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", + "-XX:+PrintInlining", "TestOnSpinWait$Launcher"); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + // The test is applicable only to C2 (present in Server VM). + if (analyzer.getStderr().contains("Server VM")) { + analyzer.shouldContain("java.lang.Runtime::onSpinWait (1 bytes) (intrinsic)"); + } + } + + static class Launcher { + + public static void main(final String[] args) throws Exception { + int end = 20_000; + + for (int i=0; i < end; i++) { + java.lang.Runtime.onSpinWait(); + } + } + } +}