8328480: C2: SubTypeCheckNode in checkcast should use the klass constant of a unique concrete sub class

Reviewed-by: roland, kvn
This commit is contained in:
Christian Hagedorn 2024-04-15 06:25:24 +00:00
parent 1abb826210
commit b486709b06
2 changed files with 85 additions and 7 deletions

View File

@ -3268,8 +3268,9 @@ Node* GraphKit::gen_instanceof(Node* obj, Node* superklass, bool safe_for_replac
Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
Node* *failure_control) {
kill_dead_locals(); // Benefit all the uncommon traps
const TypeKlassPtr *tk = _gvn.type(superklass)->is_klassptr()->try_improve();
const TypeOopPtr *toop = tk->cast_to_exactness(false)->as_instance_type();
const TypeKlassPtr* klass_ptr_type = _gvn.type(superklass)->is_klassptr();
const TypeKlassPtr* improved_klass_ptr_type = klass_ptr_type->try_improve();
const TypeOopPtr* toop = improved_klass_ptr_type->cast_to_exactness(false)->as_instance_type();
// Fast cutout: Check the case that the cast is vacuously true.
// This detects the common cases where the test will short-circuit
@ -3277,10 +3278,10 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
// because if the test is going to turn into zero code, we don't
// want a residual null check left around. (Causes a slowdown,
// for example, in some objArray manipulations, such as a[i]=a[j].)
if (tk->singleton()) {
if (improved_klass_ptr_type->singleton()) {
const TypeOopPtr* objtp = _gvn.type(obj)->isa_oopptr();
if (objtp != nullptr) {
switch (C->static_subtype_check(tk, objtp->as_klass_type())) {
switch (C->static_subtype_check(improved_klass_ptr_type, objtp->as_klass_type())) {
case Compile::SSC_always_true:
// If we know the type check always succeed then we don't use
// the profiling data at this bytecode. Don't lose it, feed it
@ -3346,7 +3347,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
}
Node* cast_obj = nullptr;
if (tk->klass_is_exact()) {
if (improved_klass_ptr_type->klass_is_exact()) {
// The following optimization tries to statically cast the speculative type of the object
// (for example obtained during profiling) to the type of the superklass and then do a
// dynamic check that the type of the object is what we expect. To work correctly
@ -3356,7 +3357,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
// a speculative type use it to perform an exact cast.
ciKlass* spec_obj_type = obj_type->speculative_type();
if (spec_obj_type != nullptr || data != nullptr) {
cast_obj = maybe_cast_profiled_receiver(not_null_obj, tk, spec_obj_type, safe_for_replace);
cast_obj = maybe_cast_profiled_receiver(not_null_obj, improved_klass_ptr_type, spec_obj_type, safe_for_replace);
if (cast_obj != nullptr) {
if (failure_control != nullptr) // failure is now impossible
(*failure_control) = top();
@ -3368,7 +3369,11 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
if (cast_obj == nullptr) {
// Generate the subtype check
Node* not_subtype_ctrl = gen_subtype_check(not_null_obj, superklass );
Node* improved_superklass = superklass;
if (improved_klass_ptr_type != klass_ptr_type && improved_klass_ptr_type->singleton()) {
improved_superklass = makecon(improved_klass_ptr_type);
}
Node* not_subtype_ctrl = gen_subtype_check(not_null_obj, improved_superklass);
// Plug in success path into the merge
cast_obj = _gvn.transform(new CheckCastPPNode(control(), not_null_obj, toop));

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2024, 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 8328480
* @summary Test that SubTypeCheckNode takes improved unique concrete klass constant in order to fold consecutive sub
* type checks.
* @library /test/lib /
* @run driver compiler.types.TestSubTypeCheckUniqueSubclass
*/
package compiler.types;
import compiler.lib.ir_framework.*;
public class TestSubTypeCheckUniqueSubclass {
static Object o = new C(); // Make sure C is loaded.
static Object o2 = new C2(); // Make sure C2 is loaded while NeverLoaded is not.
public static void main(String[] args) {
TestFramework.run();
}
@Test
@Warmup(0)
@IR(counts = {IRNode.SUBTYPE_CHECK, "1"},
phase = CompilePhase.ITER_GVN1)
static void testAbstractAbstract() {
A a = (A)o;
A a2 = (B)o;
}
@Test
@Warmup(0)
@IR(counts = {IRNode.SUBTYPE_CHECK, "1"},
phase = CompilePhase.ITER_GVN1)
static void testAbstractAbstractWithUnloaded() {
A2 a = (A2)o2;
A2 a2 = (B2)o2;
}
}
abstract class A {}
abstract class B extends A {}
class C extends B {}
abstract class A2 {}
abstract class B2 extends A2 {}
class C2 extends B2 {}
// Class never loaded -> C2 looks like unique sub class.
class NeverLoaded extends B2 {}