(L) Prelim RFR: 8132510: Replace ThreadLocalStorage with compiler/language-based thread-local variables
Andrew Haley
aph at redhat.com
Thu Nov 5 16:01:14 UTC 2015
On 11/05/2015 10:20 AM, Andrew Haley wrote:
> On 05/11/15 04:36, David Holmes wrote:
>> I still need some assistance from Aarch64 folk to write their get_thread
>> function please!
Here you are.
I found a bug in the existing AArch64 get_thread.
The specification of MacroAssembler::get_thread() is that it clobbers
no registers. Most of the vector state is callee-clobbered, so if you
want to call a get_thread() method which is written in C you have to
save the entire vector state as well as all call-clobbered general
registers. You have to do this because it is possible that GCC will
use a vector register for temporary storage. (This is not just a
theoretical possibility: I have seen AArch64 bugs caused by this
actually happening.) So, I wrote code to save all the general and
vector registers. It was horrible.
I scrapped it and instead wrote a little assembly-language routine
which returns the contents of Thread::_thr_current. This clobbers
only a couple of registers, and everything is much nicer.
I suppose it might have been possible to change the specification of
MacroAssembler::get_thread() so that it clobbered the vector state,
but never mind: it's done now.
Andrew.
-------------- next part --------------
diff --git a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
@@ -4651,23 +4651,22 @@
sub(result, result, len); // Return index where we stopped
}
-// get_thread can be called anywhere inside generated code so we need
-// to save whatever non-callee save context might get clobbered by the
-// call to Thread::current or, indeed, the call setup code.
-// x86 appears to save C arg registers.
-
+// get_thread() can be called anywhere inside generated code so we
+// need to save whatever non-callee save context might get clobbered
+// by the call to JavaThread::aarch64_get_thread_helper() or, indeed,
+// the call setup code.
+//
+// aarch64_get_thread_helper() clobbers only r0, r1, and flags.
+//
void MacroAssembler::get_thread(Register dst) {
-
- // Save all call-clobbered regs except dst, plus r19 and r20.
- RegSet saved_regs = RegSet::range(r0, r20) + lr - dst;
+ RegSet saved_regs = RegSet::range(r0, r1) + lr - dst;
push(saved_regs, sp);
- // FIX-ME: implement
- // return Thread::current()
-
+ mov(lr, CAST_FROM_FN_PTR(address, JavaThread::aarch64_get_thread_helper));
+ blrt(lr, 1, 0, 1);
if (dst != c_rarg0) {
mov(dst, c_rarg0);
}
- // restore pushed registers
+
pop(saved_regs, sp);
}
diff --git a/src/os_cpu/linux_aarch64/vm/threadLS_linux_aarch64.s b/src/os_cpu/linux_aarch64/vm/threadLS_linux_aarch64.s
new file mode 100644
--- /dev/null
+++ b/src/os_cpu/linux_aarch64/vm/threadLS_linux_aarch64.s
@@ -0,0 +1,44 @@
+// Copyright (c) 2015, Red Hat Inc. 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.
+
+ // JavaThread::aarch64_get_thread_helper()
+ //
+ // Return the current thread pointer in x0.
+ // Clobber x1, flags.
+ // All other registers are preserved,
+
+ .global _ZN10JavaThread25aarch64_get_thread_helperEv
+ .type _ZN10JavaThread25aarch64_get_thread_helperEv, %function
+
+_ZN10JavaThread25aarch64_get_thread_helperEv:
+ stp x29, x30, [sp, -16]!
+ adrp x0, :tlsdesc:_ZN6Thread12_thr_currentE
+ ldr x1, [x0, #:tlsdesc_lo12:_ZN6Thread12_thr_currentE]
+ add x0, x0, :tlsdesc_lo12:_ZN6Thread12_thr_currentE
+ .tlsdesccall _ZN6Thread12_thr_currentE
+ blr x1
+ mrs x1, tpidr_el0
+ add x0, x1, x0
+ ldr x0, [x0]
+ ldp x29, x30, [sp], 16
+ ret
+
+ .size _ZN10JavaThread25aarch64_get_thread_helperEv, .-_ZN10JavaThread25aarch64_get_thread_helperEv
diff --git a/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp b/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp
--- a/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp
+++ b/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp
@@ -77,6 +77,8 @@
bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava);
public:
+ static Thread *aarch64_get_thread_helper();
+
// These routines are only used on cpu architectures that
// have separate register stacks (Itanium).
static bool register_stack_overflow() { return false; }
More information about the hotspot-dev
mailing list