< prev index next > src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp
Print this page
/*
! * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. 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
/*
! * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. 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
}
break;
case StubId::c1_new_type_array_id:
case StubId::c1_new_object_array_id:
{
Register length = x9; // Incoming
Register klass = x13; // Incoming
Register obj = x10; // Result
if (id == StubId::c1_new_type_array_id) {
__ set_info("new_type_array", dont_gc_arguments);
! } else {
__ set_info("new_object_array", dont_gc_arguments);
}
#ifdef ASSERT
// assert object type is really an array of the proper kind
{
Label ok;
Register tmp = obj;
__ lwu(tmp, Address(klass, Klass::layout_helper_offset()));
__ sraiw(tmp, tmp, Klass::_lh_array_tag_shift);
! int tag = ((id == StubId::c1_new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_obj_value);
! __ mv(t0, tag);
! __ beq(t0, tmp, ok);
! __ stop("assert(is an array klass)");
__ should_not_reach_here();
__ bind(ok);
}
#endif // ASSERT
}
break;
case StubId::c1_new_type_array_id:
case StubId::c1_new_object_array_id:
+ case StubId::c1_new_null_free_array_id:
{
Register length = x9; // Incoming
Register klass = x13; // Incoming
Register obj = x10; // Result
if (id == StubId::c1_new_type_array_id) {
__ set_info("new_type_array", dont_gc_arguments);
! } else if (id == StubId::c1_new_object_array_id) {
__ set_info("new_object_array", dont_gc_arguments);
+ } else {
+ assert(id == StubId::c1_new_null_free_array_id, "must be");
+ __ set_info("new_null_free_array", dont_gc_arguments);
}
#ifdef ASSERT
// assert object type is really an array of the proper kind
{
Label ok;
Register tmp = obj;
__ lwu(tmp, Address(klass, Klass::layout_helper_offset()));
__ sraiw(tmp, tmp, Klass::_lh_array_tag_shift);
!
! switch (id) {
! case StubId::c1_new_type_array_id:
! __ mv(t0, (int)Klass::_lh_array_tag_type_value);
+ __ beq(t0, tmp, ok);
+ __ stop("assert(is a type array klass)");
+ break;
+ case StubId::c1_new_object_array_id:
+ __ mv(t0, (int)Klass::_lh_array_tag_ref_value); // new "[Ljava/lang/Object;"
+ __ beq(t0, tmp, ok);
+ __ mv(t0, (int)Klass::_lh_array_tag_flat_value); // new "[LVT;"
+ __ beq(t0, tmp, ok);
+ __ stop("assert(is an object or inline type array klass)");
+ break;
+ case StubId::c1_new_null_free_array_id:
+ __ mv(t0, (int)Klass::_lh_array_tag_flat_value); // the array can be a flat array.
+ __ beq(t0, tmp, ok);
+ __ mv(t0, (int)Klass::_lh_array_tag_ref_value); // the array cannot be a flat array (due to the InlineArrayElementMaxFlatSize, etc.)
+ __ beq(t0, tmp, ok);
+ __ stop("assert(is an object or inline type array klass)");
+ break;
+ default: ShouldNotReachHere();
+ }
+
__ should_not_reach_here();
__ bind(ok);
}
#endif // ASSERT
OopMap* map = save_live_registers(sasm);
assert_cond(map != nullptr);
int call_offset = 0;
if (id == StubId::c1_new_type_array_id) {
call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);
! } else {
call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);
}
oop_maps = new OopMapSet();
assert_cond(oop_maps != nullptr);
oop_maps->add_gc_map(call_offset, map);
OopMap* map = save_live_registers(sasm);
assert_cond(map != nullptr);
int call_offset = 0;
if (id == StubId::c1_new_type_array_id) {
call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);
! } else if (id == StubId::c1_new_object_array_id) {
call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);
+ } else {
+ call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_null_free_array), klass, length);
}
oop_maps = new OopMapSet();
assert_cond(oop_maps != nullptr);
oop_maps->add_gc_map(call_offset, map);
// x10: new multi array
__ verify_oop(x10);
}
break;
+ case StubId::c1_buffer_inline_args_id:
+ case StubId::c1_buffer_inline_args_no_receiver_id:
+ {
+ const char* name = (id == StubId::c1_buffer_inline_args_id) ?
+ "buffer_inline_args" : "buffer_inline_args_no_receiver";
+ StubFrame f(sasm, name, dont_gc_arguments);
+ OopMap* map = save_live_registers(sasm);
+ Register method = x9; // Incoming
+ address entry = (id == StubId::c1_buffer_inline_args_id) ?
+ CAST_FROM_FN_PTR(address, buffer_inline_args) :
+ CAST_FROM_FN_PTR(address, buffer_inline_args_no_receiver);
+ // This is called from a C1 method's scalarized entry point
+ // where x10-x17 may be holding live argument values so we can't
+ // return the result in x10 as the other stubs do. RA is used as
+ // a temporary below to avoid the result being clobbered by
+ // restore_live_registers. It's saved and restored by
+ // StubAssembler::prologue and epilogue anyway.
+ int call_offset = __ call_RT(ra, noreg, entry, method);
+ oop_maps = new OopMapSet();
+ oop_maps->add_gc_map(call_offset, map);
+ restore_live_registers(sasm);
+ __ mv(x18, ra);
+ __ verify_oop(x18); // x18: an array of buffered value objects
+ }
+ break;
+
+ case StubId::c1_load_flat_array_id:
+ {
+ StubFrame f(sasm, "load_flat_array", dont_gc_arguments);
+ OopMap* map = save_live_registers(sasm);
+
+ // Called with store_parameter and not C abi
+
+ f.load_argument(1, x10); // x10,: array
+ f.load_argument(0, x11); // x11,: index
+ int call_offset = __ call_RT(x10, noreg, CAST_FROM_FN_PTR(address, load_flat_array), x10, x11);
+
+ // Ensure the stores that initialize the buffer are visible
+ // before many subsequent store that publishes this reference.
+ __ membar(MacroAssembler::StoreStore);
+
+ oop_maps = new OopMapSet();
+ oop_maps->add_gc_map(call_offset, map);
+ restore_live_registers_except_r10(sasm);
+
+ // x10: loaded element at array[index]
+ __ verify_oop(x10);
+ }
+ break;
+
+ case StubId::c1_store_flat_array_id:
+ {
+ StubFrame f(sasm, "store_flat_array", dont_gc_arguments);
+ OopMap* map = save_live_registers(sasm);
+
+ // Called with store_parameter and not C abi
+
+ f.load_argument(2, x10); // x10: array
+ f.load_argument(1, x11); // x11: index
+ f.load_argument(0, x12); // x12: value
+ int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, store_flat_array), x10, x11, x12);
+
+ oop_maps = new OopMapSet();
+ oop_maps->add_gc_map(call_offset, map);
+ restore_live_registers_except_r10(sasm);
+ }
+ break;
+
+ case StubId::c1_substitutability_check_id:
+ {
+ StubFrame f(sasm, "substitutability_check", dont_gc_arguments);
+ OopMap* map = save_live_registers(sasm);
+
+ // Called with store_parameter and not C abi
+
+ f.load_argument(1, x11); // x11,: left
+ f.load_argument(0, x12); // x12,: right
+ int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, substitutability_check), x11, x12);
+
+ oop_maps = new OopMapSet();
+ oop_maps->add_gc_map(call_offset, map);
+ restore_live_registers_except_r10(sasm);
+
+ // x10,: are the two operands substitutable
+ }
+ break;
+
case StubId::c1_register_finalizer_id:
{
__ set_info("register_finalizer", dont_gc_arguments);
// This is called via call_runtime so the arguments
}
break;
case StubId::c1_throw_incompatible_class_change_error_id:
{
! StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments, does_not_return);
oop_maps = generate_exception_throw(sasm,
CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
}
break;
case StubId::c1_slow_subtype_check_id:
{
// Typical calling sequence:
// push klass_RInfo (object klass or other subclass)
// push sup_k_RInfo (array element klass or other superclass)
}
break;
case StubId::c1_throw_incompatible_class_change_error_id:
{
! StubFrame f(sasm, "throw_incompatible_class_change_error", dont_gc_arguments, does_not_return);
oop_maps = generate_exception_throw(sasm,
CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
}
break;
+ case StubId::c1_throw_illegal_monitor_state_exception_id:
+ { StubFrame f(sasm, "throw_illegal_monitor_state_exception", dont_gc_arguments);
+ oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_illegal_monitor_state_exception), false);
+ }
+ break;
+
+ case StubId::c1_throw_identity_exception_id:
+ { StubFrame f(sasm, "throw_identity_exception", dont_gc_arguments);
+ oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_identity_exception), true);
+ }
+ break;
+
case StubId::c1_slow_subtype_check_id:
{
// Typical calling sequence:
// push klass_RInfo (object klass or other subclass)
// push sup_k_RInfo (array element klass or other superclass)
< prev index next >