Skip to content

Commit da74fbd

Browse files
committed
8347006: LoadRangeNode floats above array guard in arraycopy intrinsic
Reviewed-by: chagedorn Backport-of: 82e2a79
1 parent f0a89c5 commit da74fbd

File tree

5 files changed

+58
-44
lines changed

5 files changed

+58
-44
lines changed

src/hotspot/share/opto/library_call.cpp

+18-10
Original file line numberDiff line numberDiff line change
@@ -4262,7 +4262,7 @@ bool LibraryCallKit::inline_native_subtype_check() {
42624262

42634263
//---------------------generate_array_guard_common------------------------
42644264
Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
4265-
bool obj_array, bool not_array) {
4265+
bool obj_array, bool not_array, Node** obj) {
42664266

42674267
if (stopped()) {
42684268
return nullptr;
@@ -4304,7 +4304,14 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
43044304
// invert the test if we are looking for a non-array
43054305
if (not_array) btest = BoolTest(btest).negate();
43064306
Node* bol = _gvn.transform(new BoolNode(cmp, btest));
4307-
return generate_fair_guard(bol, region);
4307+
Node* ctrl = generate_fair_guard(bol, region);
4308+
Node* is_array_ctrl = not_array ? control() : ctrl;
4309+
if (obj != nullptr && is_array_ctrl != nullptr && is_array_ctrl != top()) {
4310+
// Keep track of the fact that 'obj' is an array to prevent
4311+
// array specific accesses from floating above the guard.
4312+
*obj = _gvn.transform(new CastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM));
4313+
}
4314+
return ctrl;
43084315
}
43094316

43104317

@@ -4399,7 +4406,7 @@ bool LibraryCallKit::inline_native_getLength() {
43994406
if (stopped()) return true;
44004407

44014408
// Deoptimize if it is a non-array.
4402-
Node* non_array = generate_non_array_guard(load_object_klass(array), nullptr);
4409+
Node* non_array = generate_non_array_guard(load_object_klass(array), nullptr, &array);
44034410

44044411
if (non_array != nullptr) {
44054412
PreserveJVMState pjvms(this);
@@ -5259,12 +5266,13 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
52595266
record_for_igvn(result_reg);
52605267

52615268
Node* obj_klass = load_object_klass(obj);
5262-
Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)nullptr);
5269+
Node* array_obj = obj;
5270+
Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)nullptr, &array_obj);
52635271
if (array_ctl != nullptr) {
52645272
// It's an array.
52655273
PreserveJVMState pjvms(this);
52665274
set_control(array_ctl);
5267-
Node* obj_length = load_array_length(obj);
5275+
Node* obj_length = load_array_length(array_obj);
52685276
Node* array_size = nullptr; // Size of the array without object alignment padding.
52695277
Node* alloc_obj = new_array(obj_klass, obj_length, 0, &array_size, /*deoptimize_on_exception=*/true);
52705278

@@ -5278,7 +5286,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
52785286
set_control(is_obja);
52795287
// Generate a direct call to the right arraycopy function(s).
52805288
// Clones are always tightly coupled.
5281-
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, obj, intcon(0), alloc_obj, intcon(0), obj_length, true, false);
5289+
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, array_obj, intcon(0), alloc_obj, intcon(0), obj_length, true, false);
52825290
ac->set_clone_oop_array();
52835291
Node* n = _gvn.transform(ac);
52845292
assert(n == ac, "cannot disappear");
@@ -5299,7 +5307,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
52995307
// the object.)
53005308

53015309
if (!stopped()) {
5302-
copy_to_clone(obj, alloc_obj, array_size, true);
5310+
copy_to_clone(array_obj, alloc_obj, array_size, true);
53035311

53045312
// Present the results of the copy.
53055313
result_reg->init_req(_array_path, control());
@@ -5920,8 +5928,8 @@ bool LibraryCallKit::inline_arraycopy() {
59205928
record_for_igvn(slow_region);
59215929

59225930
// (1) src and dest are arrays.
5923-
generate_non_array_guard(load_object_klass(src), slow_region);
5924-
generate_non_array_guard(load_object_klass(dest), slow_region);
5931+
generate_non_array_guard(load_object_klass(src), slow_region, &src);
5932+
generate_non_array_guard(load_object_klass(dest), slow_region, &dest);
59255933

59265934
// (2) src and dest arrays must have elements of the same BasicType
59275935
// done at macro expansion or at Ideal transformation time
@@ -8537,7 +8545,7 @@ bool LibraryCallKit::inline_getObjectSize() {
85378545
PhiNode* result_val = new PhiNode(result_reg, TypeLong::LONG);
85388546
record_for_igvn(result_reg);
85398547

8540-
Node* array_ctl = generate_array_guard(klass_node, nullptr);
8548+
Node* array_ctl = generate_array_guard(klass_node, nullptr, &obj);
85418549
if (array_ctl != nullptr) {
85428550
// Array case: size is round(header + element_size*arraylength).
85438551
// Since arraylength is different for every array instance, we have to

src/hotspot/share/opto/library_call.hpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -163,20 +163,20 @@ class LibraryCallKit : public GraphKit {
163163
RegionNode* region);
164164
Node* generate_interface_guard(Node* kls, RegionNode* region);
165165
Node* generate_hidden_class_guard(Node* kls, RegionNode* region);
166-
Node* generate_array_guard(Node* kls, RegionNode* region) {
167-
return generate_array_guard_common(kls, region, false, false);
166+
Node* generate_array_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
167+
return generate_array_guard_common(kls, region, false, false, obj);
168168
}
169-
Node* generate_non_array_guard(Node* kls, RegionNode* region) {
170-
return generate_array_guard_common(kls, region, false, true);
169+
Node* generate_non_array_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
170+
return generate_array_guard_common(kls, region, false, true, obj);
171171
}
172-
Node* generate_objArray_guard(Node* kls, RegionNode* region) {
173-
return generate_array_guard_common(kls, region, true, false);
172+
Node* generate_objArray_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
173+
return generate_array_guard_common(kls, region, true, false, obj);
174174
}
175-
Node* generate_non_objArray_guard(Node* kls, RegionNode* region) {
176-
return generate_array_guard_common(kls, region, true, true);
175+
Node* generate_non_objArray_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
176+
return generate_array_guard_common(kls, region, true, true, obj);
177177
}
178178
Node* generate_array_guard_common(Node* kls, RegionNode* region,
179-
bool obj_array, bool not_array);
179+
bool obj_array, bool not_array, Node** obj = nullptr);
180180
Node* generate_virtual_guard(Node* obj_klass, RegionNode* slow_region);
181181
CallJavaNode* generate_method_call(vmIntrinsicID method_id, bool is_virtual, bool is_static, bool res_not_null);
182182
CallJavaNode* generate_method_call_static(vmIntrinsicID method_id, bool res_not_null) {

src/hotspot/share/opto/type.cpp

+13-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -582,6 +582,7 @@ void Type::Initialize_shared(Compile* current) {
582582
TypeAryPtr::_array_interfaces = TypeInterfaces::make(&array_interfaces);
583583
TypeAryKlassPtr::_array_interfaces = TypeAryPtr::_array_interfaces;
584584

585+
TypeAryPtr::BOTTOM = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::BOTTOM, TypeInt::POS), nullptr, false, Type::OffsetBot);
585586
TypeAryPtr::RANGE = TypeAryPtr::make( TypePtr::BotPTR, TypeAry::make(Type::BOTTOM,TypeInt::POS), nullptr /* current->env()->Object_klass() */, false, arrayOopDesc::length_offset_in_bytes());
586587

587588
TypeAryPtr::NARROWOOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeNarrowOop::BOTTOM, TypeInt::POS), nullptr /*ciArrayKlass::make(o)*/, false, Type::OffsetBot);
@@ -4682,16 +4683,17 @@ bool TypeAryKlassPtr::is_meet_subtype_of_helper(const TypeKlassPtr *other, bool
46824683

46834684
//=============================================================================
46844685
// Convenience common pre-built types.
4685-
const TypeAryPtr *TypeAryPtr::RANGE;
4686-
const TypeAryPtr *TypeAryPtr::OOPS;
4687-
const TypeAryPtr *TypeAryPtr::NARROWOOPS;
4688-
const TypeAryPtr *TypeAryPtr::BYTES;
4689-
const TypeAryPtr *TypeAryPtr::SHORTS;
4690-
const TypeAryPtr *TypeAryPtr::CHARS;
4691-
const TypeAryPtr *TypeAryPtr::INTS;
4692-
const TypeAryPtr *TypeAryPtr::LONGS;
4693-
const TypeAryPtr *TypeAryPtr::FLOATS;
4694-
const TypeAryPtr *TypeAryPtr::DOUBLES;
4686+
const TypeAryPtr* TypeAryPtr::BOTTOM;
4687+
const TypeAryPtr* TypeAryPtr::RANGE;
4688+
const TypeAryPtr* TypeAryPtr::OOPS;
4689+
const TypeAryPtr* TypeAryPtr::NARROWOOPS;
4690+
const TypeAryPtr* TypeAryPtr::BYTES;
4691+
const TypeAryPtr* TypeAryPtr::SHORTS;
4692+
const TypeAryPtr* TypeAryPtr::CHARS;
4693+
const TypeAryPtr* TypeAryPtr::INTS;
4694+
const TypeAryPtr* TypeAryPtr::LONGS;
4695+
const TypeAryPtr* TypeAryPtr::FLOATS;
4696+
const TypeAryPtr* TypeAryPtr::DOUBLES;
46954697

46964698
//------------------------------make-------------------------------------------
46974699
const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset,

src/hotspot/share/opto/type.hpp

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -1470,16 +1470,17 @@ class TypeAryPtr : public TypeOopPtr {
14701470
virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
14711471

14721472
// Convenience common pre-built types.
1473-
static const TypeAryPtr *RANGE;
1474-
static const TypeAryPtr *OOPS;
1475-
static const TypeAryPtr *NARROWOOPS;
1476-
static const TypeAryPtr *BYTES;
1477-
static const TypeAryPtr *SHORTS;
1478-
static const TypeAryPtr *CHARS;
1479-
static const TypeAryPtr *INTS;
1480-
static const TypeAryPtr *LONGS;
1481-
static const TypeAryPtr *FLOATS;
1482-
static const TypeAryPtr *DOUBLES;
1473+
static const TypeAryPtr* BOTTOM;
1474+
static const TypeAryPtr* RANGE;
1475+
static const TypeAryPtr* OOPS;
1476+
static const TypeAryPtr* NARROWOOPS;
1477+
static const TypeAryPtr* BYTES;
1478+
static const TypeAryPtr* SHORTS;
1479+
static const TypeAryPtr* CHARS;
1480+
static const TypeAryPtr* INTS;
1481+
static const TypeAryPtr* LONGS;
1482+
static const TypeAryPtr* FLOATS;
1483+
static const TypeAryPtr* DOUBLES;
14831484
// selects one of the above:
14841485
static const TypeAryPtr *get_array_body_type(BasicType elem) {
14851486
assert((uint)elem <= T_CONFLICT && _array_body_type[elem] != nullptr, "bad elem type");

test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyNoInit.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,14 @@
2323

2424
/*
2525
* @test
26-
* @bug 8064703
26+
* @bug 8064703 8347006
2727
* @summary Deoptimization between array allocation and arraycopy may result in non initialized array
2828
*
2929
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=020
3030
* compiler.arraycopy.TestArrayCopyNoInit
31+
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=020
32+
* -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders -XX:-UseTLAB
33+
* compiler.arraycopy.TestArrayCopyNoInit
3134
*/
3235

3336
package compiler.arraycopy;

0 commit comments

Comments
 (0)