Skip to content

Commit 82e2a79

Browse files
committed
8347006: LoadRangeNode floats above array guard in arraycopy intrinsic
Reviewed-by: roland, qamai, kvn
1 parent 85ed78c commit 82e2a79

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
@@ -4256,7 +4256,7 @@ bool LibraryCallKit::inline_native_subtype_check() {
42564256

42574257
//---------------------generate_array_guard_common------------------------
42584258
Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
4259-
bool obj_array, bool not_array) {
4259+
bool obj_array, bool not_array, Node** obj) {
42604260

42614261
if (stopped()) {
42624262
return nullptr;
@@ -4298,7 +4298,14 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
42984298
// invert the test if we are looking for a non-array
42994299
if (not_array) btest = BoolTest(btest).negate();
43004300
Node* bol = _gvn.transform(new BoolNode(cmp, btest));
4301-
return generate_fair_guard(bol, region);
4301+
Node* ctrl = generate_fair_guard(bol, region);
4302+
Node* is_array_ctrl = not_array ? control() : ctrl;
4303+
if (obj != nullptr && is_array_ctrl != nullptr && is_array_ctrl != top()) {
4304+
// Keep track of the fact that 'obj' is an array to prevent
4305+
// array specific accesses from floating above the guard.
4306+
*obj = _gvn.transform(new CastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM));
4307+
}
4308+
return ctrl;
43024309
}
43034310

43044311

@@ -4393,7 +4400,7 @@ bool LibraryCallKit::inline_native_getLength() {
43934400
if (stopped()) return true;
43944401

43954402
// Deoptimize if it is a non-array.
4396-
Node* non_array = generate_non_array_guard(load_object_klass(array), nullptr);
4403+
Node* non_array = generate_non_array_guard(load_object_klass(array), nullptr, &array);
43974404

43984405
if (non_array != nullptr) {
43994406
PreserveJVMState pjvms(this);
@@ -5253,12 +5260,13 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
52535260
record_for_igvn(result_reg);
52545261

52555262
Node* obj_klass = load_object_klass(obj);
5256-
Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)nullptr);
5263+
Node* array_obj = obj;
5264+
Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)nullptr, &array_obj);
52575265
if (array_ctl != nullptr) {
52585266
// It's an array.
52595267
PreserveJVMState pjvms(this);
52605268
set_control(array_ctl);
5261-
Node* obj_length = load_array_length(obj);
5269+
Node* obj_length = load_array_length(array_obj);
52625270
Node* array_size = nullptr; // Size of the array without object alignment padding.
52635271
Node* alloc_obj = new_array(obj_klass, obj_length, 0, &array_size, /*deoptimize_on_exception=*/true);
52645272

@@ -5272,7 +5280,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
52725280
set_control(is_obja);
52735281
// Generate a direct call to the right arraycopy function(s).
52745282
// Clones are always tightly coupled.
5275-
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, obj, intcon(0), alloc_obj, intcon(0), obj_length, true, false);
5283+
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, array_obj, intcon(0), alloc_obj, intcon(0), obj_length, true, false);
52765284
ac->set_clone_oop_array();
52775285
Node* n = _gvn.transform(ac);
52785286
assert(n == ac, "cannot disappear");
@@ -5293,7 +5301,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
52935301
// the object.)
52945302

52955303
if (!stopped()) {
5296-
copy_to_clone(obj, alloc_obj, array_size, true);
5304+
copy_to_clone(array_obj, alloc_obj, array_size, true);
52975305

52985306
// Present the results of the copy.
52995307
result_reg->init_req(_array_path, control());
@@ -5914,8 +5922,8 @@ bool LibraryCallKit::inline_arraycopy() {
59145922
record_for_igvn(slow_region);
59155923

59165924
// (1) src and dest are arrays.
5917-
generate_non_array_guard(load_object_klass(src), slow_region);
5918-
generate_non_array_guard(load_object_klass(dest), slow_region);
5925+
generate_non_array_guard(load_object_klass(src), slow_region, &src);
5926+
generate_non_array_guard(load_object_klass(dest), slow_region, &dest);
59195927

59205928
// (2) src and dest arrays must have elements of the same BasicType
59215929
// done at macro expansion or at Ideal transformation time
@@ -8531,7 +8539,7 @@ bool LibraryCallKit::inline_getObjectSize() {
85318539
PhiNode* result_val = new PhiNode(result_reg, TypeLong::LONG);
85328540
record_for_igvn(result_reg);
85338541

8534-
Node* array_ctl = generate_array_guard(klass_node, nullptr);
8542+
Node* array_ctl = generate_array_guard(klass_node, nullptr, &obj);
85358543
if (array_ctl != nullptr) {
85368544
// Array case: size is round(header + element_size*arraylength).
85378545
// 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
@@ -1473,16 +1473,17 @@ class TypeAryPtr : public TypeOopPtr {
14731473
virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
14741474

14751475
// Convenience common pre-built types.
1476-
static const TypeAryPtr *RANGE;
1477-
static const TypeAryPtr *OOPS;
1478-
static const TypeAryPtr *NARROWOOPS;
1479-
static const TypeAryPtr *BYTES;
1480-
static const TypeAryPtr *SHORTS;
1481-
static const TypeAryPtr *CHARS;
1482-
static const TypeAryPtr *INTS;
1483-
static const TypeAryPtr *LONGS;
1484-
static const TypeAryPtr *FLOATS;
1485-
static const TypeAryPtr *DOUBLES;
1476+
static const TypeAryPtr* BOTTOM;
1477+
static const TypeAryPtr* RANGE;
1478+
static const TypeAryPtr* OOPS;
1479+
static const TypeAryPtr* NARROWOOPS;
1480+
static const TypeAryPtr* BYTES;
1481+
static const TypeAryPtr* SHORTS;
1482+
static const TypeAryPtr* CHARS;
1483+
static const TypeAryPtr* INTS;
1484+
static const TypeAryPtr* LONGS;
1485+
static const TypeAryPtr* FLOATS;
1486+
static const TypeAryPtr* DOUBLES;
14861487
// selects one of the above:
14871488
static const TypeAryPtr *get_array_body_type(BasicType elem) {
14881489
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)