-
Notifications
You must be signed in to change notification settings - Fork 137
8372700: [lworld] compiler/c2/irTests/stable/* fail with --enable-preview #1826
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: lworld
Are you sure you want to change the base?
Changes from all commits
a6885a2
1c7d4df
7909109
276b06f
fc8d78f
2d63ba8
ceb2fa2
fee2e88
a2244c5
8b3346f
63b1d95
f87a670
9a95f29
9269cf5
80564f4
b64ff8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| /* | ||
| * Copyright (c) 2025, 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. | ||
| * | ||
| */ | ||
|
|
||
| #include "ci/ciArray.hpp" | ||
| #include "ci/ciConstant.hpp" | ||
| #include "ci/ciField.hpp" | ||
| #include "ci/ciFlatArray.hpp" | ||
| #include "ci/ciInlineKlass.hpp" | ||
| #include "ci/ciUtilities.inline.hpp" | ||
| #include "oops/oop.inline.hpp" | ||
|
|
||
| ciConstant ciFlatArray::null_marker_of_element_by_offset_impl(arrayOop ary, int index) { | ||
| if (ary == nullptr) { | ||
| return ciConstant(); | ||
| } | ||
| assert(ary->is_array(), ""); | ||
| if (index < 0 || index >= ary->length()) { | ||
| return ciConstant(); | ||
| } | ||
| assert(ary->is_objArray(), ""); | ||
| flatArrayOop objary = (flatArrayOop) ary; | ||
| jboolean elem = objary->null_marker_of_obj_at(index); | ||
| return ciConstant(T_BOOLEAN, elem); | ||
| } | ||
|
|
||
| ciConstant ciFlatArray::check_constant_null_marker_cache(int off) { | ||
| if (_constant_null_markers != nullptr) { | ||
| for (int i = 0; i < _constant_null_markers->length(); ++i) { | ||
| ConstantValue cached_val = _constant_null_markers->at(i); | ||
| if (cached_val.off() == off) { | ||
| return cached_val.value(); | ||
| } | ||
| } | ||
| } | ||
| return ciConstant(); | ||
| } | ||
|
|
||
| void ciFlatArray::add_to_constant_null_marker_cache(int off, ciConstant val) { | ||
| assert(val.is_valid(), "value must be valid"); | ||
| assert(!check_constant_value_cache(off, val.basic_type()).is_valid(), "duplicate"); | ||
| if (_constant_null_markers == nullptr) { | ||
| Arena* arena = CURRENT_ENV->arena(); | ||
| _constant_null_markers = new (arena) GrowableArray<ConstantValue>(arena, 1, 0, ConstantValue()); | ||
| } | ||
| _constant_null_markers->append(ConstantValue(off, val)); | ||
| } | ||
|
|
||
| // Current value of an element. | ||
| // Returns T_ILLEGAL if there is no element at the given index. | ||
| ciConstant ciFlatArray::null_marker_of_element_by_index(int index) { | ||
| ciConstant value = check_constant_null_marker_cache(index); | ||
| if (value.is_valid()) { | ||
| return value; | ||
| } | ||
| GUARDED_VM_ENTRY( | ||
| value = null_marker_of_element_by_offset_impl(get_arrayOop(), index);) | ||
| add_to_constant_null_marker_cache(index, value); | ||
| return value; | ||
| } | ||
|
|
||
| ciConstant ciFlatArray::null_marker_of_element_by_offset(intptr_t element_offset) { | ||
| FlatArrayKlass* faklass; | ||
| GUARDED_VM_ENTRY(faklass = FlatArrayKlass::cast(get_arrayOop()->klass());) | ||
| int lh = faklass->layout_helper(); | ||
| int shift = Klass::layout_helper_log2_element_size(lh); | ||
| intptr_t header = arrayOopDesc::base_offset_in_bytes(T_FLAT_ELEMENT); | ||
| intptr_t index = (element_offset - header) >> shift; | ||
| intptr_t offset = header + (index << shift); | ||
| if (offset != element_offset || index != (jint) index || index < 0 || index >= length()) { | ||
| return ciConstant(); | ||
| } | ||
| return null_marker_of_element_by_index((jint) index); | ||
| } | ||
|
|
||
| ciConstant ciFlatArray::element_value_by_offset(intptr_t element_offset) { | ||
| FlatArrayKlass* faklass; | ||
| GUARDED_VM_ENTRY(faklass = FlatArrayKlass::cast(get_arrayOop()->klass());) | ||
| int lh = faklass->layout_helper(); | ||
| int shift = Klass::layout_helper_log2_element_size(lh); | ||
| intptr_t header = arrayOopDesc::base_offset_in_bytes(T_FLAT_ELEMENT); | ||
| intptr_t index = (element_offset - header) >> shift; | ||
| intptr_t offset = header + (index << shift); | ||
| if (offset != element_offset || index != (jint) index || index < 0 || index >= length()) { | ||
| return ciConstant(); | ||
| } | ||
| return element_value((jint) index); | ||
| } | ||
|
|
||
| ciConstant ciFlatArray::field_value_by_offset(intptr_t field_offset) { | ||
| ciInlineKlass* elt_type = element_type()->as_inline_klass(); | ||
| FlatArrayKlass* faklass; | ||
| GUARDED_VM_ENTRY(faklass = FlatArrayKlass::cast(get_arrayOop()->klass());) | ||
| int lh = faklass->layout_helper(); | ||
| int shift = Klass::layout_helper_log2_element_size(lh); | ||
| intptr_t header = arrayOopDesc::base_offset_in_bytes(T_FLAT_ELEMENT); | ||
| intptr_t index = (field_offset - header) >> shift; | ||
| intptr_t element_offset = header + (index << shift); | ||
| int field_offset_in_element = (int)(field_offset - element_offset); | ||
| ciField* field = elt_type->get_field_by_offset(elt_type->payload_offset() + field_offset_in_element, false); | ||
| if (field == nullptr) { | ||
| if (field_offset_in_element != elt_type->null_marker_offset_in_payload()) { | ||
| return ciConstant(); | ||
| } | ||
| } | ||
|
|
||
| if (index != (jint) index || index < 0 || index >= length()) { | ||
| return ciConstant(); | ||
| } | ||
| ciConstant elt = field_value((jint) index, field); | ||
|
|
||
| return elt; | ||
| } | ||
|
|
||
| ciConstant ciFlatArray::field_value(int index, ciField* field) { | ||
| BasicType elembt = element_basic_type(); | ||
| ciConstant value = check_constant_value_cache(index, elembt); | ||
| if (value.is_valid()) { | ||
| if (field == nullptr) { | ||
| return value.as_object()->as_instance()->null_marker_value(); | ||
| } | ||
| return value.as_object()->as_instance()->field_value(field); | ||
| } | ||
| GUARDED_VM_ENTRY( | ||
| value = element_value_impl(T_OBJECT, get_arrayOop(), index); | ||
| ) | ||
|
|
||
| add_to_constant_value_cache(index, value); | ||
|
|
||
| if (field == nullptr) { | ||
| return value.as_object()->as_instance()->null_marker_value(); | ||
| } | ||
| return value.as_object()->as_instance()->field_value(field); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ | |
|
|
||
| #include "ci/ciConstant.hpp" | ||
| #include "ci/ciField.hpp" | ||
| #include "ci/ciInlineKlass.hpp" | ||
| #include "ci/ciInstance.hpp" | ||
| #include "ci/ciInstanceKlass.hpp" | ||
| #include "ci/ciNullObject.hpp" | ||
|
|
@@ -100,6 +101,15 @@ ciConstant ciInstance::field_value_impl(BasicType field_btype, int offset) { | |
| return value; | ||
| } | ||
|
|
||
| // Constant value of the null marker. | ||
| ciConstant ciInstance::null_marker_value() { | ||
| if (!klass()->is_inlinetype()) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be an assert?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Matter of point of view. I prefer to have the semantics rather than At call site, in the first case, I need to in the second, I need to do I prefer the first pattern, it's rather safer, and I think a lot of the code involving ciConstant have this behavior of "you get the constant if I can, otherwise, you get invalid". |
||
| return ciConstant(); | ||
| } | ||
| ciInlineKlass* ik = klass()->as_inline_klass(); | ||
| return field_value_impl(T_BOOLEAN, ik->null_marker_offset_in_payload() + ik->payload_offset()); | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------ | ||
| // ciInstance::field_value | ||
| // | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need a cache here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe? I read
valhalla/src/hotspot/share/ci/ciObject.hpp
Lines 62 to 63 in 69399ce
and
valhalla/src/hotspot/share/ci/ciObject.cpp
Lines 173 to 175 in 69399ce
It seems to be more a correctness thing than a performance matter. It couldn't see why I wouldn't have a similar risk.