Mon, 22 Oct 2018 05:26:38 -0400
8155635: C2: Mixed unsafe accesses break alias analysis
Reviewed-by: kvn
1.1 --- a/src/share/vm/opto/compile.cpp Mon Oct 22 02:50:45 2018 -0400 1.2 +++ b/src/share/vm/opto/compile.cpp Mon Oct 22 05:26:38 2018 -0400 1.3 @@ -1680,16 +1680,23 @@ 1.4 const TypePtr* flat = flatten_alias_type(adr_type); 1.5 1.6 #ifdef ASSERT 1.7 - assert(flat == flatten_alias_type(flat), "idempotent"); 1.8 - assert(flat != TypePtr::BOTTOM, "cannot alias-analyze an untyped ptr"); 1.9 - if (flat->isa_oopptr() && !flat->isa_klassptr()) { 1.10 - const TypeOopPtr* foop = flat->is_oopptr(); 1.11 - // Scalarizable allocations have exact klass always. 1.12 - bool exact = !foop->klass_is_exact() || foop->is_known_instance(); 1.13 - const TypePtr* xoop = foop->cast_to_exactness(exact)->is_ptr(); 1.14 - assert(foop == flatten_alias_type(xoop), "exactness must not affect alias type"); 1.15 + { 1.16 + ResourceMark rm; 1.17 + assert(flat == flatten_alias_type(flat), 1.18 + err_msg("not idempotent: adr_type = %s; flat = %s => %s", Type::str(adr_type), 1.19 + Type::str(flat), Type::str(flatten_alias_type(flat)))); 1.20 + assert(flat != TypePtr::BOTTOM, 1.21 + err_msg("cannot alias-analyze an untyped ptr: adr_type = %s", Type::str(adr_type))); 1.22 + if (flat->isa_oopptr() && !flat->isa_klassptr()) { 1.23 + const TypeOopPtr* foop = flat->is_oopptr(); 1.24 + // Scalarizable allocations have exact klass always. 1.25 + bool exact = !foop->klass_is_exact() || foop->is_known_instance(); 1.26 + const TypePtr* xoop = foop->cast_to_exactness(exact)->is_ptr(); 1.27 + assert(foop == flatten_alias_type(xoop), 1.28 + err_msg("exactness must not affect alias type: foop = %s; xoop = %s", 1.29 + Type::str(foop), Type::str(xoop))); 1.30 + } 1.31 } 1.32 - assert(flat == flatten_alias_type(flat), "exact bit doesn't matter"); 1.33 #endif 1.34 1.35 int idx = AliasIdxTop;
2.1 --- a/src/share/vm/opto/library_call.cpp Mon Oct 22 02:50:45 2018 -0400 2.2 +++ b/src/share/vm/opto/library_call.cpp Mon Oct 22 05:26:38 2018 -0400 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -2544,8 +2544,8 @@ 2.11 2.12 #ifndef PRODUCT 2.13 if (C->print_intrinsics() || C->print_inlining()) { 2.14 - tty->print(" from base type: "); adr_type->dump(); 2.15 - tty->print(" sharpened value: "); tjp->dump(); 2.16 + tty->print(" from base type: "); adr_type->dump(); tty->cr(); 2.17 + tty->print(" sharpened value: "); tjp->dump(); tty->cr(); 2.18 } 2.19 #endif 2.20 // Sharpen the value type. 2.21 @@ -2632,6 +2632,9 @@ 2.22 2.23 // Can base be NULL? Otherwise, always on-heap access. 2.24 bool can_access_non_heap = TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop)); 2.25 + if (can_access_non_heap && type == T_OBJECT) { 2.26 + return false; // off-heap oop accesses are not supported 2.27 + } 2.28 2.29 const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); 2.30 2.31 @@ -2776,34 +2779,10 @@ 2.32 } 2.33 2.34 MemNode::MemOrd mo = is_volatile ? MemNode::release : MemNode::unordered; 2.35 - if (type != T_OBJECT ) { 2.36 + if (type == T_OBJECT ) { 2.37 + (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo, mismatched); 2.38 + } else { 2.39 (void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile, unaligned, mismatched); 2.40 - } else { 2.41 - // Possibly an oop being stored to Java heap or native memory 2.42 - if (!can_access_non_heap) { 2.43 - // oop to Java heap. 2.44 - (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo, mismatched); 2.45 - } else { 2.46 - // We can't tell at compile time if we are storing in the Java heap or outside 2.47 - // of it. So we need to emit code to conditionally do the proper type of 2.48 - // store. 2.49 - 2.50 - IdealKit ideal(this); 2.51 -#define __ ideal. 2.52 - // QQQ who knows what probability is here?? 2.53 - __ if_then(heap_base_oop, BoolTest::ne, null(), PROB_UNLIKELY(0.999)); { 2.54 - // Sync IdealKit and graphKit. 2.55 - sync_kit(ideal); 2.56 - Node* st = store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo, mismatched); 2.57 - // Update IdealKit memory. 2.58 - __ sync_kit(this); 2.59 - } __ else_(); { 2.60 - __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, is_volatile, mismatched); 2.61 - } __ end_if(); 2.62 - // Final sync IdealKit and GraphKit. 2.63 - final_sync(ideal); 2.64 -#undef __ 2.65 - } 2.66 } 2.67 } 2.68
3.1 --- a/src/share/vm/opto/type.cpp Mon Oct 22 02:50:45 2018 -0400 3.2 +++ b/src/share/vm/opto/type.cpp Mon Oct 22 05:26:38 2018 -0400 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -885,6 +885,13 @@ 3.11 st->print(" [narrowklass]"); 3.12 } 3.13 } 3.14 + 3.15 +//----------------------------------------------------------------------------- 3.16 +const char* Type::str(const Type* t) { 3.17 + stringStream ss; 3.18 + t->dump_on(&ss); 3.19 + return ss.as_string(); 3.20 +} 3.21 #endif 3.22 3.23 //------------------------------singleton--------------------------------------
4.1 --- a/src/share/vm/opto/type.hpp Mon Oct 22 02:50:45 2018 -0400 4.2 +++ b/src/share/vm/opto/type.hpp Mon Oct 22 05:26:38 2018 -0400 4.3 @@ -358,6 +358,8 @@ 4.4 } 4.5 virtual void dump2( Dict &d, uint depth, outputStream *st ) const; 4.6 static void dump_stats(); 4.7 + 4.8 + static const char* str(const Type* t); 4.9 #endif 4.10 void typerr(const Type *t) const; // Mixing types error 4.11
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/compiler/unsafe/MixedUnsafeStoreObject.java Mon Oct 22 05:26:38 2018 -0400 5.3 @@ -0,0 +1,76 @@ 5.4 +/* 5.5 + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +/* 5.28 + * @test 5.29 + * @bug 8155635 5.30 + * @library /testlibrary 5.31 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:-TieredCompilation compiler.unsafe.MixedUnsafeStoreObject 5.32 + * @run main/othervm -Xbatch compiler.unsafe.MixedUnsafeStoreObject 5.33 + * @comment Testcase currently only known to reproduce when run with -XX:+UseG1GC. 5.34 + */ 5.35 + 5.36 +package compiler.unsafe; 5.37 + 5.38 +import sun.misc.Unsafe; 5.39 + 5.40 +import com.oracle.java.testlibrary.Utils; 5.41 + 5.42 +public class MixedUnsafeStoreObject { 5.43 + static final Unsafe UNSAFE = Utils.getUnsafe(); 5.44 + 5.45 + static final long F_OFFSET; 5.46 + 5.47 + static { 5.48 + try { 5.49 + F_OFFSET = UNSAFE.objectFieldOffset(T.class.getDeclaredField("f")); 5.50 + } catch (Exception e) { 5.51 + throw new Error(e); 5.52 + } 5.53 + } 5.54 + 5.55 + static class T { 5.56 + Object f; 5.57 + } 5.58 + 5.59 + public static void testFieldInstanceObject(Object t) { 5.60 + for (int c = 0; c < 20000; c++) { // trigger OSR compilation 5.61 + // java/lang/Object+12 * 5.62 + // _base = InstPtr, _ptr = BotPTR, _field = NULL, mismatched = true 5.63 + UNSAFE.putObject(t, F_OFFSET, "foo"); 5.64 + } 5.65 + } 5.66 + 5.67 + public static void testFieldInstanceT(T t) { 5.68 + for (int c = 0; c < 20000; c++) { // trigger OSR compilation 5.69 + // ...$T+12 * 5.70 + // _base = InstPtr, _ptr = BotPTR, _field = T.f, mismatched = false 5.71 + UNSAFE.putObject(t, F_OFFSET, "foo"); 5.72 + } 5.73 + } 5.74 + public static void main(String[] args) { 5.75 + testFieldInstanceObject(new T()); 5.76 + testFieldInstanceT(new T()); 5.77 + } 5.78 +} 5.79 +