mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 02:54:35 +02:00
8273359: CI: ciInstanceKlass::get_canonical_holder() doesn't respect instance size
Reviewed-by: kvn
This commit is contained in:
parent
d7efd0e8cf
commit
f7e9f56e23
5 changed files with 68 additions and 7 deletions
|
@ -647,7 +647,7 @@ void LIRGenerator::new_instance(LIR_Opr dst, ciInstanceKlass* klass, bool is_unr
|
||||||
|
|
||||||
assert(klass->is_loaded(), "must be loaded");
|
assert(klass->is_loaded(), "must be loaded");
|
||||||
// allocate space for instance
|
// allocate space for instance
|
||||||
assert(klass->size_helper() >= 0, "illegal instance size");
|
assert(klass->size_helper() > 0, "illegal instance size");
|
||||||
const int instance_size = align_object_size(klass->size_helper());
|
const int instance_size = align_object_size(klass->size_helper());
|
||||||
__ allocate_object(dst, scratch1, scratch2, scratch3, scratch4,
|
__ allocate_object(dst, scratch1, scratch2, scratch3, scratch4,
|
||||||
oopDesc::header_size(), instance_size, klass_reg, !klass->is_initialized(), slow_path);
|
oopDesc::header_size(), instance_size, klass_reg, !klass->is_initialized(), slow_path);
|
||||||
|
|
|
@ -205,12 +205,12 @@ ciConstantPoolCache* ciInstanceKlass::field_cache() {
|
||||||
//
|
//
|
||||||
ciInstanceKlass* ciInstanceKlass::get_canonical_holder(int offset) {
|
ciInstanceKlass* ciInstanceKlass::get_canonical_holder(int offset) {
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
if (!(offset >= 0 && offset < layout_helper())) {
|
if (!(offset >= 0 && offset < layout_helper_size_in_bytes())) {
|
||||||
tty->print("*** get_canonical_holder(%d) on ", offset);
|
tty->print("*** get_canonical_holder(%d) on ", offset);
|
||||||
this->print();
|
this->print();
|
||||||
tty->print_cr(" ***");
|
tty->print_cr(" ***");
|
||||||
};
|
};
|
||||||
assert(offset >= 0 && offset < layout_helper(), "offset must be tame");
|
assert(offset >= 0 && offset < layout_helper_size_in_bytes(), "offset must be tame");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (offset < instanceOopDesc::base_offset_in_bytes()) {
|
if (offset < instanceOopDesc::base_offset_in_bytes()) {
|
||||||
|
@ -227,7 +227,9 @@ ciInstanceKlass* ciInstanceKlass::get_canonical_holder(int offset) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
assert(self->is_loaded(), "must be loaded to have size");
|
assert(self->is_loaded(), "must be loaded to have size");
|
||||||
ciInstanceKlass* super = self->super();
|
ciInstanceKlass* super = self->super();
|
||||||
if (super == NULL || super->nof_nonstatic_fields() == 0) {
|
if (super == NULL ||
|
||||||
|
super->nof_nonstatic_fields() == 0 ||
|
||||||
|
super->layout_helper_size_in_bytes() <= offset) {
|
||||||
return self;
|
return self;
|
||||||
} else {
|
} else {
|
||||||
self = super; // return super->get_canonical_holder(offset)
|
self = super; // return super->get_canonical_holder(offset)
|
||||||
|
|
|
@ -165,6 +165,9 @@ public:
|
||||||
return compute_shared_has_subklass();
|
return compute_shared_has_subklass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jint layout_helper_size_in_bytes() {
|
||||||
|
return Klass::layout_helper_size_in_bytes(layout_helper());
|
||||||
|
}
|
||||||
jint size_helper() {
|
jint size_helper() {
|
||||||
return (Klass::layout_helper_size_in_bytes(layout_helper())
|
return (Klass::layout_helper_size_in_bytes(layout_helper())
|
||||||
>> LogHeapWordSize);
|
>> LogHeapWordSize);
|
||||||
|
|
|
@ -1355,7 +1355,7 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||||
ciInstanceKlass *k = to->klass()->as_instance_klass();
|
ciInstanceKlass *k = to->klass()->as_instance_klass();
|
||||||
if( ptr == TypePtr::Constant ) {
|
if( ptr == TypePtr::Constant ) {
|
||||||
if (to->klass() != ciEnv::current()->Class_klass() ||
|
if (to->klass() != ciEnv::current()->Class_klass() ||
|
||||||
offset < k->size_helper() * wordSize) {
|
offset < k->layout_helper_size_in_bytes()) {
|
||||||
// No constant oop pointers (such as Strings); they alias with
|
// No constant oop pointers (such as Strings); they alias with
|
||||||
// unknown strings.
|
// unknown strings.
|
||||||
assert(!is_known_inst, "not scalarizable allocation");
|
assert(!is_known_inst, "not scalarizable allocation");
|
||||||
|
@ -1379,7 +1379,7 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||||
if (!is_known_inst) { // Do it only for non-instance types
|
if (!is_known_inst) { // Do it only for non-instance types
|
||||||
tj = to = TypeInstPtr::make(TypePtr::BotPTR, env()->Object_klass(), false, NULL, offset);
|
tj = to = TypeInstPtr::make(TypePtr::BotPTR, env()->Object_klass(), false, NULL, offset);
|
||||||
}
|
}
|
||||||
} else if (offset < 0 || offset >= k->size_helper() * wordSize) {
|
} else if (offset < 0 || offset >= k->layout_helper_size_in_bytes()) {
|
||||||
// Static fields are in the space above the normal instance
|
// Static fields are in the space above the normal instance
|
||||||
// fields in the java.lang.Class instance.
|
// fields in the java.lang.Class instance.
|
||||||
if (to->klass() != ciEnv::current()->Class_klass()) {
|
if (to->klass() != ciEnv::current()->Class_klass()) {
|
||||||
|
@ -1389,6 +1389,7 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ciInstanceKlass *canonical_holder = k->get_canonical_holder(offset);
|
ciInstanceKlass *canonical_holder = k->get_canonical_holder(offset);
|
||||||
|
assert(offset < canonical_holder->layout_helper_size_in_bytes(), "");
|
||||||
if (!k->equals(canonical_holder) || tj->offset() != offset) {
|
if (!k->equals(canonical_holder) || tj->offset() != offset) {
|
||||||
if( is_known_inst ) {
|
if( is_known_inst ) {
|
||||||
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, true, NULL, offset, to->instance_id());
|
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, true, NULL, offset, to->instance_id());
|
||||||
|
@ -1661,7 +1662,7 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr
|
||||||
ciField* field;
|
ciField* field;
|
||||||
if (tinst->const_oop() != NULL &&
|
if (tinst->const_oop() != NULL &&
|
||||||
tinst->klass() == ciEnv::current()->Class_klass() &&
|
tinst->klass() == ciEnv::current()->Class_klass() &&
|
||||||
tinst->offset() >= (tinst->klass()->as_instance_klass()->size_helper() * wordSize)) {
|
tinst->offset() >= (tinst->klass()->as_instance_klass()->layout_helper_size_in_bytes())) {
|
||||||
// static field
|
// static field
|
||||||
ciInstanceKlass* k = tinst->const_oop()->as_instance()->java_lang_Class_klass()->as_instance_klass();
|
ciInstanceKlass* k = tinst->const_oop()->as_instance()->java_lang_Class_klass()->as_instance_klass();
|
||||||
field = k->get_field_by_offset(tinst->offset(), true);
|
field = k->get_field_by_offset(tinst->offset(), true);
|
||||||
|
|
55
test/hotspot/jtreg/compiler/unsafe/AlignmentGapAccess.java
Normal file
55
test/hotspot/jtreg/compiler/unsafe/AlignmentGapAccess.java
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, 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 8273359
|
||||||
|
*
|
||||||
|
* @modules java.base/jdk.internal.misc:+open
|
||||||
|
* @run main/othervm -Xbatch compiler.unsafe.AlignmentGapAccess
|
||||||
|
*/
|
||||||
|
|
||||||
|
package compiler.unsafe;
|
||||||
|
|
||||||
|
import jdk.internal.misc.Unsafe;
|
||||||
|
|
||||||
|
public class AlignmentGapAccess {
|
||||||
|
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||||
|
|
||||||
|
static class A { int fa; }
|
||||||
|
static class B extends A { byte fb; }
|
||||||
|
|
||||||
|
static final long FA_OFFSET = UNSAFE.objectFieldOffset(A.class, "fa");
|
||||||
|
static final long FB_OFFSET = UNSAFE.objectFieldOffset(B.class, "fb");
|
||||||
|
|
||||||
|
static int test(B obj) {
|
||||||
|
return UNSAFE.getInt(obj, FB_OFFSET + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (int i = 0; i < 20_000; i++) {
|
||||||
|
test(new B());
|
||||||
|
}
|
||||||
|
System.out.println("TEST PASSED");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue