summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/heap/RegisterState.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/heap/RegisterState.h')
-rw-r--r--Source/JavaScriptCore/heap/RegisterState.h158
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
+