11/*
2- * Copyright (c) 2020, 2025 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2020, 2026 , Oracle and/or its affiliates. All rights reserved.
33 * Copyright (c) 2019, Arm Limited. All rights reserved.
44 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55 *
@@ -146,10 +146,10 @@ void DowncallLinker::StubGenerator::generate() {
146146
147147 bool should_save_return_value = !_needs_return_buffer;
148148 RegSpiller out_reg_spiller (_output_registers);
149- int spill_offset = -1 ;
149+ int out_spill_offset = -1 ;
150150
151151 if (should_save_return_value) {
152- spill_offset = 0 ;
152+ out_spill_offset = 0 ;
153153 // spill area can be shared with shadow space and out args,
154154 // since they are only used before the call,
155155 // and spill area is only used after.
@@ -174,6 +174,9 @@ void DowncallLinker::StubGenerator::generate() {
174174 // FP-> | |
175175 // |---------------------| = frame_bottom_offset = frame_size
176176 // | (optional) |
177+ // | in_reg_spiller area |
178+ // |---------------------|
179+ // | (optional) |
177180 // | capture state buf |
178181 // |---------------------| = StubLocations::CAPTURED_STATE_BUFFER
179182 // | (optional) |
@@ -187,6 +190,19 @@ void DowncallLinker::StubGenerator::generate() {
187190 GrowableArray<VMStorage> out_regs = ForeignGlobals::replace_place_holders (_input_registers, locs);
188191 ArgumentShuffle arg_shuffle (filtered_java_regs, out_regs, shuffle_reg);
189192
193+ // Need to spill for state capturing runtime call.
194+ // The area spilled into is distinct from the capture state buffer.
195+ RegSpiller in_reg_spiller (out_regs);
196+ int in_spill_offset = -1 ;
197+ if (_captured_state_mask != 0 ) {
198+ // The spill area cannot be shared with the out_spill since
199+ // spilling needs to happen before the call. Allocate a new
200+ // region in the stack for this spill space.
201+ in_spill_offset = allocated_frame_size;
202+ allocated_frame_size += in_reg_spiller.spill_size_bytes ();
203+ }
204+
205+
190206#ifndef PRODUCT
191207 LogTarget (Trace, foreign, downcall) lt;
192208 if (lt.is_enabled ()) {
@@ -228,6 +244,20 @@ void DowncallLinker::StubGenerator::generate() {
228244 arg_shuffle.generate (_masm, shuffle_reg, 0 , _abi._shadow_space_bytes );
229245 __ block_comment (" } argument shuffle" );
230246
247+ if (_captured_state_mask != 0 ) {
248+ assert (in_spill_offset != -1 , " must be" );
249+ __ block_comment (" { load initial thread local" );
250+ in_reg_spiller.generate_spill (_masm, in_spill_offset);
251+
252+ // Copy the contents of the capture state buffer into thread local
253+ __ ldr (c_rarg0, Address (sp, locs.data_offset (StubLocations::CAPTURED_STATE_BUFFER)));
254+ __ movw (c_rarg1, _captured_state_mask);
255+ __ rt_call (CAST_FROM_FN_PTR (address, DowncallLinker::capture_state_pre), tmp1);
256+
257+ in_reg_spiller.generate_fill (_masm, in_spill_offset);
258+ __ block_comment (" } load initial thread local" );
259+ }
260+
231261 __ blr (as_Register (locs.get (StubLocations::TARGET_ADDRESS)));
232262 // this call is assumed not to have killed rthread
233263
@@ -254,15 +284,15 @@ void DowncallLinker::StubGenerator::generate() {
254284 __ block_comment (" { save thread local" );
255285
256286 if (should_save_return_value) {
257- out_reg_spiller.generate_spill (_masm, spill_offset );
287+ out_reg_spiller.generate_spill (_masm, out_spill_offset );
258288 }
259289
260290 __ ldr (c_rarg0, Address (sp, locs.data_offset (StubLocations::CAPTURED_STATE_BUFFER)));
261291 __ movw (c_rarg1, _captured_state_mask);
262- __ rt_call (CAST_FROM_FN_PTR (address, DowncallLinker::capture_state ), tmp1);
292+ __ rt_call (CAST_FROM_FN_PTR (address, DowncallLinker::capture_state_post ), tmp1);
263293
264294 if (should_save_return_value) {
265- out_reg_spiller.generate_fill (_masm, spill_offset );
295+ out_reg_spiller.generate_fill (_masm, out_spill_offset );
266296 }
267297
268298 __ block_comment (" } save thread local" );
@@ -321,7 +351,7 @@ void DowncallLinker::StubGenerator::generate() {
321351
322352 if (should_save_return_value) {
323353 // Need to save the native result registers around any runtime calls.
324- out_reg_spiller.generate_spill (_masm, spill_offset );
354+ out_reg_spiller.generate_spill (_masm, out_spill_offset );
325355 }
326356
327357 __ mov (c_rarg0, rthread);
@@ -330,7 +360,7 @@ void DowncallLinker::StubGenerator::generate() {
330360 __ blr (tmp1);
331361
332362 if (should_save_return_value) {
333- out_reg_spiller.generate_fill (_masm, spill_offset );
363+ out_reg_spiller.generate_fill (_masm, out_spill_offset );
334364 }
335365
336366 __ b (L_after_safepoint_poll);
@@ -342,13 +372,13 @@ void DowncallLinker::StubGenerator::generate() {
342372 __ bind (L_reguard);
343373
344374 if (should_save_return_value) {
345- out_reg_spiller.generate_spill (_masm, spill_offset );
375+ out_reg_spiller.generate_spill (_masm, out_spill_offset );
346376 }
347377
348378 __ rt_call (CAST_FROM_FN_PTR (address, SharedRuntime::reguard_yellow_pages), tmp1);
349379
350380 if (should_save_return_value) {
351- out_reg_spiller.generate_fill (_masm, spill_offset );
381+ out_reg_spiller.generate_fill (_masm, out_spill_offset );
352382 }
353383
354384 __ b (L_after_reguard);
0 commit comments