8055910: closed/java/util/Collections/CheckedCollections.java failed with ClassCastException not thrown
Missing subtype check for Arrays.copyOf intrinsic Reviewed-by: kvn, iveresov
This commit is contained in:
parent
b9e949183d
commit
fa27000f3c
@ -1830,8 +1830,8 @@ ArrayCopyNode* ArrayCopyNode::make(GraphKit* kit, bool may_throw,
|
||||
Node* dest, Node* dest_offset,
|
||||
Node* length,
|
||||
bool alloc_tightly_coupled,
|
||||
Node* src_length, Node* dest_length,
|
||||
Node* src_klass, Node* dest_klass) {
|
||||
Node* src_klass, Node* dest_klass,
|
||||
Node* src_length, Node* dest_length) {
|
||||
|
||||
ArrayCopyNode* ac = new ArrayCopyNode(kit->C, alloc_tightly_coupled);
|
||||
Node* prev_mem = kit->set_predefined_input_for_runtime_call(ac);
|
||||
|
@ -1138,8 +1138,8 @@ public:
|
||||
Node* dest, Node* dest_offset,
|
||||
Node* length,
|
||||
bool alloc_tightly_coupled,
|
||||
Node* src_length = NULL, Node* dest_length = NULL,
|
||||
Node* src_klass = NULL, Node* dest_klass = NULL);
|
||||
Node* src_klass = NULL, Node* dest_klass = NULL,
|
||||
Node* src_length = NULL, Node* dest_length = NULL);
|
||||
|
||||
void connect_outputs(GraphKit* kit);
|
||||
|
||||
|
@ -3871,7 +3871,7 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) {
|
||||
Node* orig_tail = _gvn.transform(new SubINode(orig_length, start));
|
||||
Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length);
|
||||
|
||||
newcopy = new_array(klass_node, length, 0); // no argments to push
|
||||
newcopy = new_array(klass_node, length, 0); // no arguments to push
|
||||
|
||||
// Generate a direct call to the right arraycopy function(s).
|
||||
// We know the copy is disjoint but we might not know if the
|
||||
@ -3881,7 +3881,8 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) {
|
||||
|
||||
Node* alloc = tightly_coupled_allocation(newcopy, NULL);
|
||||
|
||||
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, alloc != NULL);
|
||||
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, alloc != NULL,
|
||||
load_object_klass(original), klass_node);
|
||||
if (!is_copyOfRange) {
|
||||
ac->set_copyof();
|
||||
} else {
|
||||
@ -4804,8 +4805,8 @@ bool LibraryCallKit::inline_arraycopy() {
|
||||
// Create LoadRange and LoadKlass nodes for use during macro expansion here
|
||||
// so the compiler has a chance to eliminate them: during macro expansion,
|
||||
// we have to set their control (CastPP nodes are eliminated).
|
||||
load_array_length(src), load_array_length(dest),
|
||||
load_object_klass(src), load_object_klass(dest));
|
||||
load_object_klass(src), load_object_klass(dest),
|
||||
load_array_length(src), load_array_length(dest));
|
||||
|
||||
if (notest) {
|
||||
ac->set_arraycopy_notest();
|
||||
|
@ -506,6 +506,8 @@ Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode*
|
||||
Node* src_klass = ac->in(ArrayCopyNode::SrcKlass);
|
||||
Node* dest_klass = ac->in(ArrayCopyNode::DestKlass);
|
||||
|
||||
assert(src_klass != NULL && dest_klass != NULL, "should have klasses");
|
||||
|
||||
// Generate the subtype check.
|
||||
// This might fold up statically, or then again it might not.
|
||||
//
|
||||
@ -1209,6 +1211,7 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) {
|
||||
|
||||
// (7) src_offset + length must not exceed length of src.
|
||||
Node* alen = ac->in(ArrayCopyNode::SrcLen);
|
||||
assert(alen != NULL, "need src len");
|
||||
generate_limit_guard(&ctrl,
|
||||
src_offset, length,
|
||||
alen,
|
||||
@ -1216,6 +1219,7 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) {
|
||||
|
||||
// (8) dest_offset + length must not exceed length of dest.
|
||||
alen = ac->in(ArrayCopyNode::DestLen);
|
||||
assert(alen != NULL, "need dest len");
|
||||
generate_limit_guard(&ctrl,
|
||||
dest_offset, length,
|
||||
alen,
|
||||
|
@ -2799,9 +2799,10 @@ bool ClearArrayNode::step_through(Node** np, uint instance_id, PhaseTransform* p
|
||||
assert(n->is_ClearArray(), "sanity");
|
||||
intptr_t offset;
|
||||
AllocateNode* alloc = AllocateNode::Ideal_allocation(n->in(3), phase, offset);
|
||||
// This method is called only before Allocate nodes are expanded during
|
||||
// macro nodes expansion. Before that ClearArray nodes are only generated
|
||||
// in LibraryCallKit::generate_arraycopy() which follows allocations.
|
||||
// This method is called only before Allocate nodes are expanded
|
||||
// during macro nodes expansion. Before that ClearArray nodes are
|
||||
// only generated in PhaseMacroExpand::generate_arraycopy() (before
|
||||
// Allocate nodes are expanded) which follows allocations.
|
||||
assert(alloc != NULL, "should have allocation");
|
||||
if (alloc->_idx == instance_id) {
|
||||
// Can not bypass initialization of the instance we are looking for.
|
||||
|
63
hotspot/test/compiler/arraycopy/TestArrayOfNoTypeCheck.java
Normal file
63
hotspot/test/compiler/arraycopy/TestArrayOfNoTypeCheck.java
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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 8055910
|
||||
* @summary Arrays.copyOf doesn't perform subtype check
|
||||
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayOfNoTypeCheck
|
||||
*
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TestArrayOfNoTypeCheck {
|
||||
|
||||
static class A {
|
||||
}
|
||||
|
||||
static class B extends A {
|
||||
}
|
||||
|
||||
static B[] test(A[] arr) {
|
||||
return Arrays.copyOf(arr, 10, B[].class);
|
||||
}
|
||||
|
||||
static public void main(String[] args) {
|
||||
A[] arr = new A[20];
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
test(arr);
|
||||
}
|
||||
A[] arr2 = new A[20];
|
||||
arr2[0] = new A();
|
||||
boolean exception = false;
|
||||
try {
|
||||
test(arr2);
|
||||
} catch (ArrayStoreException ase) {
|
||||
exception = true;
|
||||
}
|
||||
if (!exception) {
|
||||
throw new RuntimeException("TEST FAILED: ArrayStoreException not thrown");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user