mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-24 04:54:40 +02:00
8142386: Octane crashes with assert(is_Load())
Unsafe access to an array is wrongly marked as mismatched Reviewed-by: vlivanov, thartmann
This commit is contained in:
parent
1d58a73e8c
commit
c18a26c573
5 changed files with 128 additions and 33 deletions
|
@ -1468,17 +1468,11 @@ Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
|
||||||
Node* mem = memory(adr_idx);
|
Node* mem = memory(adr_idx);
|
||||||
Node* ld;
|
Node* ld;
|
||||||
if (require_atomic_access && bt == T_LONG) {
|
if (require_atomic_access && bt == T_LONG) {
|
||||||
ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency);
|
ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency, unaligned, mismatched);
|
||||||
} else if (require_atomic_access && bt == T_DOUBLE) {
|
} else if (require_atomic_access && bt == T_DOUBLE) {
|
||||||
ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency);
|
ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency, unaligned, mismatched);
|
||||||
} else {
|
} else {
|
||||||
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency);
|
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency, unaligned, mismatched);
|
||||||
}
|
|
||||||
if (unaligned) {
|
|
||||||
ld->as_Load()->set_unaligned_access();
|
|
||||||
}
|
|
||||||
if (mismatched) {
|
|
||||||
ld->as_Load()->set_mismatched_access();
|
|
||||||
}
|
}
|
||||||
ld = _gvn.transform(ld);
|
ld = _gvn.transform(ld);
|
||||||
if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) {
|
if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) {
|
||||||
|
|
|
@ -2588,6 +2588,10 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
|
||||||
} else {
|
} else {
|
||||||
bt = alias_type->field()->type()->basic_type();
|
bt = alias_type->field()->type()->basic_type();
|
||||||
}
|
}
|
||||||
|
if (bt == T_ARRAY) {
|
||||||
|
// accessing an array field with getObject is not a mismatch
|
||||||
|
bt = T_OBJECT;
|
||||||
|
}
|
||||||
if (bt != type) {
|
if (bt != type) {
|
||||||
mismatched = true;
|
mismatched = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -761,7 +761,8 @@ bool LoadNode::is_immutable_value(Node* adr) {
|
||||||
|
|
||||||
//----------------------------LoadNode::make-----------------------------------
|
//----------------------------LoadNode::make-----------------------------------
|
||||||
// Polymorphic factory method:
|
// Polymorphic factory method:
|
||||||
Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo, ControlDependency control_dependency) {
|
Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo,
|
||||||
|
ControlDependency control_dependency, bool unaligned, bool mismatched) {
|
||||||
Compile* C = gvn.C;
|
Compile* C = gvn.C;
|
||||||
|
|
||||||
// sanity check the alias category against the created node type
|
// sanity check the alias category against the created node type
|
||||||
|
@ -776,40 +777,68 @@ Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypeP
|
||||||
// oop will be recorded in oop map if load crosses safepoint
|
// oop will be recorded in oop map if load crosses safepoint
|
||||||
rt->isa_oopptr() || is_immutable_value(adr),
|
rt->isa_oopptr() || is_immutable_value(adr),
|
||||||
"raw memory operations should have control edge");
|
"raw memory operations should have control edge");
|
||||||
|
LoadNode* load = NULL;
|
||||||
switch (bt) {
|
switch (bt) {
|
||||||
case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
case T_BOOLEAN: load = new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); break;
|
||||||
case T_BYTE: return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
case T_BYTE: load = new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); break;
|
||||||
case T_INT: return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
case T_INT: load = new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); break;
|
||||||
case T_CHAR: return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
case T_CHAR: load = new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); break;
|
||||||
case T_SHORT: return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
case T_SHORT: load = new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); break;
|
||||||
case T_LONG: return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency);
|
case T_LONG: load = new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency); break;
|
||||||
case T_FLOAT: return new LoadFNode (ctl, mem, adr, adr_type, rt, mo, control_dependency);
|
case T_FLOAT: load = new LoadFNode (ctl, mem, adr, adr_type, rt, mo, control_dependency); break;
|
||||||
case T_DOUBLE: return new LoadDNode (ctl, mem, adr, adr_type, rt, mo, control_dependency);
|
case T_DOUBLE: load = new LoadDNode (ctl, mem, adr, adr_type, rt, mo, control_dependency); break;
|
||||||
case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo, control_dependency);
|
case T_ADDRESS: load = new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo, control_dependency); break;
|
||||||
case T_OBJECT:
|
case T_OBJECT:
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
|
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
|
||||||
Node* load = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo, control_dependency));
|
load = new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo, control_dependency);
|
||||||
return new DecodeNNode(load, load->bottom_type()->make_ptr());
|
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop");
|
assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop");
|
||||||
return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo, control_dependency);
|
load = new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo, control_dependency);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
ShouldNotReachHere();
|
assert(load != NULL, "LoadNode should have been created");
|
||||||
return (LoadNode*)NULL;
|
if (unaligned) {
|
||||||
|
load->set_unaligned_access();
|
||||||
|
}
|
||||||
|
if (mismatched) {
|
||||||
|
load->set_mismatched_access();
|
||||||
|
}
|
||||||
|
if (load->Opcode() == Op_LoadN) {
|
||||||
|
Node* ld = gvn.transform(load);
|
||||||
|
return new DecodeNNode(ld, ld->bottom_type()->make_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
return load;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) {
|
LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo,
|
||||||
|
ControlDependency control_dependency, bool unaligned, bool mismatched) {
|
||||||
bool require_atomic = true;
|
bool require_atomic = true;
|
||||||
return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency, require_atomic);
|
LoadLNode* load = new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency, require_atomic);
|
||||||
|
if (unaligned) {
|
||||||
|
load->set_unaligned_access();
|
||||||
|
}
|
||||||
|
if (mismatched) {
|
||||||
|
load->set_mismatched_access();
|
||||||
|
}
|
||||||
|
return load;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) {
|
LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo,
|
||||||
|
ControlDependency control_dependency, bool unaligned, bool mismatched) {
|
||||||
bool require_atomic = true;
|
bool require_atomic = true;
|
||||||
return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, control_dependency, require_atomic);
|
LoadDNode* load = new LoadDNode(ctl, mem, adr, adr_type, rt, mo, control_dependency, require_atomic);
|
||||||
|
if (unaligned) {
|
||||||
|
load->set_unaligned_access();
|
||||||
|
}
|
||||||
|
if (mismatched) {
|
||||||
|
load->set_mismatched_access();
|
||||||
|
}
|
||||||
|
return load;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -198,9 +198,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Polymorphic factory method:
|
// Polymorphic factory method:
|
||||||
static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr,
|
static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr,
|
||||||
const TypePtr* at, const Type *rt, BasicType bt,
|
const TypePtr* at, const Type *rt, BasicType bt,
|
||||||
MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
|
MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest,
|
||||||
|
bool unaligned = false, bool mismatched = false);
|
||||||
|
|
||||||
virtual uint hash() const; // Check the type
|
virtual uint hash() const; // Check the type
|
||||||
|
|
||||||
|
@ -375,7 +376,8 @@ public:
|
||||||
virtual BasicType memory_type() const { return T_LONG; }
|
virtual BasicType memory_type() const { return T_LONG; }
|
||||||
bool require_atomic_access() const { return _require_atomic_access; }
|
bool require_atomic_access() const { return _require_atomic_access; }
|
||||||
static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
|
static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
|
||||||
const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
|
const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest,
|
||||||
|
bool unaligned = false, bool mismatched = false);
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
virtual void dump_spec(outputStream *st) const {
|
virtual void dump_spec(outputStream *st) const {
|
||||||
LoadNode::dump_spec(st);
|
LoadNode::dump_spec(st);
|
||||||
|
@ -426,7 +428,8 @@ public:
|
||||||
virtual BasicType memory_type() const { return T_DOUBLE; }
|
virtual BasicType memory_type() const { return T_DOUBLE; }
|
||||||
bool require_atomic_access() const { return _require_atomic_access; }
|
bool require_atomic_access() const { return _require_atomic_access; }
|
||||||
static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
|
static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
|
||||||
const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
|
const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest,
|
||||||
|
bool unaligned = false, bool mismatched = false);
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
virtual void dump_spec(outputStream *st) const {
|
virtual void dump_spec(outputStream *st) const {
|
||||||
LoadNode::dump_spec(st);
|
LoadNode::dump_spec(st);
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, 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 8142386
|
||||||
|
* @library /testlibrary /test/lib
|
||||||
|
* @summary Unsafe access to an array is wrongly marked as mismatched
|
||||||
|
* @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:-TieredCompilation TestUnsafeMismatchedArrayFieldAccess
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import jdk.test.lib.Utils;
|
||||||
|
import sun.misc.Unsafe;
|
||||||
|
|
||||||
|
public class TestUnsafeMismatchedArrayFieldAccess {
|
||||||
|
|
||||||
|
private static final Unsafe UNSAFE = Utils.getUnsafe();
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
array_offset = UNSAFE.objectFieldOffset(TestUnsafeMismatchedArrayFieldAccess.class.getDeclaredField("array"));
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] array;
|
||||||
|
static final long array_offset;
|
||||||
|
|
||||||
|
void m() {
|
||||||
|
UNSAFE.getObject(this, array_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void main(String[] args) {
|
||||||
|
TestUnsafeMismatchedArrayFieldAccess test = new TestUnsafeMismatchedArrayFieldAccess();
|
||||||
|
|
||||||
|
for (int i = 0; i < 20000; i++) {
|
||||||
|
test.m();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue