提交 085531fa 编写于 作者: R roland

Merge

......@@ -2809,7 +2809,8 @@ Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj,
*/
Node* GraphKit::maybe_cast_profiled_obj(Node* obj,
ciKlass* type,
bool not_null) {
bool not_null,
SafePointNode* sfpt) {
// type == NULL if profiling tells us this object is always null
if (type != NULL) {
Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check;
......@@ -2831,7 +2832,13 @@ Node* GraphKit::maybe_cast_profiled_obj(Node* obj,
ciKlass* exact_kls = type;
Node* slow_ctl = type_check_receiver(exact_obj, exact_kls, 1.0,
&exact_obj);
{
if (sfpt != NULL) {
GraphKit kit(sfpt->jvms());
PreserveJVMState pjvms(&kit);
kit.set_control(slow_ctl);
kit.uncommon_trap(class_reason,
Deoptimization::Action_maybe_recompile);
} else {
PreserveJVMState pjvms(this);
set_control(slow_ctl);
uncommon_trap(class_reason,
......
......@@ -418,7 +418,8 @@ class GraphKit : public Phase {
// Cast obj to type and emit guard unless we had too many traps here already
Node* maybe_cast_profiled_obj(Node* obj,
ciKlass* type,
bool not_null = false);
bool not_null = false,
SafePointNode* sfpt = NULL);
// Cast obj to not-null on this path
Node* cast_not_null(Node* obj, bool do_replace_in_map = true);
......
......@@ -4697,10 +4697,6 @@ bool LibraryCallKit::inline_arraycopy() {
Node* dest_offset = argument(3); // type: int
Node* length = argument(4); // type: int
// Check for allocation before we add nodes that would confuse
// tightly_coupled_allocation()
AllocateArrayNode* alloc = tightly_coupled_allocation(dest, NULL);
// The following tests must be performed
// (1) src and dest are arrays.
// (2) src and dest arrays must have elements of the same BasicType
......@@ -4717,6 +4713,36 @@ bool LibraryCallKit::inline_arraycopy() {
src = null_check(src, T_ARRAY);
dest = null_check(dest, T_ARRAY);
// Check for allocation before we add nodes that would confuse
// tightly_coupled_allocation()
AllocateArrayNode* alloc = tightly_coupled_allocation(dest, NULL);
SafePointNode* sfpt = NULL;
if (alloc != NULL) {
// The JVM state for uncommon traps between the allocation and
// arraycopy is set to the state before the allocation: if the
// initialization is performed by the array copy, we don't want to
// go back to the interpreter with an unitialized array.
JVMState* old_jvms = alloc->jvms();
JVMState* jvms = old_jvms->clone_shallow(C);
uint size = alloc->req();
sfpt = new SafePointNode(size, jvms);
jvms->set_map(sfpt);
for (uint i = 0; i < size; i++) {
sfpt->init_req(i, alloc->in(i));
}
// re-push array length for deoptimization
sfpt->ins_req(jvms->stkoff() + jvms->sp(), alloc->in(AllocateNode::ALength));
jvms->set_sp(jvms->sp()+1);
jvms->set_monoff(jvms->monoff()+1);
jvms->set_scloff(jvms->scloff()+1);
jvms->set_endoff(jvms->endoff()+1);
jvms->set_should_reexecute(true);
sfpt->set_i_o(map()->i_o());
sfpt->set_memory(map()->memory());
}
bool notest = false;
const Type* src_type = _gvn.type(src);
......@@ -4762,14 +4788,14 @@ bool LibraryCallKit::inline_arraycopy() {
if (could_have_src && could_have_dest) {
// This is going to pay off so emit the required guards
if (!has_src) {
src = maybe_cast_profiled_obj(src, src_k);
src = maybe_cast_profiled_obj(src, src_k, true, sfpt);
src_type = _gvn.type(src);
top_src = src_type->isa_aryptr();
has_src = (top_src != NULL && top_src->klass() != NULL);
src_spec = true;
}
if (!has_dest) {
dest = maybe_cast_profiled_obj(dest, dest_k);
dest = maybe_cast_profiled_obj(dest, dest_k, true);
dest_type = _gvn.type(dest);
top_dest = dest_type->isa_aryptr();
has_dest = (top_dest != NULL && top_dest->klass() != NULL);
......@@ -4810,10 +4836,10 @@ bool LibraryCallKit::inline_arraycopy() {
if (could_have_src && could_have_dest) {
// If we can have both exact types, emit the missing guards
if (could_have_src && !src_spec) {
src = maybe_cast_profiled_obj(src, src_k);
src = maybe_cast_profiled_obj(src, src_k, true, sfpt);
}
if (could_have_dest && !dest_spec) {
dest = maybe_cast_profiled_obj(dest, dest_k);
dest = maybe_cast_profiled_obj(dest, dest_k, true);
}
}
}
......@@ -4855,13 +4881,28 @@ bool LibraryCallKit::inline_arraycopy() {
Node* not_subtype_ctrl = gen_subtype_check(src_klass, dest_klass);
if (not_subtype_ctrl != top()) {
PreserveJVMState pjvms(this);
set_control(not_subtype_ctrl);
uncommon_trap(Deoptimization::Reason_intrinsic,
Deoptimization::Action_make_not_entrant);
assert(stopped(), "Should be stopped");
if (sfpt != NULL) {
GraphKit kit(sfpt->jvms());
PreserveJVMState pjvms(&kit);
kit.set_control(not_subtype_ctrl);
kit.uncommon_trap(Deoptimization::Reason_intrinsic,
Deoptimization::Action_make_not_entrant);
assert(kit.stopped(), "Should be stopped");
} else {
PreserveJVMState pjvms(this);
set_control(not_subtype_ctrl);
uncommon_trap(Deoptimization::Reason_intrinsic,
Deoptimization::Action_make_not_entrant);
assert(stopped(), "Should be stopped");
}
}
{
if (sfpt != NULL) {
GraphKit kit(sfpt->jvms());
kit.set_control(_gvn.transform(slow_region));
kit.uncommon_trap(Deoptimization::Reason_intrinsic,
Deoptimization::Action_make_not_entrant);
assert(kit.stopped(), "Should be stopped");
} else {
PreserveJVMState pjvms(this);
set_control(_gvn.transform(slow_region));
uncommon_trap(Deoptimization::Reason_intrinsic,
......
/*
* 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 8064703
* @summary Deoptimization between array allocation and arraycopy may result in non initialized array
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=020 TestArrayCopyNoInit
*
*/
import java.lang.invoke.*;
public class TestArrayCopyNoInit {
static int[] m1(int[] src) {
int[] dest = new int[10];
try {
System.arraycopy(src, 0, dest, 0, 10);
} catch (NullPointerException npe) {
}
return dest;
}
static int[] m2(Object src, boolean flag) {
Class tmp = src.getClass();
if (flag) {
return null;
}
int[] dest = new int[10];
try {
System.arraycopy(src, 0, dest, 0, 10);
} catch (ArrayStoreException npe) {
}
return dest;
}
static int[] m3(int[] src, int src_offset) {
int tmp = src[0];
int[] dest = new int[10];
try {
System.arraycopy(src, src_offset, dest, 0, 10);
} catch (IndexOutOfBoundsException npe) {
}
return dest;
}
static int[] m4(int[] src, int length) {
int tmp = src[0];
int[] dest = new int[10];
try {
System.arraycopy(src, 0, dest, 0, length);
} catch (IndexOutOfBoundsException npe) {
}
return dest;
}
static TestArrayCopyNoInit[] m5(Object[] src) {
Object tmp = src[0];
TestArrayCopyNoInit[] dest = new TestArrayCopyNoInit[10];
System.arraycopy(src, 0, dest, 0, 0);
return dest;
}
static class A {
}
static class B extends A {
}
static class C extends B {
}
static class D extends C {
}
static class E extends D {
}
static class F extends E {
}
static class G extends F {
}
static class H extends G {
}
static class I extends H {
}
static H[] m6(Object[] src) {
Object tmp = src[0];
H[] dest = new H[10];
System.arraycopy(src, 0, dest, 0, 0);
return dest;
}
static Object m7_src(Object src) {
return src;
}
static int[] m7(Object src, boolean flag) {
Class tmp = src.getClass();
if (flag) {
return null;
}
src = m7_src(src);
int[] dest = new int[10];
try {
System.arraycopy(src, 0, dest, 0, 10);
} catch (ArrayStoreException npe) {
}
return dest;
}
static public void main(String[] args) throws Throwable {
boolean success = true;
int[] src = new int[10];
TestArrayCopyNoInit[] src2 = new TestArrayCopyNoInit[10];
int[] res = null;
TestArrayCopyNoInit[] res2 = null;
Object src_obj = new Object();
for (int i = 0; i < 20000; i++) {
m1(src);
}
res = m1(null);
for (int i = 0; i < res.length; i++) {
if (res[i] != 0) {
success = false;
System.out.println("Uninitialized array following NPE");
break;
}
}
for (int i = 0; i < 20000; i++) {
if ((i%2) == 0) {
m2(src, false);
} else {
m2(src_obj, true);
}
}
res = m2(src_obj, false);
for (int i = 0; i < res.length; i++) {
if (res[i] != 0) {
success = false;
System.out.println("Uninitialized array following failed array check");
break;
}
}
for (int i = 0; i < 20000; i++) {
m3(src, 0);
}
res = m3(src, -1);
for (int i = 0; i < res.length; i++) {
if (res[i] != 0) {
success = false;
System.out.println("Uninitialized array following failed src offset check");
break;
}
}
for (int i = 0; i < 20000; i++) {
m4(src, 0);
}
res = m4(src, -1);
for (int i = 0; i < res.length; i++) {
if (res[i] != 0) {
success = false;
System.out.println("Uninitialized array following failed length check");
break;
}
}
for (int i = 0; i < 20000; i++) {
m5(src2);
}
res2 = m5(new Object[10]);
for (int i = 0; i < res2.length; i++) {
if (res2[i] != null) {
success = false;
System.out.println("Uninitialized array following failed type check");
break;
}
}
H[] src3 = new H[10];
I b = new I();
for (int i = 0; i < 20000; i++) {
m6(src3);
}
H[] res3 = m6(new Object[10]);
for (int i = 0; i < res3.length; i++) {
if (res3[i] != null) {
success = false;
System.out.println("Uninitialized array following failed full type check");
break;
}
}
for (int i = 0; i < 20000; i++) {
if ((i%2) == 0) {
m7(src, false);
} else {
m7(src_obj, true);
}
}
res = m7(src_obj, false);
for (int i = 0; i < res.length; i++) {
if (res[i] != 0) {
success = false;
System.out.println("Uninitialized array following failed type check with return value profiling");
break;
}
}
if (!success) {
throw new RuntimeException("Some tests failed");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册