diff options
Diffstat (limited to 'Source/JavaScriptCore/heap/RegisterState.h')
| -rw-r--r-- | Source/JavaScriptCore/heap/RegisterState.h | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/heap/RegisterState.h b/Source/JavaScriptCore/heap/RegisterState.h new file mode 100644 index 000000000..6005a9143 --- /dev/null +++ b/Source/JavaScriptCore/heap/RegisterState.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <setjmp.h> + +namespace JSC { + +#if !OS(WINDOWS) + +// ALLOCATE_AND_GET_REGISTER_STATE has to ensure that the GC sees callee-saves. It achieves this by +// ensuring that the callee-saves are either spilled to the stack or saved in the RegisterState. The code +// looks like it's achieving only the latter. However, it's possible that the compiler chooses to use +// a callee-save for one of the caller's variables, which means that the value that we were interested in +// got spilled. In that case, we will store something bogus into the RegisterState, and that's OK. + +#if CPU(X86) +struct RegisterState { + uint32_t ebx; + uint32_t edi; + uint32_t esi; +}; + +#define SAVE_REG(regname, where) \ + asm volatile ("movl %%" #regname ", %0" : "=m"(where) : : "memory") + +#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \ + RegisterState registers; \ + SAVE_REG(ebx, registers.ebx); \ + SAVE_REG(edi, registers.edi); \ + SAVE_REG(esi, registers.esi) + +#elif CPU(X86_64) +struct RegisterState { + uint64_t rbx; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; +}; + +#define SAVE_REG(regname, where) \ + asm volatile ("movq %%" #regname ", %0" : "=m"(where) : : "memory") + +#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \ + RegisterState registers; \ + SAVE_REG(rbx, registers.rbx); \ + SAVE_REG(r12, registers.r12); \ + SAVE_REG(r13, registers.r13); \ + SAVE_REG(r14, registers.r14); \ + SAVE_REG(r15, registers.r15) + +#elif CPU(ARM_THUMB2) +struct RegisterState { + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; +}; + +#define SAVE_REG(regname, where) \ + asm volatile ("str " #regname ", %0" : "=m"(where) : : "memory") + +#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \ + RegisterState registers; \ + SAVE_REG(r4, registers.r4); \ + SAVE_REG(r5, registers.r5); \ + SAVE_REG(r6, registers.r6); \ + SAVE_REG(r8, registers.r8); \ + SAVE_REG(r9, registers.r9); \ + SAVE_REG(r10, registers.r10); \ + SAVE_REG(r11, registers.r11) + +#elif CPU(ARM64) +struct RegisterState { + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; +}; + +#define SAVE_REG(regname, where) \ + asm volatile ("str " #regname ", %0" : "=m"(where) : : "memory") + +#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \ + RegisterState registers; \ + SAVE_REG(x19, registers.x19); \ + SAVE_REG(x20, registers.x20); \ + SAVE_REG(x21, registers.x21); \ + SAVE_REG(x22, registers.x22); \ + SAVE_REG(x23, registers.x23); \ + SAVE_REG(x24, registers.x24); \ + SAVE_REG(x25, registers.x25); \ + SAVE_REG(x26, registers.x26); \ + SAVE_REG(x27, registers.x27); \ + SAVE_REG(x28, registers.x28) + +#endif +#endif // !OS(WINDOWS) + +#ifndef ALLOCATE_AND_GET_REGISTER_STATE +#if COMPILER(GCC_OR_CLANG) +#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*)))) +#else +#define REGISTER_BUFFER_ALIGNMENT +#endif + +typedef jmp_buf RegisterState; + +// ALLOCATE_AND_GET_REGISTER_STATE() is a macro so that it is always "inlined" even in debug builds. +#if COMPILER(MSVC) +#pragma warning(push) +#pragma warning(disable: 4611) +#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \ + RegisterState registers REGISTER_BUFFER_ALIGNMENT; \ + setjmp(registers) +#pragma warning(pop) +#else +#define ALLOCATE_AND_GET_REGISTER_STATE(registers) \ + RegisterState registers REGISTER_BUFFER_ALIGNMENT; \ + setjmp(registers) +#endif +#endif // ALLOCATE_AND_GET_REGISTER_STATE + +} // namespace JSC + |
