Thu, 10 Aug 2017 12:08:50 +0530
8184271: Time related C1 intrinsics produce inconsistent results when floating around
Summary: C1 intrinsics for System.nanoTime(), System.currentTimeMillis() and JVM.counterTime() should be pinned.
Reviewed-by: kvn, vlivanov, iveresov
1.1 --- a/src/share/vm/c1/c1_Instruction.hpp Thu Aug 03 08:07:17 2017 -0700 1.2 +++ b/src/share/vm/c1/c1_Instruction.hpp Thu Aug 10 12:08:50 2017 +0530 1.3 @@ -1568,7 +1568,7 @@ 1.4 set_needs_null_check(has_receiver); 1.5 1.6 // some intrinsics can't trap, so don't force them to be pinned 1.7 - if (!can_trap()) { 1.8 + if (!can_trap() && !vmIntrinsics::should_be_pinned(_id)) { 1.9 unpin(PinStateSplitConstructor); 1.10 } 1.11 }
2.1 --- a/src/share/vm/classfile/vmSymbols.cpp Thu Aug 03 08:07:17 2017 -0700 2.2 +++ b/src/share/vm/classfile/vmSymbols.cpp Thu Aug 10 12:08:50 2017 +0530 2.3 @@ -324,6 +324,20 @@ 2.4 return vmIntrinsics::_none; 2.5 } 2.6 2.7 +// Some intrinsics produce different results if they are not pinned 2.8 +bool vmIntrinsics::should_be_pinned(vmIntrinsics::ID id) { 2.9 + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); 2.10 + switch(id) { 2.11 +#ifdef TRACE_HAVE_INTRINSICS 2.12 + case vmIntrinsics::_counterTime: 2.13 +#endif 2.14 + case vmIntrinsics::_currentTimeMillis: 2.15 + case vmIntrinsics::_nanoTime: 2.16 + return true; 2.17 + default: 2.18 + return false; 2.19 + } 2.20 +} 2.21 2.22 #define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0" 2.23 static const char* vm_intrinsic_name_bodies =
3.1 --- a/src/share/vm/classfile/vmSymbols.hpp Thu Aug 03 08:07:17 2017 -0700 3.2 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Aug 10 12:08:50 2017 +0530 3.3 @@ -1301,6 +1301,8 @@ 3.4 3.5 // Raw conversion: 3.6 static ID for_raw_conversion(BasicType src, BasicType dest); 3.7 + 3.8 + static bool should_be_pinned(vmIntrinsics::ID id); 3.9 }; 3.10 3.11 #endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/compiler/c1/TestPinnedIntrinsics.java Thu Aug 10 12:08:50 2017 +0530 4.3 @@ -0,0 +1,68 @@ 4.4 +/* 4.5 + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 + 4.27 +/* 4.28 + * @test 4.29 + * @bug 8184271 4.30 + * @summary Test correct scheduling of System.nanoTime and System.currentTimeMillis C1 intrinsics. 4.31 + * @run main/othervm -XX:TieredStopAtLevel=1 -Xbatch 4.32 + * -XX:CompileCommand=dontinline,compiler.c1.TestPinnedIntrinsics::checkNanoTime 4.33 + * -XX:CompileCommand=dontinline,compiler.c1.TestPinnedIntrinsics::checkCurrentTimeMillis 4.34 + * compiler.c1.TestPinnedIntrinsics 4.35 + */ 4.36 + 4.37 +package compiler.c1; 4.38 + 4.39 +public class TestPinnedIntrinsics { 4.40 + 4.41 + private static void testNanoTime() { 4.42 + long start = System.nanoTime(); 4.43 + long end = System.nanoTime(); 4.44 + checkNanoTime(end - start); 4.45 + } 4.46 + 4.47 + private static void checkNanoTime(long diff) { 4.48 + if (diff < 0) { 4.49 + throw new RuntimeException("testNanoTime failed with " + diff); 4.50 + } 4.51 + } 4.52 + 4.53 + private static void testCurrentTimeMillis() { 4.54 + long start = System.currentTimeMillis(); 4.55 + long end = System.currentTimeMillis(); 4.56 + checkCurrentTimeMillis(end - start); 4.57 + } 4.58 + 4.59 + private static void checkCurrentTimeMillis(long diff) { 4.60 + if (diff < 0) { 4.61 + throw new RuntimeException("testCurrentTimeMillis failed with " + diff); 4.62 + } 4.63 + } 4.64 + 4.65 + public static void main(String[] args) { 4.66 + for (int i = 0; i < 100_000; ++i) { 4.67 + testNanoTime(); 4.68 + testCurrentTimeMillis(); 4.69 + } 4.70 + } 4.71 +}