提交 983d3b71 编写于 作者: S shshahma

8134918: C2: Type speculation produces mismatched unsafe accesses

Reviewed-by: kvn, thartmann
上级 7ef1f50d
......@@ -1595,6 +1595,17 @@ void Compile::AliasType::Init(int i, const TypePtr* at) {
}
}
BasicType Compile::AliasType::basic_type() const {
if (element() != NULL) {
const Type* element = adr_type()->is_aryptr()->elem();
return element->isa_narrowoop() ? T_OBJECT : element->array_element_basic_type();
} if (field() != NULL) {
return field()->layout_type();
} else {
return T_ILLEGAL; // unknown
}
}
//---------------------------------print_on------------------------------------
#ifndef PRODUCT
void Compile::AliasType::print_on(outputStream* st) {
......
......@@ -152,6 +152,8 @@ class Compile : public Phase {
_element = e;
}
BasicType basic_type() const;
void print_on(outputStream* st) PRODUCT_RETURN;
};
......
......@@ -2556,6 +2556,7 @@ const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_
bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile, bool unaligned) {
if (callee()->is_static()) return false; // caller must have the capability!
assert(type != T_OBJECT || !unaligned, "unaligned access not supported with object type");
#ifndef PRODUCT
{
......@@ -2631,14 +2632,35 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
const TypePtr *adr_type = _gvn.type(adr)->isa_ptr();
// First guess at the value type.
const Type *value_type = Type::get_const_basic_type(type);
// Try to categorize the address. If it comes up as TypeJavaPtr::BOTTOM,
// there was not enough information to nail it down.
Compile::AliasType* alias_type = C->alias_type(adr_type);
assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here");
assert(alias_type->adr_type() == TypeRawPtr::BOTTOM || alias_type->adr_type() == TypeOopPtr::BOTTOM ||
alias_type->basic_type() != T_ILLEGAL, "field, array element or unknown");
bool mismatched = false;
BasicType bt = alias_type->basic_type();
if (bt != T_ILLEGAL) {
if (bt == T_BYTE && adr_type->isa_aryptr()) {
// Alias type doesn't differentiate between byte[] and boolean[]).
// Use address type to get the element type.
bt = adr_type->is_aryptr()->elem()->array_element_basic_type();
}
if (bt == T_ARRAY || bt == T_NARROWOOP) {
// accessing an array field with getObject is not a mismatch
bt = T_OBJECT;
}
if ((bt == T_OBJECT) != (type == T_OBJECT)) {
// Don't intrinsify mismatched object accesses
return false;
}
mismatched = (bt != type);
}
// First guess at the value type.
const Type *value_type = Type::get_const_basic_type(type);
// We will need memory barriers unless we can determine a unique
// alias category for this reference. (Note: If for some reason
// the barriers get omitted and the unsafe reference begins to "pollute"
......@@ -2697,23 +2719,6 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
// around 5701, class sun/reflect/UnsafeBooleanFieldAccessorImpl.
if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder);
assert(alias_type->adr_type() == TypeRawPtr::BOTTOM || alias_type->adr_type() == TypeOopPtr::BOTTOM ||
alias_type->field() != NULL || alias_type->element() != NULL, "field, array element or unknown");
bool mismatched = false;
if (alias_type->element() != NULL || alias_type->field() != NULL) {
BasicType bt;
if (alias_type->element() != NULL) {
const Type* element = alias_type->element();
bt = element->isa_narrowoop() ? T_OBJECT : element->array_element_basic_type();
} else {
bt = alias_type->field()->type()->basic_type();
}
if (bt != type) {
mismatched = true;
}
}
assert(type != T_OBJECT || !unaligned, "unaligned access not supported with object type");
if (!is_store) {
MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered;
// To be valid, unsafe loads may depend on other conditions than
......@@ -2972,11 +2977,20 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
Node* adr = make_unsafe_address(base, offset);
const TypePtr *adr_type = _gvn.type(adr)->isa_ptr();
Compile::AliasType* alias_type = C->alias_type(adr_type);
assert(alias_type->adr_type() == TypeRawPtr::BOTTOM || alias_type->adr_type() == TypeOopPtr::BOTTOM ||
alias_type->basic_type() != T_ILLEGAL, "field, array element or unknown");
BasicType bt = alias_type->basic_type();
if (bt != T_ILLEGAL &&
((bt == T_OBJECT || bt == T_ARRAY) != (type == T_OBJECT))) {
// Don't intrinsify mismatched object accesses.
return false;
}
// For CAS, unlike inline_unsafe_access, there seems no point in
// trying to refine types. Just use the coarse types here.
const Type *value_type = Type::get_const_basic_type(type);
Compile::AliasType* alias_type = C->alias_type(adr_type);
assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here");
const Type *value_type = Type::get_const_basic_type(type);
if (kind == LS_xchg && type == T_OBJECT) {
const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type);
......
/*
* Copyright (c) 2016, Oracle and/or its affiliates. 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
* @bug 8134918
* @modules java.base/jdk.internal.misc
* @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation -Xbatch
* -XX:CompileCommand=dontinline,UnsafeAccess::test*
* UnsafeAccess
*/
import sun.misc.Unsafe;
public class UnsafeAccess {
private static final Unsafe U = Unsafe.getUnsafe();
static Class cls = Object.class;
static long off = U.ARRAY_OBJECT_BASE_OFFSET;
static Object testUnsafeAccess(Object o, boolean isObjArray) {
if (o != null && cls.isInstance(o)) { // speculates "o" type to int[]
return helperUnsafeAccess(o, isObjArray);
}
return null;
}
static Object helperUnsafeAccess(Object o, boolean isObjArray) {
if (isObjArray) {
U.putObject(o, off, new Object());
}
return o;
}
static Object testUnsafeLoadStore(Object o, boolean isObjArray) {
if (o != null && cls.isInstance(o)) { // speculates "o" type to int[]
return helperUnsafeLoadStore(o, isObjArray);
}
return null;
}
static Object helperUnsafeLoadStore(Object o, boolean isObjArray) {
if (isObjArray) {
Object o1 = U.getObject(o, off);
U.compareAndSwapObject(o, off, o1, new Object());
}
return o;
}
public static void main(String[] args) {
Object[] objArray = new Object[10];
int[] intArray = new int[10];
for (int i = 0; i < 20_000; i++) {
helperUnsafeAccess(objArray, true);
}
for (int i = 0; i < 20_000; i++) {
testUnsafeAccess(intArray, false);
}
for (int i = 0; i < 20_000; i++) {
helperUnsafeLoadStore(objArray, true);
}
for (int i = 0; i < 20_000; i++) {
testUnsafeLoadStore(intArray, false);
}
System.out.println("TEST PASSED");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册