rt: Inline get_sp_limit/set_sp_limit/get_sp for x86_64.

This commit is contained in:
Luqman Aden 2013-03-17 21:40:59 -07:00
parent f54adca7c9
commit d1778767cc
7 changed files with 175 additions and 64 deletions

29
src/rt/arch/arm/sp.h Normal file
View File

@ -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

29
src/rt/arch/i386/sp.h Normal file
View File

@ -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

29
src/rt/arch/mips/sp.h Normal file
View File

@ -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

View File

@ -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

71
src/rt/arch/x86_64/sp.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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