8237894: CTW: C1 compilation fails with assert(x->type()->tag() == f->type()->tag()) failed: should have same type
Field access instructions hash decalred_type in addition, indexed access instructions hash value type of the instruction in addition. Reviewed-by: thartmann, shade
This commit is contained in:
parent
6dffcf7533
commit
136a1574ec
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -3796,6 +3796,23 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, bool ign
|
|||||||
INLINE_BAILOUT("mdo allocation failed");
|
INLINE_BAILOUT("mdo allocation failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool is_invokedynamic = (bc == Bytecodes::_invokedynamic);
|
||||||
|
const bool has_receiver = (bc != Bytecodes::_invokestatic && !is_invokedynamic);
|
||||||
|
|
||||||
|
const int args_base = state()->stack_size() - callee->arg_size();
|
||||||
|
assert(args_base >= 0, "stack underflow during inlining");
|
||||||
|
|
||||||
|
Value recv = NULL;
|
||||||
|
if (has_receiver) {
|
||||||
|
assert(!callee->is_static(), "callee must not be static");
|
||||||
|
assert(callee->arg_size() > 0, "must have at least a receiver");
|
||||||
|
|
||||||
|
recv = state()->stack_at(args_base);
|
||||||
|
if (recv->is_null_obj()) {
|
||||||
|
INLINE_BAILOUT("receiver is always null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// now perform tests that are based on flag settings
|
// now perform tests that are based on flag settings
|
||||||
bool inlinee_by_directive = compilation()->directive()->should_inline(callee);
|
bool inlinee_by_directive = compilation()->directive()->should_inline(callee);
|
||||||
if (callee->force_inline() || inlinee_by_directive) {
|
if (callee->force_inline() || inlinee_by_directive) {
|
||||||
@ -3838,21 +3855,11 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, bool ign
|
|||||||
|
|
||||||
BlockBegin* orig_block = block();
|
BlockBegin* orig_block = block();
|
||||||
|
|
||||||
const bool is_invokedynamic = bc == Bytecodes::_invokedynamic;
|
|
||||||
const bool has_receiver = (bc != Bytecodes::_invokestatic && !is_invokedynamic);
|
|
||||||
|
|
||||||
const int args_base = state()->stack_size() - callee->arg_size();
|
|
||||||
assert(args_base >= 0, "stack underflow during inlining");
|
|
||||||
|
|
||||||
// Insert null check if necessary
|
// Insert null check if necessary
|
||||||
Value recv = NULL;
|
|
||||||
if (has_receiver) {
|
if (has_receiver) {
|
||||||
// note: null check must happen even if first instruction of callee does
|
// note: null check must happen even if first instruction of callee does
|
||||||
// an implicit null check since the callee is in a different scope
|
// an implicit null check since the callee is in a different scope
|
||||||
// and we must make sure exception handling does the right thing
|
// and we must make sure exception handling does the right thing
|
||||||
assert(!callee->is_static(), "callee must not be static");
|
|
||||||
assert(callee->arg_size() > 0, "must have at least a receiver");
|
|
||||||
recv = state()->stack_at(args_base);
|
|
||||||
null_check(recv);
|
null_check(recv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -454,6 +454,8 @@ class Instruction: public CompilationResourceObj {
|
|||||||
bool is_linked() const { return check_flag(IsLinkedInBlockFlag); }
|
bool is_linked() const { return check_flag(IsLinkedInBlockFlag); }
|
||||||
bool can_be_linked() { return as_Local() == NULL && as_Phi() == NULL; }
|
bool can_be_linked() { return as_Local() == NULL && as_Phi() == NULL; }
|
||||||
|
|
||||||
|
bool is_null_obj() { return as_Constant() != NULL && type()->as_ObjectType()->constant_value()->is_null_object(); }
|
||||||
|
|
||||||
bool has_uses() const { return use_count() > 0; }
|
bool has_uses() const { return use_count() > 0; }
|
||||||
ValueStack* state_before() const { return _state_before; }
|
ValueStack* state_before() const { return _state_before; }
|
||||||
ValueStack* exception_state() const { return _exception_state; }
|
ValueStack* exception_state() const { return _exception_state; }
|
||||||
@ -834,8 +836,8 @@ LEAF(LoadField, AccessField)
|
|||||||
|
|
||||||
ciType* declared_type() const;
|
ciType* declared_type() const;
|
||||||
|
|
||||||
// generic
|
// generic; cannot be eliminated if needs patching or if volatile.
|
||||||
HASHING2(LoadField, !needs_patching() && !field()->is_volatile(), obj()->subst(), offset()) // cannot be eliminated if needs patching or if volatile
|
HASHING3(LoadField, !needs_patching() && !field()->is_volatile(), obj()->subst(), offset(), declared_type())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -964,8 +966,8 @@ LEAF(LoadIndexed, AccessIndexed)
|
|||||||
ciType* exact_type() const;
|
ciType* exact_type() const;
|
||||||
ciType* declared_type() const;
|
ciType* declared_type() const;
|
||||||
|
|
||||||
// generic
|
// generic;
|
||||||
HASHING2(LoadIndexed, true, array()->subst(), index()->subst())
|
HASHING3(LoadIndexed, true, type()->tag(), array()->subst(), index()->subst())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
131
test/hotspot/jtreg/compiler/c1/TestValueNumberingNullObject.java
Normal file
131
test/hotspot/jtreg/compiler/c1/TestValueNumberingNullObject.java
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020, 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 8237894
|
||||||
|
* @summary CTW: C1 compilation fails with assert(x->type()->tag() == f->type()->tag()) failed: should have same type
|
||||||
|
*
|
||||||
|
* @run main/othervm
|
||||||
|
* -Xcomp -Xbatch -XX:CompileCommand=compileonly,compiler.c1.T*::*
|
||||||
|
* -XX:CompileCommand=exclude,compiler.c1.TestValueNumberingNullObject::main
|
||||||
|
* -XX:CompileCommand=inline,*.*
|
||||||
|
* -XX:TieredStopAtLevel=3
|
||||||
|
* compiler.c1.TestValueNumberingNullObject
|
||||||
|
*/
|
||||||
|
|
||||||
|
package compiler.c1;
|
||||||
|
|
||||||
|
class T1 {
|
||||||
|
|
||||||
|
public T2 f1;
|
||||||
|
|
||||||
|
public int za() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int zb() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int zc() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int zd() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ze() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int zf() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int zg() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int zh() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class T2 {
|
||||||
|
|
||||||
|
public T1 f1;
|
||||||
|
|
||||||
|
public int zh() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestValueNumberingNullObject {
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
new T1(); // Load
|
||||||
|
new T2(); // Load
|
||||||
|
try {
|
||||||
|
// case 1
|
||||||
|
// Null based field access.
|
||||||
|
// Value Numbering null based field access causes instructions to be eliminated across type/subtypes.
|
||||||
|
// declared type of these instructions are field type, so it being receiver causes problems to Type System.
|
||||||
|
// to mitigate this issue, we hash declared type in addition to existing hashing.
|
||||||
|
testFieldAccess();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// case 2
|
||||||
|
// Null based indexed access.
|
||||||
|
// Value Numbering null based indexed access causes instructions to be eliminated across type/subtypes.
|
||||||
|
// element basic type in encoded in the access instruction, this causes problems to Type system.
|
||||||
|
// declared type of these instructions are null, so it being receiver doesn't cause any problem to Type System.
|
||||||
|
// to mitigate this issue, we hash basic type in addition to existing hashing
|
||||||
|
basicTypeAccess();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static long testFieldAccess() {
|
||||||
|
T1 t1 = null;
|
||||||
|
T2 t2 = null;
|
||||||
|
T1[] t3 = null;
|
||||||
|
T2[] t4 = null;
|
||||||
|
|
||||||
|
long value = t1.f1.zh() + t2.f1.zh();
|
||||||
|
// null array object based field access.
|
||||||
|
value += t3[2].f1.zh() + t4[2].f1.zh();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long basicTypeAccess() {
|
||||||
|
long[] f1 = null;
|
||||||
|
int[] f2 = null;
|
||||||
|
T2[] t2 = null;
|
||||||
|
T1[] t1 = null;
|
||||||
|
return f1[5] + f2[5] + t2[5].zh() + t1[5].zh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user