From d1778767cca290e844d5aa9d044dcc2f9edc9d8c Mon Sep 17 00:00:00 2001 From: Luqman Aden <me@luqman.ca> Date: Sun, 17 Mar 2013 21:40:59 -0700 Subject: [PATCH] rt: Inline get_sp_limit/set_sp_limit/get_sp for x86_64. --- src/rt/arch/arm/sp.h | 29 ++++++++++++++ src/rt/arch/i386/sp.h | 29 ++++++++++++++ src/rt/arch/mips/sp.h | 29 ++++++++++++++ src/rt/arch/x86_64/record_sp.S | 52 ------------------------- src/rt/arch/x86_64/sp.h | 71 ++++++++++++++++++++++++++++++++++ src/rt/rust_globals.h | 16 ++++++++ src/rt/rust_task.h | 13 +------ 7 files changed, 175 insertions(+), 64 deletions(-) create mode 100644 src/rt/arch/arm/sp.h create mode 100644 src/rt/arch/i386/sp.h create mode 100644 src/rt/arch/mips/sp.h create mode 100644 src/rt/arch/x86_64/sp.h diff --git a/src/rt/arch/arm/sp.h b/src/rt/arch/arm/sp.h new file mode 100644 index 00000000000..cd798847607 --- /dev/null +++ b/src/rt/arch/arm/sp.h @@ -0,0 +1,29 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Getting the stack pointer and getting/setting sp limit. + +#ifndef SP_H +#define SP_H + +#include "../../rust_globals.h" + +// Gets a pointer to the vicinity of the current stack pointer +extern "C" uintptr_t get_sp(); + +// Gets the pointer to the end of the Rust stack from a platform- +// specific location in the thread control block +extern "C" CDECL uintptr_t get_sp_limit(); + +// Records the pointer to the end of the Rust stack in a platform- +// specific location in the thread control block +extern "C" CDECL void record_sp_limit(void *limit); + +#endif diff --git a/src/rt/arch/i386/sp.h b/src/rt/arch/i386/sp.h new file mode 100644 index 00000000000..cd798847607 --- /dev/null +++ b/src/rt/arch/i386/sp.h @@ -0,0 +1,29 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Getting the stack pointer and getting/setting sp limit. + +#ifndef SP_H +#define SP_H + +#include "../../rust_globals.h" + +// Gets a pointer to the vicinity of the current stack pointer +extern "C" uintptr_t get_sp(); + +// Gets the pointer to the end of the Rust stack from a platform- +// specific location in the thread control block +extern "C" CDECL uintptr_t get_sp_limit(); + +// Records the pointer to the end of the Rust stack in a platform- +// specific location in the thread control block +extern "C" CDECL void record_sp_limit(void *limit); + +#endif diff --git a/src/rt/arch/mips/sp.h b/src/rt/arch/mips/sp.h new file mode 100644 index 00000000000..cd798847607 --- /dev/null +++ b/src/rt/arch/mips/sp.h @@ -0,0 +1,29 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Getting the stack pointer and getting/setting sp limit. + +#ifndef SP_H +#define SP_H + +#include "../../rust_globals.h" + +// Gets a pointer to the vicinity of the current stack pointer +extern "C" uintptr_t get_sp(); + +// Gets the pointer to the end of the Rust stack from a platform- +// specific location in the thread control block +extern "C" CDECL uintptr_t get_sp_limit(); + +// Records the pointer to the end of the Rust stack in a platform- +// specific location in the thread control block +extern "C" CDECL void record_sp_limit(void *limit); + +#endif diff --git a/src/rt/arch/x86_64/record_sp.S b/src/rt/arch/x86_64/record_sp.S index 0999e19f328..e69de29bb2d 100644 --- a/src/rt/arch/x86_64/record_sp.S +++ b/src/rt/arch/x86_64/record_sp.S @@ -1,52 +0,0 @@ -.text - -#if defined(__APPLE__) || defined(_WIN32) -#define RECORD_SP_LIMIT _record_sp_limit -#define GET_SP_LIMIT _get_sp_limit -#define GET_SP _get_sp -#else -#define RECORD_SP_LIMIT record_sp_limit -#define GET_SP_LIMIT get_sp_limit -#define GET_SP get_sp -#endif - -.globl RECORD_SP_LIMIT -.globl GET_SP_LIMIT -.globl GET_SP - -#if defined(__linux__) -RECORD_SP_LIMIT: - movq %rdi, %fs:112 - ret -#elif defined(__APPLE__) -RECORD_SP_LIMIT: - movq $0x60+90*8, %rsi - movq %rdi, %gs:(%rsi) - ret -#elif defined(__FreeBSD__) -RECORD_SP_LIMIT: - movq %rdi, %fs:24 - ret -#else -RECORD_SP_LIMIT: - ret -#endif - -#if defined(__linux__) -GET_SP_LIMIT: - movq %fs:112, %rax - ret -#elif defined(__APPLE__) -GET_SP_LIMIT: - movq $0x60+90*8, %rsi - movq %gs:(%rsi), %rax - ret -#elif defined(__FreeBSD__) -GET_SP_LIMIT: - movq %fs:24, %rax - ret -#endif - -GET_SP: - movq %rsp, %rax - ret diff --git a/src/rt/arch/x86_64/sp.h b/src/rt/arch/x86_64/sp.h new file mode 100644 index 00000000000..bf011f4d019 --- /dev/null +++ b/src/rt/arch/x86_64/sp.h @@ -0,0 +1,71 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Getting the stack pointer and getting/setting sp limit. + +#ifndef SP_H +#define SP_H + +#include "../../rust_globals.h" + +// Gets a pointer to the vicinity of the current stack pointer +extern "C" ALWAYS_INLINE uintptr_t get_sp() { + uintptr_t sp; + asm volatile ( + "movq %%rsp, %0" + : "=m"(sp)); + return sp; +} + +// Gets the pointer to the end of the Rust stack from a platform- +// specific location in the thread control block +extern "C" CDECL ALWAYS_INLINE uintptr_t get_sp_limit() { + uintptr_t limit; + +#if defined(__linux__) + asm volatile ( + "movq %%fs:112, %0" + : "=r"(limit)); +#elif defined(__APPLE__) + asm volatile ( + "movq $0x60+90*8, %%rsi\n\t" + "movq %%gs:(%%rsi), %0" + : "=r"(limit) + :: "rsi"); +#elif defined(__FreeBSD__) + asm volatile ( + "movq %%fs:24, %0" + : "=r"(limit)); +#endif + + return limit; +} + +// Records the pointer to the end of the Rust stack in a platform- +// specific location in the thread control block +extern "C" CDECL ALWAYS_INLINE void record_sp_limit(void *limit) { +#if defined(__linux__) + asm volatile ( + "movq %0, %%fs:112" + :: "r"(limit)); +#elif defined(__APPLE__) + asm volatile ( + "movq $0x60+90*8, %%rsi\n\t" + "movq %0, %%gs:(%%rsi)" + :: "r"(limit) + : "rsi"); +#elif defined(__FreeBSD__) + asm volatile ( + "movq %0, %%fs:24" + :: "r"(limit)); +#endif +} + +#endif diff --git a/src/rt/rust_globals.h b/src/rt/rust_globals.h index 3d3ce7562b5..ff57af08337 100644 --- a/src/rt/rust_globals.h +++ b/src/rt/rust_globals.h @@ -11,6 +11,22 @@ #ifndef RUST_GLOBALS_H #define RUST_GLOBALS_H +#if defined(__cplusplus) +#define INLINE inline +#elif defined(_MSC_VER) || defined(__GNUC__) +#define INLINE __inline__ +#else +#define INLINE inline +#endif + +#if defined(__GNUC__) +#define ALWAYS_INLINE __attribute((always_inline)) INLINE +#elif defined(_MSC_VER) +#define ALWAYS_INLINE __forceinline +#else +#define ALWAYS_INLINE INLINE +#endif + #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 8c9ec172c45..00d20fefc0e 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -118,6 +118,7 @@ #include "rust_stack.h" #include "rust_type.h" #include "rust_sched_loop.h" +#include "sp.h" // The amount of extra space at the end of each stack segment, available // to the rt, compiler and dynamic linker for running small functions @@ -419,15 +420,6 @@ template <typename T> struct task_owned { } }; -// This stuff is on the stack-switching fast path - -// Records the pointer to the end of the Rust stack in a platform- -// specific location in the thread control block -extern "C" CDECL void record_sp_limit(void *limit); -extern "C" CDECL uintptr_t get_sp_limit(); -// Gets a pointer to the vicinity of the current stack pointer -extern "C" uintptr_t get_sp(); - // This is the function that switches between the C and the Rust stack by // calling another function with a single void* argument while changing the // stack pointer. It has a funny name because gdb doesn't normally like to @@ -600,9 +592,6 @@ rust_task::prev_stack() { record_stack_limit(); } -extern "C" CDECL void -record_sp_limit(void *limit); - // The LLVM-generated segmented-stack function prolog compares the amount of // stack needed for each frame to the end-of-stack pointer stored in the // TCB. As an optimization, when the frame size is less than 256 bytes, it