Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,9 +649,10 @@ static void gen_c2i_adapter(MacroAssembler *masm,
has_inline_argument = (sig_extended->at(i)._bt == T_METADATA);
}
if (has_inline_argument) {
// There is at least an inline type argument: we're coming from
// compiled code so we have no buffers to back the inline types
// Allocate the buffers here with a runtime call.
// There is at least a value type argument: we're coming from
// compiled code so we may not have buffers to back the value
// objects. Allocate the buffers here with a runtime call for
// the value arguments that needs a buffer.
RegisterSaver reg_save(true /* save_vectors */);
OopMap* map = reg_save.save_live_registers(masm, 0, &frame_size_in_words);

Expand Down
7 changes: 4 additions & 3 deletions src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -919,9 +919,10 @@ static void gen_c2i_adapter(MacroAssembler *masm,
has_inline_argument = (sig_extended->at(i)._bt == T_METADATA);
}
if (has_inline_argument) {
// There is at least an inline type argument: we're coming from
// compiled code so we have no buffers to back the inline types.
// Allocate the buffers here with a runtime call.
// There is at least a value type argument: we're coming from
// compiled code so we may not have buffers to back the value
// objects. Allocate the buffers here with a runtime call for
// the value arguments that needs a buffer.
OopMap* map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_wide_vectors*/ false);

frame_complete = __ offset();
Expand Down
22 changes: 17 additions & 5 deletions src/hotspot/share/runtime/sharedRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3347,6 +3347,9 @@ bool AdapterHandlerLibrary::generate_adapter_code(AdapterHandlerEntry* handler,
GrowableArray<SigEntry>* heap_sig = new (mtInternal) GrowableArray<SigEntry>(ces.sig_cc()->length(), mtInternal);
heap_sig->appendAll(ces.sig_cc());
handler->set_sig_cc(heap_sig);
heap_sig = new (mtInternal) GrowableArray<SigEntry>(ces.sig_cc_ro()->length(), mtInternal);
heap_sig->appendAll(ces.sig_cc_ro());
handler->set_sig_cc_ro(heap_sig);
}
// On zero there is no code to save and no need to create a blob and
// or relocate the handler.
Expand Down Expand Up @@ -3416,6 +3419,7 @@ void AdapterHandlerEntry::remove_unshareable_info() {
_adapter_blob = nullptr;
_linked = false;
_sig_cc = nullptr;
_sig_cc_ro = nullptr;
}

class CopyAdapterTableToArchive : StackObj {
Expand Down Expand Up @@ -3507,6 +3511,9 @@ void AdapterHandlerEntry::link() {
GrowableArray<SigEntry>* heap_sig = new (mtInternal) GrowableArray<SigEntry>(ces.sig_cc()->length(), mtInternal);
heap_sig->appendAll(ces.sig_cc());
set_sig_cc(heap_sig);
heap_sig = new (mtInternal) GrowableArray<SigEntry>(ces.sig_cc_ro()->length(), mtInternal);
heap_sig->appendAll(ces.sig_cc_ro());
set_sig_cc_ro(heap_sig);
}
}
} else {
Expand Down Expand Up @@ -3610,6 +3617,9 @@ AdapterHandlerEntry::~AdapterHandlerEntry() {
if (_sig_cc != nullptr) {
delete _sig_cc;
}
if (_sig_cc_ro != nullptr) {
delete _sig_cc_ro;
}
#ifdef ASSERT
FREE_C_HEAP_ARRAY(unsigned char, _saved_code);
#endif
Expand Down Expand Up @@ -4072,7 +4082,7 @@ oop SharedRuntime::allocate_inline_types_impl(JavaThread* current, methodHandle
callerFrame = callerFrame.sender(&reg_map2);
}
int arg_size;
const GrowableArray<SigEntry>* sig = callee->adapter()->get_sig_cc();
const GrowableArray<SigEntry>* sig = allocate_receiver ? callee->adapter()->get_sig_cc() : callee->adapter()->get_sig_cc_ro();
assert(sig != nullptr, "sig should never be null");
TempNewSymbol tmp_sig = SigEntry::create_symbol(sig);
VMRegPair* reg_pairs = find_callee_arguments(tmp_sig, false, false, &arg_size);
Expand Down Expand Up @@ -4110,9 +4120,10 @@ oop SharedRuntime::allocate_inline_types_impl(JavaThread* current, methodHandle
assert(reg_pos < (uint)arg_size, "");
VMRegPair reg_pair = reg_pairs[reg_pos];
oop* buffer = callerFrame.oopmapreg_to_oop_location(reg_pair.first(), &reg_map2);
instanceHandle h_buffer(THREAD, (instanceOop)*buffer);
InlineKlass* vk = InlineKlass::cast(holder);
if (*buffer != nullptr) {
assert((*buffer)->klass() == vk, "buffer not of expected class");
if (h_buffer.not_null()) {
assert(h_buffer->klass() == vk, "buffer not of expected class");
} else {
// Only allocate if buffer passed at the call is null
if (array_oop == nullptr) {
Expand Down Expand Up @@ -4147,10 +4158,11 @@ oop SharedRuntime::allocate_inline_types_impl(JavaThread* current, methodHandle
assert(reg_pos < (uint)arg_size, "out of bound register?");
VMRegPair reg_pair = reg_pairs[reg_pos];
oop* buffer = callerFrame.oopmapreg_to_oop_location(reg_pair.first(), &reg_map2);
instanceHandle h_buffer(THREAD, (instanceOop)*buffer);
InlineKlass* vk = ss.as_inline_klass(holder);
assert(vk != nullptr, "Unexpected klass");
if (*buffer != nullptr) {
assert((*buffer)->klass() == vk, "buffer not of expected class");
if (h_buffer.not_null()) {
assert(h_buffer->klass() == vk, "buffer not of expected class");
} else {
// Only allocate if buffer passed at the call is null
if (array_oop == nullptr) {
Expand Down
6 changes: 5 additions & 1 deletion src/hotspot/share/runtime/sharedRuntime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@ class AdapterHandlerEntry : public MetaspaceObj {

// Support for scalarized inline type calling convention
const GrowableArray<SigEntry>* _sig_cc;
const GrowableArray<SigEntry>* _sig_cc_ro;

#ifdef ASSERT
// Captures code and signature used to generate this adapter when
Expand All @@ -748,7 +749,8 @@ class AdapterHandlerEntry : public MetaspaceObj {
_adapter_blob(nullptr),
_id(id),
_linked(false),
_sig_cc(nullptr)
_sig_cc(nullptr),
_sig_cc_ro(nullptr)
#ifdef ASSERT
, _saved_code(nullptr),
_saved_code_length(0)
Expand Down Expand Up @@ -850,6 +852,8 @@ class AdapterHandlerEntry : public MetaspaceObj {
// Support for scalarized inline type calling convention
void set_sig_cc(const GrowableArray<SigEntry>* sig) { _sig_cc = sig; }
const GrowableArray<SigEntry>* get_sig_cc() const { return _sig_cc; }
void set_sig_cc_ro(const GrowableArray<SigEntry>* sig) { _sig_cc_ro = sig; }
const GrowableArray<SigEntry>* get_sig_cc_ro() const { return _sig_cc_ro; }

uint id() const { return _id; }
AdapterFingerPrint* fingerprint() const { return _fingerprint; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2026 IBM Corporation. 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 8381563
* @summary [lworld] SharedRuntime::allocate_inline_types hits "buffer not of expected class" assert
* @enablePreview
* @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
* @run main/othervm -XX:-BackgroundCompilation
* -XX:CompileOnly=compiler.valhalla.inlinetypes.TestScalarizedCCReceiverOnlyEntryAllocBuffer::test1
* ${test.main.class}
*/

package compiler.valhalla.inlinetypes;

public class TestScalarizedCCReceiverOnlyEntryAllocBuffer {

static Object field1;

public static void main(String[] args) {
MyValue2 v2 = new MyValue2(42);
MyValue3 v3 = new MyValue3(42);
MyValue4 v4 = new MyValue4(42);

for (int i = 0; i < 20_000; i++) {
test1(v2);
test1(v3);
test1(v4);
}
}

static void test1(I i) {
MyValue1 v1 = new MyValue1(42);
field1 = v1;
i.m(v1);
}


static value class MyValue1 {
int intField;

MyValue1(int intField) {
this.intField = intField;
}
}

static interface I {
default public void m(MyValue1 v) {
}
}

static value class MyValue2 implements I {
int intField;

MyValue2(int intField) {
this.intField = intField;
}

public void m(MyValue1 v) {
}
}

static value class MyValue3 implements I {
int intField;

MyValue3(int intField) {
this.intField = intField;
}

public void m(MyValue1 v) {
}
}

static value class MyValue4 implements I {
int intField;

MyValue4(int intField) {
this.intField = intField;
}

public void m(MyValue1 v) {
}
}
}