8155635: C2: Mixed unsafe accesses break alias analysis

Mon, 22 Oct 2018 05:26:38 -0400

author
dbuck
date
Mon, 22 Oct 2018 05:26:38 -0400
changeset 9512
992120803410
parent 9511
e33aa14a0d8b
child 9513
e044997c2eda
child 9516
359ded4897e9

8155635: C2: Mixed unsafe accesses break alias analysis
Reviewed-by: kvn

src/share/vm/opto/compile.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/library_call.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/type.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/type.hpp file | annotate | diff | comparison | revisions
test/compiler/unsafe/MixedUnsafeStoreObject.java file | annotate | diff | comparison | revisions
     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 +

mercurial