You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2230 lines
95 KiB
2230 lines
95 KiB
From 472429e623cf48e864a7a2f10d589817a88289a1 Mon Sep 17 00:00:00 2001
|
|
From: Nikolaos Papaspyrou <nikolaos@chromium.org>
|
|
Date: Wed, 18 Jan 2023 21:11:59 +0100
|
|
Subject: [PATCH] [heap] Fix saving the callee-saved registers on stack
|
|
|
|
This CL reinstates the trampoline for pushing the values of
|
|
callee-saved registers on the stack, which is used for stack scanning.
|
|
It reintroduces the set of architecture-specific functions
|
|
PushAllRegistersAndIterateStack, removed in crrev.com/c/3989143.
|
|
The reason for this change is that the simpler architecture-specific
|
|
functions SaveCalleeSavedRegisters failed to correctly save the
|
|
values of the registers, in the presence of C++ compiler optimizations.
|
|
|
|
It also removes the stack context, introduced in crrev.com/c/4017512,
|
|
and uses again the trampoline for iterating through the stack.
|
|
|
|
Bug: v8:13257
|
|
Change-Id: I9e656a9b3ba6616168602300f2180b4f340593f3
|
|
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4171639
|
|
Commit-Queue: Nikolaos Papaspyrou <nikolaos@chromium.org>
|
|
Reviewed-by: Omer Katz <omerkatz@chromium.org>
|
|
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
|
|
Cr-Commit-Position: refs/heads/main@{#85394}
|
|
|
|
(stripped tests)
|
|
---
|
|
|
|
diff --git a/BUILD.bazel b/BUILD.bazel
|
|
index 283eeff..e3269a4 100644
|
|
--- a/v8/BUILD.bazel
|
|
+++ b/v8/BUILD.bazel
|
|
@@ -3201,16 +3201,16 @@
|
|
# Note these cannot be v8_target_is_* selects because these contain
|
|
# inline assembly that runs inside the executable. Since these are
|
|
# linked directly into mksnapshot, they must use the actual target cpu.
|
|
- "@v8//bazel/config:is_inline_asm_ia32": ["src/heap/base/asm/ia32/save_registers_asm.cc"],
|
|
- "@v8//bazel/config:is_inline_asm_x64": ["src/heap/base/asm/x64/save_registers_asm.cc"],
|
|
- "@v8//bazel/config:is_inline_asm_arm": ["src/heap/base/asm/arm/save_registers_asm.cc"],
|
|
- "@v8//bazel/config:is_inline_asm_arm64": ["src/heap/base/asm/arm64/save_registers_asm.cc"],
|
|
- "@v8//bazel/config:is_inline_asm_s390x": ["src/heap/base/asm/s390/save_registers_asm.cc"],
|
|
- "@v8//bazel/config:is_inline_asm_riscv64": ["src/heap/base/asm/riscv64/save_registers_asm.cc"],
|
|
- "@v8//bazel/config:is_inline_asm_ppc64le": ["src/heap/base/asm/ppc/save_registers_asm.cc"],
|
|
- "@v8//bazel/config:is_msvc_asm_ia32": ["src/heap/base/asm/ia32/save_registers_masm.asm"],
|
|
- "@v8//bazel/config:is_msvc_asm_x64": ["src/heap/base/asm/x64/save_registers_masm.asm"],
|
|
- "@v8//bazel/config:is_msvc_asm_arm64": ["src/heap/base/asm/arm64/save_registers_masm.S"],
|
|
+ "@v8//bazel/config:is_inline_asm_ia32": ["src/heap/base/asm/ia32/push_registers_asm.cc"],
|
|
+ "@v8//bazel/config:is_inline_asm_x64": ["src/heap/base/asm/x64/push_registers_asm.cc"],
|
|
+ "@v8//bazel/config:is_inline_asm_arm": ["src/heap/base/asm/arm/push_registers_asm.cc"],
|
|
+ "@v8//bazel/config:is_inline_asm_arm64": ["src/heap/base/asm/arm64/push_registers_asm.cc"],
|
|
+ "@v8//bazel/config:is_inline_asm_s390x": ["src/heap/base/asm/s390/push_registers_asm.cc"],
|
|
+ "@v8//bazel/config:is_inline_asm_riscv64": ["src/heap/base/asm/riscv64/push_registers_asm.cc"],
|
|
+ "@v8//bazel/config:is_inline_asm_ppc64le": ["src/heap/base/asm/ppc/push_registers_asm.cc"],
|
|
+ "@v8//bazel/config:is_msvc_asm_ia32": ["src/heap/base/asm/ia32/push_registers_masm.asm"],
|
|
+ "@v8//bazel/config:is_msvc_asm_x64": ["src/heap/base/asm/x64/push_registers_masm.asm"],
|
|
+ "@v8//bazel/config:is_msvc_asm_arm64": ["src/heap/base/asm/arm64/push_registers_masm.S"],
|
|
}),
|
|
)
|
|
|
|
diff --git a/BUILD.gn b/BUILD.gn
|
|
index 80a7eb6..56798db 100644
|
|
--- a/v8/BUILD.gn
|
|
+++ b/v8/BUILD.gn
|
|
@@ -5989,31 +5989,31 @@
|
|
|
|
if (is_clang || !is_win) {
|
|
if (current_cpu == "x64") {
|
|
- sources += [ "src/heap/base/asm/x64/save_registers_asm.cc" ]
|
|
+ sources += [ "src/heap/base/asm/x64/push_registers_asm.cc" ]
|
|
} else if (current_cpu == "x86") {
|
|
- sources += [ "src/heap/base/asm/ia32/save_registers_asm.cc" ]
|
|
+ sources += [ "src/heap/base/asm/ia32/push_registers_asm.cc" ]
|
|
} else if (current_cpu == "arm") {
|
|
- sources += [ "src/heap/base/asm/arm/save_registers_asm.cc" ]
|
|
+ sources += [ "src/heap/base/asm/arm/push_registers_asm.cc" ]
|
|
} else if (current_cpu == "arm64") {
|
|
- sources += [ "src/heap/base/asm/arm64/save_registers_asm.cc" ]
|
|
+ sources += [ "src/heap/base/asm/arm64/push_registers_asm.cc" ]
|
|
} else if (current_cpu == "ppc64") {
|
|
- sources += [ "src/heap/base/asm/ppc/save_registers_asm.cc" ]
|
|
+ sources += [ "src/heap/base/asm/ppc/push_registers_asm.cc" ]
|
|
} else if (current_cpu == "s390x") {
|
|
- sources += [ "src/heap/base/asm/s390/save_registers_asm.cc" ]
|
|
+ sources += [ "src/heap/base/asm/s390/push_registers_asm.cc" ]
|
|
} else if (current_cpu == "mips64el") {
|
|
- sources += [ "src/heap/base/asm/mips64/save_registers_asm.cc" ]
|
|
+ sources += [ "src/heap/base/asm/mips64/push_registers_asm.cc" ]
|
|
} else if (current_cpu == "loong64") {
|
|
- sources += [ "src/heap/base/asm/loong64/save_registers_asm.cc" ]
|
|
+ sources += [ "src/heap/base/asm/loong64/push_registers_asm.cc" ]
|
|
} else if (current_cpu == "riscv64" || current_cpu == "riscv32") {
|
|
- sources += [ "src/heap/base/asm/riscv/save_registers_asm.cc" ]
|
|
+ sources += [ "src/heap/base/asm/riscv/push_registers_asm.cc" ]
|
|
}
|
|
} else if (is_win) {
|
|
if (current_cpu == "x64") {
|
|
- sources += [ "src/heap/base/asm/x64/save_registers_masm.asm" ]
|
|
+ sources += [ "src/heap/base/asm/x64/push_registers_masm.asm" ]
|
|
} else if (current_cpu == "x86") {
|
|
- sources += [ "src/heap/base/asm/ia32/save_registers_masm.asm" ]
|
|
+ sources += [ "src/heap/base/asm/ia32/push_registers_masm.asm" ]
|
|
} else if (current_cpu == "arm64") {
|
|
- sources += [ "src/heap/base/asm/arm64/save_registers_masm.S" ]
|
|
+ sources += [ "src/heap/base/asm/arm64/push_registers_masm.S" ]
|
|
}
|
|
}
|
|
|
|
diff --git a/src/execution/isolate.cc b/src/execution/isolate.cc
|
|
index 8a2ec80..31536a1 100644
|
|
--- a/v8/src/execution/isolate.cc
|
|
+++ b/v8/src/execution/isolate.cc
|
|
@@ -3075,8 +3075,7 @@
|
|
.get()
|
|
.get();
|
|
current = WasmContinuationObject::cast(current).parent();
|
|
- thread_local_top()->stack_.SetStackStart(
|
|
- reinterpret_cast<void*>(stack->base()));
|
|
+ heap()->SetStackStart(reinterpret_cast<void*>(stack->base()));
|
|
// We don't need to add all inactive stacks. Only the ones in the active chain
|
|
// may contain cpp heap pointers.
|
|
while (!current.IsUndefined()) {
|
|
@@ -3372,9 +3371,12 @@
|
|
Isolate* saved_isolate = isolate->TryGetCurrent();
|
|
SetIsolateThreadLocals(isolate, nullptr);
|
|
isolate->set_thread_id(ThreadId::Current());
|
|
- isolate->thread_local_top()->stack_ =
|
|
- saved_isolate ? std::move(saved_isolate->thread_local_top()->stack_)
|
|
- : ::heap::base::Stack(base::Stack::GetStackStart());
|
|
+ if (saved_isolate) {
|
|
+ isolate->thread_local_top()->stack_ =
|
|
+ std::move(saved_isolate->thread_local_top()->stack_);
|
|
+ } else {
|
|
+ isolate->heap()->SetStackStart(base::Stack::GetStackStart());
|
|
+ }
|
|
|
|
bool owns_shared_isolate = isolate->owns_shared_isolate_;
|
|
Isolate* maybe_shared_isolate = isolate->shared_isolate_;
|
|
diff --git a/src/execution/thread-local-top.cc b/src/execution/thread-local-top.cc
|
|
index 0d7071d..c115ae0 100644
|
|
--- a/v8/src/execution/thread-local-top.cc
|
|
+++ b/v8/src/execution/thread-local-top.cc
|
|
@@ -44,10 +44,13 @@
|
|
Clear();
|
|
isolate_ = isolate;
|
|
thread_id_ = ThreadId::Current();
|
|
- stack_.SetStackStart(base::Stack::GetStackStart());
|
|
#if V8_ENABLE_WEBASSEMBLY
|
|
+ stack_.SetStackStart(base::Stack::GetStackStart(),
|
|
+ v8_flags.experimental_wasm_stack_switching);
|
|
thread_in_wasm_flag_address_ = reinterpret_cast<Address>(
|
|
trap_handler::GetThreadInWasmThreadLocalAddress());
|
|
+#else
|
|
+ stack_.SetStackStart(base::Stack::GetStackStart(), false);
|
|
#endif // V8_ENABLE_WEBASSEMBLY
|
|
#ifdef USE_SIMULATOR
|
|
simulator_ = Simulator::current(isolate);
|
|
diff --git a/src/heap/base/asm/arm/push_registers_asm.cc b/src/heap/base/asm/arm/push_registers_asm.cc
|
|
new file mode 100644
|
|
index 0000000..5246c3f
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/arm/push_registers_asm.cc
|
|
@@ -0,0 +1,39 @@
|
|
+// Copyright 2020 the V8 project authors. All rights reserved.
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
+// found in the LICENSE file.
|
|
+
|
|
+// Push all callee-saved registers to get them on the stack for conservative
|
|
+// stack scanning.
|
|
+//
|
|
+// See asm/x64/push_registers_clang.cc for why the function is not generated
|
|
+// using clang.
|
|
+//
|
|
+// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
+// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
+
|
|
+// We maintain 8-byte alignment at calls by pushing an additional
|
|
+// non-callee-saved register (r3).
|
|
+//
|
|
+// Calling convention source:
|
|
+// https://en.wikipedia.org/wiki/Calling_convention#ARM_(A32)
|
|
+// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html
|
|
+asm(".globl PushAllRegistersAndIterateStack \n"
|
|
+ ".type PushAllRegistersAndIterateStack, %function \n"
|
|
+ ".hidden PushAllRegistersAndIterateStack \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+ // Push all callee-saved registers and save return address.
|
|
+ // Only {r4-r11} are callee-saved registers. Push r3 in addition to align
|
|
+ // the stack back to 8 bytes.
|
|
+ " push {r3-r11, lr} \n"
|
|
+ // Pass 1st parameter (r0) unchanged (Stack*).
|
|
+ // Pass 2nd parameter (r1) unchanged (StackVisitor*).
|
|
+ // Save 3rd parameter (r2; IterateStackCallback).
|
|
+ " mov r3, r2 \n"
|
|
+ // Pass 3rd parameter as sp (stack pointer).
|
|
+ " mov r2, sp \n"
|
|
+ // Call the callback.
|
|
+ " blx r3 \n"
|
|
+ // Discard all the registers.
|
|
+ " add sp, sp, #36 \n"
|
|
+ // Pop lr into pc which returns and switches mode if needed.
|
|
+ " pop {pc} \n");
|
|
diff --git a/src/heap/base/asm/arm/save_registers_asm.cc b/src/heap/base/asm/arm/save_registers_asm.cc
|
|
deleted file mode 100644
|
|
index ace9503..0000000
|
|
--- a/v8/src/heap/base/asm/arm/save_registers_asm.cc
|
|
+++ /dev/null
|
|
@@ -1,36 +0,0 @@
|
|
-// Copyright 2020 the V8 project authors. All rights reserved.
|
|
-// Use of this source code is governed by a BSD-style license that can be
|
|
-// found in the LICENSE file.
|
|
-
|
|
-#include <src/heap/base/stack.h>
|
|
-
|
|
-// Save all callee-saved registers in the specified buffer.
|
|
-// extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-
|
|
-// See asm/x64/save_registers_asm.cc for why the function is not generated
|
|
-// using clang.
|
|
-//
|
|
-// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
-// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
-//
|
|
-// We maintain 8-byte alignment at calls by pushing an additional
|
|
-// non-callee-saved register (r3).
|
|
-//
|
|
-// Calling convention source:
|
|
-// https://en.wikipedia.org/wiki/Calling_convention#ARM_(A32)
|
|
-// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html
|
|
-
|
|
-// 8 32-bit registers = 8 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 8,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 4, "Mismatch in word size");
|
|
-
|
|
-asm(".globl SaveCalleeSavedRegisters \n"
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
- // r0: [ intptr_t* buffer ]
|
|
- // Save the callee-saved registers: {r4-r11}.
|
|
- " stm r0, {r4-r11} \n"
|
|
- // Return.
|
|
- " bx lr \n");
|
|
diff --git a/src/heap/base/asm/arm64/push_registers_asm.cc b/src/heap/base/asm/arm64/push_registers_asm.cc
|
|
new file mode 100644
|
|
index 0000000..1efcc34
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/arm64/push_registers_asm.cc
|
|
@@ -0,0 +1,62 @@
|
|
+// Copyright 2020 the V8 project authors. All rights reserved.
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
+// found in the LICENSE file.
|
|
+
|
|
+// Push all callee-saved registers to get them on the stack for conservative
|
|
+// stack scanning.
|
|
+//
|
|
+// See asm/x64/push_registers_clang.cc for why the function is not generated
|
|
+// using clang.
|
|
+//
|
|
+// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
+// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
+
|
|
+// We maintain 16-byte alignment.
|
|
+//
|
|
+// Calling convention source:
|
|
+// https://en.wikipedia.org/wiki/Calling_convention#ARM_(A64)
|
|
+
|
|
+asm(
|
|
+#if defined(__APPLE__)
|
|
+ ".globl _PushAllRegistersAndIterateStack \n"
|
|
+ ".private_extern _PushAllRegistersAndIterateStack \n"
|
|
+ ".p2align 2 \n"
|
|
+ "_PushAllRegistersAndIterateStack: \n"
|
|
+#else // !defined(__APPLE__)
|
|
+ ".globl PushAllRegistersAndIterateStack \n"
|
|
+#if !defined(_WIN64)
|
|
+ ".type PushAllRegistersAndIterateStack, %function \n"
|
|
+ ".hidden PushAllRegistersAndIterateStack \n"
|
|
+#endif // !defined(_WIN64)
|
|
+ ".p2align 2 \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+#endif // !defined(__APPLE__)
|
|
+ // x19-x29 are callee-saved.
|
|
+ " stp x19, x20, [sp, #-16]! \n"
|
|
+ " stp x21, x22, [sp, #-16]! \n"
|
|
+ " stp x23, x24, [sp, #-16]! \n"
|
|
+ " stp x25, x26, [sp, #-16]! \n"
|
|
+ " stp x27, x28, [sp, #-16]! \n"
|
|
+#ifdef V8_ENABLE_CONTROL_FLOW_INTEGRITY
|
|
+ // Sign return address.
|
|
+ " paciasp \n"
|
|
+#endif
|
|
+ " stp fp, lr, [sp, #-16]! \n"
|
|
+ // Maintain frame pointer.
|
|
+ " mov fp, sp \n"
|
|
+ // Pass 1st parameter (x0) unchanged (Stack*).
|
|
+ // Pass 2nd parameter (x1) unchanged (StackVisitor*).
|
|
+ // Save 3rd parameter (x2; IterateStackCallback)
|
|
+ " mov x7, x2 \n"
|
|
+ // Pass 3rd parameter as sp (stack pointer).
|
|
+ " mov x2, sp \n"
|
|
+ " blr x7 \n"
|
|
+ // Load return address and frame pointer.
|
|
+ " ldp fp, lr, [sp], #16 \n"
|
|
+#ifdef V8_ENABLE_CONTROL_FLOW_INTEGRITY
|
|
+ // Authenticate return address.
|
|
+ " autiasp \n"
|
|
+#endif
|
|
+ // Drop all callee-saved registers.
|
|
+ " add sp, sp, #80 \n"
|
|
+ " ret \n");
|
|
diff --git a/src/heap/base/asm/arm64/push_registers_masm.S b/src/heap/base/asm/arm64/push_registers_masm.S
|
|
new file mode 100644
|
|
index 0000000..888523a
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/arm64/push_registers_masm.S
|
|
@@ -0,0 +1,32 @@
|
|
+; Copyright 2020 the V8 project authors. All rights reserved.
|
|
+; Use of this source code is governed by a BSD-style license that can be
|
|
+; found in the LICENSE file.
|
|
+
|
|
+; This file is exactly the same as push_registers_asm.cc, just formatted for
|
|
+; the Microsoft Arm Assembler.
|
|
+
|
|
+ AREA |.text|, CODE, ALIGN=4, READONLY
|
|
+ EXPORT PushAllRegistersAndIterateStack
|
|
+PushAllRegistersAndIterateStack
|
|
+ ; x19-x29 are callee-saved
|
|
+ STP x19, x20, [sp, #-16]!
|
|
+ STP x21, x22, [sp, #-16]!
|
|
+ STP x23, x24, [sp, #-16]!
|
|
+ STP x25, x26, [sp, #-16]!
|
|
+ STP x27, x28, [sp, #-16]!
|
|
+ STP fp, lr, [sp, #-16]!
|
|
+ ; Maintain frame pointer
|
|
+ MOV fp, sp
|
|
+ ; Pass 1st parameter (x0) unchanged (Stack*).
|
|
+ ; Pass 2nd parameter (x1) unchanged (StackVisitor*).
|
|
+ ; Save 3rd parameter (x2; IterateStackCallback)
|
|
+ MOV x7, x2
|
|
+ ; Pass 3rd parameter as sp (stack pointer)
|
|
+ MOV x2, sp
|
|
+ BLR x7
|
|
+ ; Load return address
|
|
+ LDR lr, [sp, #8]
|
|
+ ; Restore frame pointer and pop all callee-saved registers.
|
|
+ LDR fp, [sp], #96
|
|
+ RET
|
|
+ END
|
|
diff --git a/src/heap/base/asm/arm64/save_registers_asm.cc b/src/heap/base/asm/arm64/save_registers_asm.cc
|
|
deleted file mode 100644
|
|
index 5fe81d8..0000000
|
|
--- a/v8/src/heap/base/asm/arm64/save_registers_asm.cc
|
|
+++ /dev/null
|
|
@@ -1,50 +0,0 @@
|
|
-// Copyright 2020 the V8 project authors. All rights reserved.
|
|
-// Use of this source code is governed by a BSD-style license that can be
|
|
-// found in the LICENSE file.
|
|
-
|
|
-#include <src/heap/base/stack.h>
|
|
-
|
|
-// Save all callee-saved registers in the specified buffer.
|
|
-// extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-
|
|
-// See asm/x64/save_registers_asm.cc for why the function is not generated
|
|
-// using clang.
|
|
-//
|
|
-// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
-// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
-//
|
|
-// We maintain 16-byte alignment.
|
|
-//
|
|
-// Calling convention source:
|
|
-// https://en.wikipedia.org/wiki/Calling_convention#ARM_(A64)
|
|
-
|
|
-// 11 64-bit registers = 11 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 11,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 8, "Mismatch in word size");
|
|
-
|
|
-asm(
|
|
-#if defined(__APPLE__)
|
|
- ".globl _SaveCalleeSavedRegisters \n"
|
|
- ".private_extern _SaveCalleeSavedRegisters \n"
|
|
- ".p2align 2 \n"
|
|
- "_SaveCalleeSavedRegisters: \n"
|
|
-#else // !defined(__APPLE__)
|
|
- ".globl SaveCalleeSavedRegisters \n"
|
|
-#if !defined(_WIN64)
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
-#endif // !defined(_WIN64)
|
|
- ".p2align 2 \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
-#endif // !defined(__APPLE__)
|
|
- // $x0: [ intptr_t* buffer ]
|
|
- // Save the callee-saved registers: x19-x29.
|
|
- " stp x19, x20, [x0], #16 \n"
|
|
- " stp x21, x22, [x0], #16 \n"
|
|
- " stp x23, x24, [x0], #16 \n"
|
|
- " stp x25, x26, [x0], #16 \n"
|
|
- " stp x27, x28, [x0], #16 \n"
|
|
- " str x29, [x0] \n"
|
|
- // Return.
|
|
- " ret \n");
|
|
diff --git a/src/heap/base/asm/arm64/save_registers_masm.S b/src/heap/base/asm/arm64/save_registers_masm.S
|
|
deleted file mode 100644
|
|
index ab79055..0000000
|
|
--- a/v8/src/heap/base/asm/arm64/save_registers_masm.S
|
|
+++ /dev/null
|
|
@@ -1,24 +0,0 @@
|
|
-; Copyright 2020 the V8 project authors. All rights reserved.
|
|
-; Use of this source code is governed by a BSD-style license that can be
|
|
-; found in the LICENSE file.
|
|
-
|
|
-; This file is exactly the same as save_registers_asm.cc, just formatted for
|
|
-; the Microsoft Arm Assembler.
|
|
-
|
|
-; Save all callee-saved registers in the specified buffer.
|
|
-; extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-
|
|
- AREA |.text|, CODE, ALIGN=4, READONLY
|
|
- EXPORT SaveCalleeSavedRegisters
|
|
-SaveCalleeSavedRegisters
|
|
- ; x0: [ intptr_t* buffer ]
|
|
- ; x19-x29 are callee-saved
|
|
- STP x19, x20, [x0], #16
|
|
- STP x21, x22, [x0], #16
|
|
- STP x23, x24, [x0], #16
|
|
- STP x25, x26, [x0], #16
|
|
- STP x27, x28, [x0], #16
|
|
- STR x29, [x0]
|
|
- ; Return.
|
|
- RET
|
|
- END
|
|
diff --git a/src/heap/base/asm/ia32/push_registers_asm.cc b/src/heap/base/asm/ia32/push_registers_asm.cc
|
|
new file mode 100644
|
|
index 0000000..ed9c14a
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/ia32/push_registers_asm.cc
|
|
@@ -0,0 +1,53 @@
|
|
+// Copyright 2020 the V8 project authors. All rights reserved.
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
+// found in the LICENSE file.
|
|
+
|
|
+// Push all callee-saved registers to get them on the stack for conservative
|
|
+// stack scanning.
|
|
+//
|
|
+// See asm/x64/push_registers_clang.cc for why the function is not generated
|
|
+// using clang.
|
|
+//
|
|
+// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
+// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
+
|
|
+// We maintain 16-byte alignment at calls. There is an 4-byte return address
|
|
+// on the stack and we push 28 bytes which maintains 16-byte stack alignment
|
|
+// at the call.
|
|
+//
|
|
+// The following assumes cdecl calling convention.
|
|
+// Source: https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl
|
|
+asm(
|
|
+#ifdef _WIN32
|
|
+ ".globl _PushAllRegistersAndIterateStack \n"
|
|
+ "_PushAllRegistersAndIterateStack: \n"
|
|
+#else // !_WIN32
|
|
+ ".globl PushAllRegistersAndIterateStack \n"
|
|
+ ".type PushAllRegistersAndIterateStack, %function \n"
|
|
+ ".hidden PushAllRegistersAndIterateStack \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+#endif // !_WIN32
|
|
+ // [ IterateStackCallback ]
|
|
+ // [ StackVisitor* ]
|
|
+ // [ Stack* ]
|
|
+ // [ ret ]
|
|
+ // ebp is callee-saved. Maintain proper frame pointer for debugging.
|
|
+ " push %ebp \n"
|
|
+ " movl %esp, %ebp \n"
|
|
+ " push %ebx \n"
|
|
+ " push %esi \n"
|
|
+ " push %edi \n"
|
|
+ // Save 3rd parameter (IterateStackCallback).
|
|
+ " movl 28(%esp), %ecx \n"
|
|
+ // Pass 3rd parameter as esp (stack pointer).
|
|
+ " push %esp \n"
|
|
+ // Pass 2nd parameter (StackVisitor*).
|
|
+ " push 28(%esp) \n"
|
|
+ // Pass 1st parameter (Stack*).
|
|
+ " push 28(%esp) \n"
|
|
+ " call *%ecx \n"
|
|
+ // Pop the callee-saved registers.
|
|
+ " addl $24, %esp \n"
|
|
+ // Restore rbp as it was used as frame pointer.
|
|
+ " pop %ebp \n"
|
|
+ " ret \n");
|
|
diff --git a/src/heap/base/asm/ia32/push_registers_masm.asm b/src/heap/base/asm/ia32/push_registers_masm.asm
|
|
new file mode 100644
|
|
index 0000000..a35fd6e
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/ia32/push_registers_masm.asm
|
|
@@ -0,0 +1,48 @@
|
|
+;; Copyright 2020 the V8 project authors. All rights reserved.
|
|
+;; Use of this source code is governed by a BSD-style license that can be
|
|
+;; found in the LICENSE file.
|
|
+
|
|
+;; MASM syntax
|
|
+;; https://docs.microsoft.com/en-us/cpp/assembler/masm/microsoft-macro-assembler-reference?view=vs-2019
|
|
+
|
|
+.model flat, C
|
|
+
|
|
+public PushAllRegistersAndIterateStack
|
|
+
|
|
+.code
|
|
+PushAllRegistersAndIterateStack:
|
|
+ ;; Push all callee-saved registers to get them on the stack for conservative
|
|
+ ;; stack scanning.
|
|
+ ;;
|
|
+ ;; We maintain 16-byte alignment at calls. There is an 8-byte return address
|
|
+ ;; on the stack and we push 72 bytes which maintains 16-byte stack alignment
|
|
+ ;; at the call.
|
|
+ ;;
|
|
+ ;; The following assumes cdecl calling convention.
|
|
+ ;; Source: https://docs.microsoft.com/en-us/cpp/cpp/cdecl?view=vs-2019
|
|
+ ;;
|
|
+ ;; [ IterateStackCallback ]
|
|
+ ;; [ StackVisitor* ]
|
|
+ ;; [ Stack* ]
|
|
+ ;; [ ret ]
|
|
+ push ebp
|
|
+ mov ebp, esp
|
|
+ push ebx
|
|
+ push esi
|
|
+ push edi
|
|
+ ;; Save 3rd parameter (IterateStackCallback).
|
|
+ mov ecx, [ esp + 28 ]
|
|
+ ;; Pass 3rd parameter as esp (stack pointer).
|
|
+ push esp
|
|
+ ;; Pass 2nd parameter (StackVisitor*).
|
|
+ push [ esp + 28 ]
|
|
+ ;; Pass 1st parameter (Stack*).
|
|
+ push [ esp + 28 ]
|
|
+ call ecx
|
|
+ ;; Pop the callee-saved registers.
|
|
+ add esp, 24
|
|
+ ;; Restore rbp as it was used as frame pointer.
|
|
+ pop ebp
|
|
+ ret
|
|
+
|
|
+end
|
|
diff --git a/src/heap/base/asm/ia32/save_registers_asm.cc b/src/heap/base/asm/ia32/save_registers_asm.cc
|
|
deleted file mode 100644
|
|
index 7c05247..0000000
|
|
--- a/v8/src/heap/base/asm/ia32/save_registers_asm.cc
|
|
+++ /dev/null
|
|
@@ -1,48 +0,0 @@
|
|
-// Copyright 2020 the V8 project authors. All rights reserved.
|
|
-// Use of this source code is governed by a BSD-style license that can be
|
|
-// found in the LICENSE file.
|
|
-
|
|
-#include <src/heap/base/stack.h>
|
|
-
|
|
-// Save all callee-saved registers in the specified buffer.
|
|
-// extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-
|
|
-// See asm/x64/save_registers_asm.cc for why the function is not generated
|
|
-// using clang.
|
|
-//
|
|
-// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
-// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
-//
|
|
-// The following assumes cdecl calling convention.
|
|
-// Source: https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl
|
|
-
|
|
-// 3 32-bit registers = 3 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 3,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 4, "Mismatch in word size");
|
|
-
|
|
-asm(
|
|
-#ifdef _WIN32
|
|
- ".globl _SaveCalleeSavedRegisters \n"
|
|
- "_SaveCalleeSavedRegisters: \n"
|
|
-#else // !_WIN32
|
|
- ".globl SaveCalleeSavedRegisters \n"
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
-#endif // !_WIN32
|
|
- // 8: [ intptr_t* buffer ]
|
|
- // 4: [ ret ]
|
|
- // 0: [ saved %ebp ]
|
|
- // %ebp is callee-saved. Maintain proper frame pointer for debugging.
|
|
- " push %ebp \n"
|
|
- " movl %esp, %ebp \n"
|
|
- // Load the buffer's address in %ecx.
|
|
- " movl 8(%ebp), %ecx \n"
|
|
- // Save the callee-saved registers.
|
|
- " movl %ebx, 0(%ecx) \n"
|
|
- " movl %esi, 4(%ecx) \n"
|
|
- " movl %edi, 8(%ecx) \n"
|
|
- // Restore %ebp as it was used as frame pointer and return.
|
|
- " pop %ebp \n"
|
|
- " ret \n");
|
|
diff --git a/src/heap/base/asm/ia32/save_registers_masm.asm b/src/heap/base/asm/ia32/save_registers_masm.asm
|
|
deleted file mode 100644
|
|
index 0892b02..0000000
|
|
--- a/v8/src/heap/base/asm/ia32/save_registers_masm.asm
|
|
+++ /dev/null
|
|
@@ -1,36 +0,0 @@
|
|
-;; Copyright 2020 the V8 project authors. All rights reserved.
|
|
-;; Use of this source code is governed by a BSD-style license that can be
|
|
-;; found in the LICENSE file.
|
|
-
|
|
-;; MASM syntax
|
|
-;; https://docs.microsoft.com/en-us/cpp/assembler/masm/microsoft-macro-assembler-reference?view=vs-2019
|
|
-
|
|
-.model flat, C
|
|
-
|
|
-public SaveCalleeSavedRegisters
|
|
-
|
|
-.code
|
|
- ;; Save all callee-saved registers in the specified buffer.
|
|
- ;; extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
- ;;
|
|
- ;; The following assumes cdecl calling convention.
|
|
- ;; Source: https://docs.microsoft.com/en-us/cpp/cpp/cdecl?view=vs-2019
|
|
-
|
|
-SaveCalleeSavedRegisters:
|
|
- ;; 8: [ intptr_t* buffer ]
|
|
- ;; 4: [ ret ]
|
|
- ;; 0: [ saved %ebp ]
|
|
- ;; %ebp is callee-saved. Maintain proper frame pointer for debugging.
|
|
- push ebp
|
|
- mov ebp, esp
|
|
- ;; Load the buffer's address in %ecx.
|
|
- mov ecx, [ebp + 8]
|
|
- ;; Save the callee-saved registers.
|
|
- mov [ecx], ebx
|
|
- mov [ecx + 4], esi
|
|
- mov [ecx + 8], edi
|
|
- ;; Restore %ebp as it was used as frame pointer and return.
|
|
- pop ebp
|
|
- ret
|
|
-
|
|
-end
|
|
diff --git a/src/heap/base/asm/loong64/push_registers_asm.cc b/src/heap/base/asm/loong64/push_registers_asm.cc
|
|
new file mode 100644
|
|
index 0000000..aa8dcd3
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/loong64/push_registers_asm.cc
|
|
@@ -0,0 +1,48 @@
|
|
+// Copyright 2021 the V8 project authors. All rights reserved.
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
+// found in the LICENSE file.
|
|
+
|
|
+// Push all callee-saved registers to get them on the stack for conservative
|
|
+// stack scanning.
|
|
+//
|
|
+// See asm/x64/push_registers_clang.cc for why the function is not generated
|
|
+// using clang.
|
|
+//
|
|
+// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
+// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
+asm(".text \n"
|
|
+ ".global PushAllRegistersAndIterateStack \n"
|
|
+ ".type PushAllRegistersAndIterateStack, %function \n"
|
|
+ ".hidden PushAllRegistersAndIterateStack \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+ // Push all callee-saved registers and save return address.
|
|
+ " addi.d $sp, $sp, -96 \n"
|
|
+ " st.d $ra, $sp, 88 \n"
|
|
+ " st.d $s8, $sp, 80 \n"
|
|
+ " st.d $sp, $sp, 72 \n"
|
|
+ " st.d $fp, $sp, 64 \n"
|
|
+ " st.d $s7, $sp, 56 \n"
|
|
+ " st.d $s6, $sp, 48 \n"
|
|
+ " st.d $s5, $sp, 40 \n"
|
|
+ " st.d $s4, $sp, 32 \n"
|
|
+ " st.d $s3, $sp, 24 \n"
|
|
+ " st.d $s2, $sp, 16 \n"
|
|
+ " st.d $s1, $sp, 8 \n"
|
|
+ " st.d $s0, $sp, 0 \n"
|
|
+ // Maintain frame pointer.
|
|
+ " addi.d $s8, $sp, 0 \n"
|
|
+ // Pass 1st parameter (a0) unchanged (Stack*).
|
|
+ // Pass 2nd parameter (a1) unchanged (StackVisitor*).
|
|
+ // Save 3rd parameter (a2; IterateStackCallback).
|
|
+ " addi.d $a3, $a2, 0 \n"
|
|
+ // Call the callback.
|
|
+ // Pass 3rd parameter as sp (stack pointer).
|
|
+ " addi.d $a2, $sp, 0 \n"
|
|
+ " jirl $ra, $a3, 0 \n"
|
|
+ // Load return address.
|
|
+ " ld.d $ra, $sp, 88 \n"
|
|
+ // Restore frame pointer.
|
|
+ " ld.d $s8, $sp, 80 \n"
|
|
+ // Discard all callee-saved registers.
|
|
+ " addi.d $sp, $sp, 96 \n"
|
|
+ " jirl $zero, $ra, 0 \n");
|
|
diff --git a/src/heap/base/asm/loong64/save_registers_asm.cc b/src/heap/base/asm/loong64/save_registers_asm.cc
|
|
deleted file mode 100644
|
|
index d5b110d..0000000
|
|
--- a/v8/src/heap/base/asm/loong64/save_registers_asm.cc
|
|
+++ /dev/null
|
|
@@ -1,40 +0,0 @@
|
|
-// Copyright 2021 the V8 project authors. All rights reserved.
|
|
-// Use of this source code is governed by a BSD-style license that can be
|
|
-// found in the LICENSE file.
|
|
-
|
|
-#include <src/heap/base/stack.h>
|
|
-
|
|
-// Save all callee-saved registers in the specified buffer.
|
|
-// extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-
|
|
-// See asm/x64/save_registers_asm.cc for why the function is not generated
|
|
-// using clang.
|
|
-//
|
|
-// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
-// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
-
|
|
-// 11 64-bit registers = 11 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 11,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 8, "Mismatch in word size");
|
|
-
|
|
-asm(".text \n"
|
|
- ".global SaveCalleeSavedRegisters \n"
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
- // $a0: [ intptr_t* buffer ]
|
|
- // Save the callee-saved registers.
|
|
- " st.d $s8, $a0, 0 \n"
|
|
- " st.d $sp, $a0, 8 \n"
|
|
- " st.d $fp, $a0, 16 \n"
|
|
- " st.d $s7, $a0, 24 \n"
|
|
- " st.d $s6, $a0, 32 \n"
|
|
- " st.d $s5, $a0, 40 \n"
|
|
- " st.d $s4, $a0, 48 \n"
|
|
- " st.d $s3, $a0, 56 \n"
|
|
- " st.d $s2, $a0, 64 \n"
|
|
- " st.d $s1, $a0, 72 \n"
|
|
- " st.d $s0, $a0, 80 \n"
|
|
- // Return.
|
|
- " jirl $zero, $ra, 0 \n");
|
|
diff --git a/src/heap/base/asm/mips64/push_registers_asm.cc b/src/heap/base/asm/mips64/push_registers_asm.cc
|
|
new file mode 100644
|
|
index 0000000..47779e0
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/mips64/push_registers_asm.cc
|
|
@@ -0,0 +1,49 @@
|
|
+// Copyright 2020 the V8 project authors. All rights reserved.
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
+// found in the LICENSE file.
|
|
+
|
|
+// Push all callee-saved registers to get them on the stack for conservative
|
|
+// stack scanning.
|
|
+//
|
|
+// See asm/x64/push_registers_clang.cc for why the function is not generated
|
|
+// using clang.
|
|
+//
|
|
+// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
+// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
+asm(".text \n"
|
|
+ ".set noreorder \n"
|
|
+ ".global PushAllRegistersAndIterateStack \n"
|
|
+ ".type PushAllRegistersAndIterateStack, %function \n"
|
|
+ ".hidden PushAllRegistersAndIterateStack \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+ // Push all callee-saved registers and save return address.
|
|
+ " daddiu $sp, $sp, -96 \n"
|
|
+ " sd $ra, 88($sp) \n"
|
|
+ " sd $s8, 80($sp) \n"
|
|
+ " sd $sp, 72($sp) \n"
|
|
+ " sd $gp, 64($sp) \n"
|
|
+ " sd $s7, 56($sp) \n"
|
|
+ " sd $s6, 48($sp) \n"
|
|
+ " sd $s5, 40($sp) \n"
|
|
+ " sd $s4, 32($sp) \n"
|
|
+ " sd $s3, 24($sp) \n"
|
|
+ " sd $s2, 16($sp) \n"
|
|
+ " sd $s1, 8($sp) \n"
|
|
+ " sd $s0, 0($sp) \n"
|
|
+ // Maintain frame pointer.
|
|
+ " move $s8, $sp \n"
|
|
+ // Pass 1st parameter (a0) unchanged (Stack*).
|
|
+ // Pass 2nd parameter (a1) unchanged (StackVisitor*).
|
|
+ // Save 3rd parameter (a2; IterateStackCallback).
|
|
+ " move $a3, $a2 \n"
|
|
+ // Call the callback.
|
|
+ " jalr $a3 \n"
|
|
+ // Delay slot: Pass 3rd parameter as sp (stack pointer).
|
|
+ " move $a2, $sp \n"
|
|
+ // Load return address.
|
|
+ " ld $ra, 88($sp) \n"
|
|
+ // Restore frame pointer.
|
|
+ " ld $s8, 80($sp) \n"
|
|
+ " jr $ra \n"
|
|
+ // Delay slot: Discard all callee-saved registers.
|
|
+ " daddiu $sp, $sp, 96 \n");
|
|
diff --git a/src/heap/base/asm/mips64/save_registers_asm.cc b/src/heap/base/asm/mips64/save_registers_asm.cc
|
|
deleted file mode 100644
|
|
index 95bcc31..0000000
|
|
--- a/v8/src/heap/base/asm/mips64/save_registers_asm.cc
|
|
+++ /dev/null
|
|
@@ -1,41 +0,0 @@
|
|
-// Copyright 2020 the V8 project authors. All rights reserved.
|
|
-// Use of this source code is governed by a BSD-style license that can be
|
|
-// found in the LICENSE file.
|
|
-
|
|
-#include <src/heap/base/stack.h>
|
|
-
|
|
-// Save all callee-saved registers in the specified buffer.
|
|
-// extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-
|
|
-// See asm/x64/save_registers_asm.cc for why the function is not generated
|
|
-// using clang.
|
|
-//
|
|
-// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
-// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
-
|
|
-// 9 64-bit registers = 9 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 9,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 8, "Mismatch in word size");
|
|
-
|
|
-asm(".text \n"
|
|
- ".set noreorder \n"
|
|
- ".global SaveCalleeSavedRegisters \n"
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
- // $a0: [ intptr_t* buffer ]
|
|
- // Save the callee-saved registers.
|
|
- " sd $gp, 64($a0) \n"
|
|
- " sd $s7, 56($a0) \n"
|
|
- " sd $s6, 48($a0) \n"
|
|
- " sd $s5, 40($a0) \n"
|
|
- " sd $s4, 32($a0) \n"
|
|
- " sd $s3, 24($a0) \n"
|
|
- " sd $s2, 16($a0) \n"
|
|
- " sd $s1, 8($a0) \n"
|
|
- // ... one more in the delay slot!
|
|
- // Return.
|
|
- " jr $ra \n"
|
|
- // Delay slot:
|
|
- " sd $s0, 0($a0) \n");
|
|
diff --git a/src/heap/base/asm/ppc/push_registers_asm.cc b/src/heap/base/asm/ppc/push_registers_asm.cc
|
|
new file mode 100644
|
|
index 0000000..f879980
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/ppc/push_registers_asm.cc
|
|
@@ -0,0 +1,97 @@
|
|
+// Copyright 2020 the V8 project authors. All rights reserved.
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
+// found in the LICENSE file.
|
|
+
|
|
+// Push all callee-saved registers to get them on the stack for conservative
|
|
+// stack scanning.
|
|
+//
|
|
+// See asm/x64/push_registers_clang.cc for why the function is not generated
|
|
+// using clang.
|
|
+
|
|
+// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
+// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
+
|
|
+// PPC ABI source:
|
|
+// http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html
|
|
+
|
|
+// AIX Runtime process stack:
|
|
+// https://www.ibm.com/support/knowledgecenter/ssw_aix_71/assembler/idalangref_runtime_process.html
|
|
+asm(
|
|
+#if defined(_AIX)
|
|
+ ".csect .text[PR] \n"
|
|
+ ".align 2 \n"
|
|
+ ".globl .PushAllRegistersAndIterateStack, hidden \n"
|
|
+ ".PushAllRegistersAndIterateStack: \n"
|
|
+#else
|
|
+ ".text \n"
|
|
+ ".align 2 \n"
|
|
+ ".globl PushAllRegistersAndIterateStack \n"
|
|
+ ".type PushAllRegistersAndIterateStack, %function \n"
|
|
+ ".hidden PushAllRegistersAndIterateStack \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+#endif
|
|
+ // Push all callee-saved registers.
|
|
+ // lr, TOC pointer, r16 to r31. 160 bytes.
|
|
+ // The parameter save area shall be allocated by the caller. 112 bytes.
|
|
+ // At anytime, SP (r1) needs to be multiple of 16 (i.e. 16-aligned).
|
|
+ " mflr 0 \n"
|
|
+ " std 0, 16(1) \n"
|
|
+#if defined(_AIX)
|
|
+ " std 2, 40(1) \n"
|
|
+#else
|
|
+ " std 2, 24(1) \n"
|
|
+#endif
|
|
+ " stdu 1, -256(1) \n"
|
|
+ " std 14, 112(1) \n"
|
|
+ " std 15, 120(1) \n"
|
|
+ " std 16, 128(1) \n"
|
|
+ " std 17, 136(1) \n"
|
|
+ " std 18, 144(1) \n"
|
|
+ " std 19, 152(1) \n"
|
|
+ " std 20, 160(1) \n"
|
|
+ " std 21, 168(1) \n"
|
|
+ " std 22, 176(1) \n"
|
|
+ " std 23, 184(1) \n"
|
|
+ " std 24, 192(1) \n"
|
|
+ " std 25, 200(1) \n"
|
|
+ " std 26, 208(1) \n"
|
|
+ " std 27, 216(1) \n"
|
|
+ " std 28, 224(1) \n"
|
|
+ " std 29, 232(1) \n"
|
|
+ " std 30, 240(1) \n"
|
|
+ " std 31, 248(1) \n"
|
|
+ // Pass 1st parameter (r3) unchanged (Stack*).
|
|
+ // Pass 2nd parameter (r4) unchanged (StackVisitor*).
|
|
+ // Save 3rd parameter (r5; IterateStackCallback).
|
|
+ " mr 6, 5 \n"
|
|
+#if defined(_AIX)
|
|
+ // Set up TOC for callee.
|
|
+ " ld 2,8(5) \n"
|
|
+ // AIX uses function descriptors, which means that
|
|
+ // pointers to functions do not point to code, but
|
|
+ // instead point to metadata about them, hence
|
|
+ // need to deterrence.
|
|
+ " ld 6,0(6) \n"
|
|
+#endif
|
|
+ // Pass 3rd parameter as sp (stack pointer).
|
|
+ " mr 5, 1 \n"
|
|
+#if !defined(_AIX)
|
|
+ // Set up r12 to be equal to the callee address (in order for TOC
|
|
+ // relocation). Only needed on LE Linux.
|
|
+ " mr 12, 6 \n"
|
|
+#endif
|
|
+ // Call the callback.
|
|
+ " mtctr 6 \n"
|
|
+ " bctrl \n"
|
|
+ // Discard all the registers.
|
|
+ " addi 1, 1, 256 \n"
|
|
+ // Restore lr.
|
|
+ " ld 0, 16(1) \n"
|
|
+ " mtlr 0 \n"
|
|
+#if defined(_AIX)
|
|
+ // Restore TOC pointer.
|
|
+ " ld 2, 40(1) \n"
|
|
+#else
|
|
+ " ld 2, 24(1) \n"
|
|
+#endif
|
|
+ " blr \n");
|
|
diff --git a/src/heap/base/asm/ppc/save_registers_asm.cc b/src/heap/base/asm/ppc/save_registers_asm.cc
|
|
deleted file mode 100644
|
|
index 9e8102a..0000000
|
|
--- a/v8/src/heap/base/asm/ppc/save_registers_asm.cc
|
|
+++ /dev/null
|
|
@@ -1,113 +0,0 @@
|
|
-// Copyright 2020 the V8 project authors. All rights reserved.
|
|
-// Use of this source code is governed by a BSD-style license that can be
|
|
-// found in the LICENSE file.
|
|
-
|
|
-#include <src/heap/base/stack.h>
|
|
-
|
|
-// Save all callee-saved registers in the specified buffer.
|
|
-// extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-
|
|
-// See asm/x64/save_registers_asm.cc for why the function is not generated
|
|
-// using clang.
|
|
-//
|
|
-// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
-// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
-//
|
|
-// PPC ABI source:
|
|
-// http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html
|
|
-
|
|
-// AIX Runtime process stack:
|
|
-// https://www.ibm.com/support/knowledgecenter/ssw_aix_71/assembler/idalangref_runtime_process.html
|
|
-
|
|
-#ifdef __PPC64__
|
|
-
|
|
-// 20 64-bit registers = 20 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 20,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 8, "Mismatch in word size");
|
|
-
|
|
-asm(
|
|
-#if defined(_AIX)
|
|
- ".csect .text[PR] \n"
|
|
- ".align 2 \n"
|
|
- ".globl .SaveCalleeSavedRegisters, hidden \n"
|
|
- ".SaveCalleeSavedRegisters: \n"
|
|
-#else
|
|
- ".text \n"
|
|
- ".align 2 \n"
|
|
- ".globl SaveCalleeSavedRegisters \n"
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
-#endif
|
|
- // r3: [ intptr_t* buffer ]
|
|
- // Save the callee-saved registers: lr, TOC pointer (r2), r14-r31.
|
|
- " mflr 0 \n"
|
|
- " std 0, 8(3) \n"
|
|
- " std 2, 16(3) \n"
|
|
- " std 14, 24(3) \n"
|
|
- " std 15, 32(3) \n"
|
|
- " std 16, 40(3) \n"
|
|
- " std 17, 48(3) \n"
|
|
- " std 18, 56(3) \n"
|
|
- " std 19, 64(3) \n"
|
|
- " std 20, 72(3) \n"
|
|
- " std 21, 80(3) \n"
|
|
- " std 22, 88(3) \n"
|
|
- " std 23, 96(3) \n"
|
|
- " std 24, 104(3) \n"
|
|
- " std 25, 112(3) \n"
|
|
- " std 26, 120(3) \n"
|
|
- " std 27, 128(3) \n"
|
|
- " std 28, 136(3) \n"
|
|
- " std 29, 144(3) \n"
|
|
- " std 30, 152(3) \n"
|
|
- " std 31, 160(3) \n"
|
|
- // Return.
|
|
- " blr \n");
|
|
-
|
|
-#else // !__PPC64__
|
|
-
|
|
-// 20 32-bit registers = 20 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 20,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 4, "Mismatch in word size");
|
|
-
|
|
-asm(
|
|
-#if defined(_AIX)
|
|
- ".globl .SaveCalleeSavedRegisters, hidden \n"
|
|
- ".csect .text[PR] \n"
|
|
- ".SaveCalleeSavedRegisters: \n"
|
|
-#else
|
|
- ".globl SaveCalleeSavedRegisters \n"
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
-#endif
|
|
- // r3: [ intptr_t* buffer ]
|
|
- // Save the callee-saved registers: lr, TOC pointer (r2), r14-r31.
|
|
- " mflr 0 \n"
|
|
- " st 0, 4(3) \n"
|
|
- " st 2, 8(3) \n"
|
|
- " st 14, 12(3) \n"
|
|
- " st 15, 16(3) \n"
|
|
- " st 16, 20(3) \n"
|
|
- " st 17, 24(3) \n"
|
|
- " st 18, 28(3) \n"
|
|
- " st 19, 32(3) \n"
|
|
- " st 20, 36(3) \n"
|
|
- " st 21, 40(3) \n"
|
|
- " st 22, 44(3) \n"
|
|
- " st 23, 48(3) \n"
|
|
- " st 24, 52(3) \n"
|
|
- " st 25, 56(3) \n"
|
|
- " st 26, 60(3) \n"
|
|
- " st 27, 64(3) \n"
|
|
- " st 28, 68(3) \n"
|
|
- " st 29, 72(3) \n"
|
|
- " st 30, 76(3) \n"
|
|
- " st 31, 80(3) \n"
|
|
- // Return.
|
|
- " blr \n");
|
|
-
|
|
-#endif // __PPC64__
|
|
diff --git a/src/heap/base/asm/riscv/push_registers_asm.cc b/src/heap/base/asm/riscv/push_registers_asm.cc
|
|
new file mode 100644
|
|
index 0000000..7cc13ea
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/riscv/push_registers_asm.cc
|
|
@@ -0,0 +1,93 @@
|
|
+// Copyright 2020 the V8 project authors. All rights reserved.
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
+// found in the LICENSE file.
|
|
+
|
|
+// Push all callee-saved registers to get them on the stack for conservative
|
|
+// stack scanning.
|
|
+//
|
|
+// See asm/x64/push_registers_asm.cc for why the function is not generated
|
|
+// using clang.
|
|
+//
|
|
+// Calling convention source:
|
|
+// https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf Table 18.2
|
|
+#ifdef V8_TARGET_ARCH_RISCV64
|
|
+asm(".global PushAllRegistersAndIterateStack \n"
|
|
+ ".type PushAllRegistersAndIterateStack, %function \n"
|
|
+ ".hidden PushAllRegistersAndIterateStack \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+ // Push all callee-saved registers and save return address.
|
|
+ " addi sp, sp, -112 \n"
|
|
+ // Save return address.
|
|
+ " sd ra, 104(sp) \n"
|
|
+ // sp is callee-saved.
|
|
+ " sd sp, 96(sp) \n"
|
|
+ // s0-s11 are callee-saved.
|
|
+ " sd s11, 88(sp) \n"
|
|
+ " sd s10, 80(sp) \n"
|
|
+ " sd s9, 72(sp) \n"
|
|
+ " sd s8, 64(sp) \n"
|
|
+ " sd s7, 56(sp) \n"
|
|
+ " sd s6, 48(sp) \n"
|
|
+ " sd s5, 40(sp) \n"
|
|
+ " sd s4, 32(sp) \n"
|
|
+ " sd s3, 24(sp) \n"
|
|
+ " sd s2, 16(sp) \n"
|
|
+ " sd s1, 8(sp) \n"
|
|
+ " sd s0, 0(sp) \n"
|
|
+ // Maintain frame pointer(fp is s0).
|
|
+ " mv s0, sp \n"
|
|
+ // Pass 1st parameter (a0) unchanged (Stack*).
|
|
+ // Pass 2nd parameter (a1) unchanged (StackVisitor*).
|
|
+ // Save 3rd parameter (a2; IterateStackCallback) to a3.
|
|
+ " mv a3, a2 \n"
|
|
+ // Pass 3rd parameter as sp (stack pointer).
|
|
+ " mv a2, sp \n"
|
|
+ // Call the callback.
|
|
+ " jalr a3 \n"
|
|
+ // Load return address.
|
|
+ " ld ra, 104(sp) \n"
|
|
+ // Restore frame pointer.
|
|
+ " ld s0, 0(sp) \n"
|
|
+ " addi sp, sp, 112 \n"
|
|
+ " jr ra \n");
|
|
+#elif V8_TARGET_ARCH_RISCV32
|
|
+asm(".global PushAllRegistersAndIterateStack \n"
|
|
+ ".type PushAllRegistersAndIterateStack, %function \n"
|
|
+ ".hidden PushAllRegistersAndIterateStack \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+ // Push all callee-saved registers and save return address.
|
|
+ " addi sp, sp, -56 \n"
|
|
+ // Save return address.
|
|
+ " sw ra, 52(sp) \n"
|
|
+ // sp is callee-saved.
|
|
+ " sw sp, 48(sp) \n"
|
|
+ // s0-s11 are callee-saved.
|
|
+ " sw s11, 44(sp) \n"
|
|
+ " sw s10, 40(sp) \n"
|
|
+ " sw s9, 36(sp) \n"
|
|
+ " sw s8, 32(sp) \n"
|
|
+ " sw s7, 28(sp) \n"
|
|
+ " sw s6, 24(sp) \n"
|
|
+ " sw s5, 20(sp) \n"
|
|
+ " sw s4, 16(sp) \n"
|
|
+ " sw s3, 12(sp) \n"
|
|
+ " sw s2, 8(sp) \n"
|
|
+ " sw s1, 4(sp) \n"
|
|
+ " sw s0, 0(sp) \n"
|
|
+ // Maintain frame pointer(fp is s0).
|
|
+ " mv s0, sp \n"
|
|
+ // Pass 1st parameter (a0) unchanged (Stack*).
|
|
+ // Pass 2nd parameter (a1) unchanged (StackVisitor*).
|
|
+ // Save 3rd parameter (a2; IterateStackCallback) to a3.
|
|
+ " mv a3, a2 \n"
|
|
+ // Pass 3rd parameter as sp (stack pointer).
|
|
+ " mv a2, sp \n"
|
|
+ // Call the callback.
|
|
+ " jalr a3 \n"
|
|
+ // Load return address.
|
|
+ " lw ra, 52(sp) \n"
|
|
+ // Restore frame pointer.
|
|
+ " lw s0, 0(sp) \n"
|
|
+ " addi sp, sp, 56 \n"
|
|
+ " jr ra \n");
|
|
+#endif
|
|
diff --git a/src/heap/base/asm/riscv/save_registers_asm.cc b/src/heap/base/asm/riscv/save_registers_asm.cc
|
|
deleted file mode 100644
|
|
index ad0bf98..0000000
|
|
--- a/v8/src/heap/base/asm/riscv/save_registers_asm.cc
|
|
+++ /dev/null
|
|
@@ -1,68 +0,0 @@
|
|
-// Copyright 2020 the V8 project authors. All rights reserved.
|
|
-// Use of this source code is governed by a BSD-style license that can be
|
|
-// found in the LICENSE file.
|
|
-
|
|
-#include <src/heap/base/stack.h>
|
|
-
|
|
-// Save all callee-saved registers in the specified buffer.
|
|
-// extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-
|
|
-// See asm/x64/save_registers_asm.cc for why the function is not generated
|
|
-// using clang.
|
|
-//
|
|
-// Calling convention source:
|
|
-// https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf Table 18.2
|
|
-
|
|
-#if V8_HOST_ARCH_RISCV64
|
|
-// 12 64-bit registers = 12 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 12,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 8, "Mismatch in word size");
|
|
-
|
|
-asm(".global SaveCalleeSavedRegisters \n"
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
- // a0: [ intptr_t* buffer ]
|
|
- // Save the callee-saved registers: s0-s11.
|
|
- " sd s11, 88(a0) \n"
|
|
- " sd s10, 80(a0) \n"
|
|
- " sd s9, 72(a0) \n"
|
|
- " sd s8, 64(a0) \n"
|
|
- " sd s7, 56(a0) \n"
|
|
- " sd s6, 48(a0) \n"
|
|
- " sd s5, 40(a0) \n"
|
|
- " sd s4, 32(a0) \n"
|
|
- " sd s3, 24(a0) \n"
|
|
- " sd s2, 16(a0) \n"
|
|
- " sd s1, 8(a0) \n"
|
|
- " sd s0, 0(a0) \n"
|
|
- // Return.
|
|
- " jr ra \n");
|
|
-#elif V8_HOST_ARCH_RISCV32
|
|
-// 12 32-bit registers = 12 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 12,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 4, "Mismatch in word size");
|
|
-
|
|
-asm(".global SaveCalleeSavedRegisters \n"
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
- // a0: [ intptr_t* buffer ]
|
|
- // Save the callee-saved registers: s0-s11.
|
|
- " sw s11, 44(a0) \n"
|
|
- " sw s10, 40(a0) \n"
|
|
- " sw s9, 36(a0) \n"
|
|
- " sw s8, 32(a0) \n"
|
|
- " sw s7, 28(a0) \n"
|
|
- " sw s6, 24(a0) \n"
|
|
- " sw s5, 20(a0) \n"
|
|
- " sw s4, 16(a0) \n"
|
|
- " sw s3, 12(a0) \n"
|
|
- " sw s2, 8(a0) \n"
|
|
- " sw s1, 4(a0) \n"
|
|
- " sw s0, 0(a0) \n"
|
|
- // Return.
|
|
- " jr ra \n");
|
|
-#endif
|
|
diff --git a/src/heap/base/asm/s390/push_registers_asm.cc b/src/heap/base/asm/s390/push_registers_asm.cc
|
|
new file mode 100644
|
|
index 0000000..ef954fa
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/s390/push_registers_asm.cc
|
|
@@ -0,0 +1,37 @@
|
|
+// Copyright 2020 the V8 project authors. All rights reserved.
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
+// found in the LICENSE file.
|
|
+
|
|
+// Push all callee-saved registers to get them on the stack for conservative
|
|
+// stack scanning.
|
|
+
|
|
+// See asm/x64/push_registers_clang.cc for why the function is not generated
|
|
+// using clang.
|
|
+
|
|
+// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
+// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
+
|
|
+// S390 ABI source:
|
|
+// http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html
|
|
+asm(".text \n"
|
|
+ ".align 8 \n"
|
|
+ ".globl PushAllRegistersAndIterateStack \n"
|
|
+ ".type PushAllRegistersAndIterateStack, %function \n"
|
|
+ ".hidden PushAllRegistersAndIterateStack \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+ // Push all callee-saved registers.
|
|
+ // r6-r13, r14 and sp(r15)
|
|
+ " stmg %r6, %sp, 48(%sp) \n"
|
|
+ // Allocate frame.
|
|
+ " lay %sp, -160(%sp) \n"
|
|
+ // Pass 1st parameter (r2) unchanged (Stack*).
|
|
+ // Pass 2nd parameter (r3) unchanged (StackVisitor*).
|
|
+ // Save 3rd parameter (r4; IterateStackCallback).
|
|
+ " lgr %r5, %r4 \n"
|
|
+ // Pass sp as 3rd parameter. 160+48 to point
|
|
+ // to callee saved region stored above.
|
|
+ " lay %r4, 208(%sp) \n"
|
|
+ // Call the callback.
|
|
+ " basr %r14, %r5 \n"
|
|
+ " lmg %r14,%sp, 272(%sp) \n"
|
|
+ " br %r14 \n");
|
|
diff --git a/src/heap/base/asm/s390/save_registers_asm.cc b/src/heap/base/asm/s390/save_registers_asm.cc
|
|
deleted file mode 100644
|
|
index be92cc2..0000000
|
|
--- a/v8/src/heap/base/asm/s390/save_registers_asm.cc
|
|
+++ /dev/null
|
|
@@ -1,34 +0,0 @@
|
|
-// Copyright 2020 the V8 project authors. All rights reserved.
|
|
-// Use of this source code is governed by a BSD-style license that can be
|
|
-// found in the LICENSE file.
|
|
-
|
|
-#include <src/heap/base/stack.h>
|
|
-
|
|
-// Save all callee-saved registers in the specified buffer.
|
|
-// extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-
|
|
-// See asm/x64/save_registers_asm.cc for why the function is not generated
|
|
-// using clang.
|
|
-//
|
|
-// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
-// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
-
|
|
-// S390 ABI source:
|
|
-// http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html
|
|
-
|
|
-// 10 64-bit registers = 10 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 10,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 8, "Mismatch in word size");
|
|
-
|
|
-asm(".text \n"
|
|
- ".align 8 \n"
|
|
- ".globl SaveCalleeSavedRegisters \n"
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
- // r2: [ intptr_t* buffer ]
|
|
- // Save the callee-saved registers: r6-r13, r14 and sp(r15).
|
|
- " stmg %r6, %sp, 0(%r2) \n"
|
|
- // Return.
|
|
- " br %r14 \n");
|
|
diff --git a/src/heap/base/asm/x64/push_registers_asm.cc b/src/heap/base/asm/x64/push_registers_asm.cc
|
|
new file mode 100644
|
|
index 0000000..1781a58
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/x64/push_registers_asm.cc
|
|
@@ -0,0 +1,106 @@
|
|
+// Copyright 2020 the V8 project authors. All rights reserved.
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
+// found in the LICENSE file.
|
|
+
|
|
+// Push all callee-saved registers to get them on the stack for conservative
|
|
+// stack scanning.
|
|
+//
|
|
+// We cannot rely on clang generating the function and right symbol mangling
|
|
+// as `__attribute__((naked))` does not prevent clang from generating TSAN
|
|
+// function entry stubs (`__tsan_func_entry`). Even with
|
|
+// `__attribute__((no_sanitize_thread)` annotation clang generates the entry
|
|
+// stub.
|
|
+// See https://bugs.llvm.org/show_bug.cgi?id=45400.
|
|
+
|
|
+// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
+// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
+// _WIN64 Defined as 1 when the compilation target is 64-bit ARM or x64.
|
|
+// Otherwise, undefined.
|
|
+#ifdef _WIN64
|
|
+
|
|
+// We maintain 16-byte alignment at calls. There is an 8-byte return address
|
|
+// on the stack and we push 232 bytes which maintains 16-byte stack alignment
|
|
+// at the call.
|
|
+// Source: https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
|
|
+asm(".globl PushAllRegistersAndIterateStack \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+ // rbp is callee-saved. Maintain proper frame pointer for debugging.
|
|
+ " push %rbp \n"
|
|
+ " mov %rsp, %rbp \n"
|
|
+ // Dummy for alignment.
|
|
+ " push $0xCDCDCD \n"
|
|
+ " push %rsi \n"
|
|
+ " push %rdi \n"
|
|
+ " push %rbx \n"
|
|
+ " push %r12 \n"
|
|
+ " push %r13 \n"
|
|
+ " push %r14 \n"
|
|
+ " push %r15 \n"
|
|
+ " sub $160, %rsp \n"
|
|
+ // Use aligned instrs as we are certain that the stack is properly aligned.
|
|
+ " movdqa %xmm6, 144(%rsp) \n"
|
|
+ " movdqa %xmm7, 128(%rsp) \n"
|
|
+ " movdqa %xmm8, 112(%rsp) \n"
|
|
+ " movdqa %xmm9, 96(%rsp) \n"
|
|
+ " movdqa %xmm10, 80(%rsp) \n"
|
|
+ " movdqa %xmm11, 64(%rsp) \n"
|
|
+ " movdqa %xmm12, 48(%rsp) \n"
|
|
+ " movdqa %xmm13, 32(%rsp) \n"
|
|
+ " movdqa %xmm14, 16(%rsp) \n"
|
|
+ " movdqa %xmm15, (%rsp) \n"
|
|
+ // Pass 1st parameter (rcx) unchanged (Stack*).
|
|
+ // Pass 2nd parameter (rdx) unchanged (StackVisitor*).
|
|
+ // Save 3rd parameter (r8; IterateStackCallback)
|
|
+ " mov %r8, %r9 \n"
|
|
+ // Pass 3rd parameter as rsp (stack pointer).
|
|
+ " mov %rsp, %r8 \n"
|
|
+ // Call the callback.
|
|
+ " call *%r9 \n"
|
|
+ // Pop the callee-saved registers.
|
|
+ " add $224, %rsp \n"
|
|
+ // Restore rbp as it was used as frame pointer.
|
|
+ " pop %rbp \n"
|
|
+ " ret \n");
|
|
+
|
|
+#else // !_WIN64
|
|
+
|
|
+// We maintain 16-byte alignment at calls. There is an 8-byte return address
|
|
+// on the stack and we push 56 bytes which maintains 16-byte stack alignment
|
|
+// at the call.
|
|
+// Source: https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf
|
|
+asm(
|
|
+#ifdef __APPLE__
|
|
+ ".globl _PushAllRegistersAndIterateStack \n"
|
|
+ ".private_extern _PushAllRegistersAndIterateStack \n"
|
|
+ "_PushAllRegistersAndIterateStack: \n"
|
|
+#else // !__APPLE__
|
|
+ ".globl PushAllRegistersAndIterateStack \n"
|
|
+ ".type PushAllRegistersAndIterateStack, %function \n"
|
|
+ ".hidden PushAllRegistersAndIterateStack \n"
|
|
+ "PushAllRegistersAndIterateStack: \n"
|
|
+#endif // !__APPLE__
|
|
+ // rbp is callee-saved. Maintain proper frame pointer for debugging.
|
|
+ " push %rbp \n"
|
|
+ " mov %rsp, %rbp \n"
|
|
+ // Dummy for alignment.
|
|
+ " push $0xCDCDCD \n"
|
|
+ " push %rbx \n"
|
|
+ " push %r12 \n"
|
|
+ " push %r13 \n"
|
|
+ " push %r14 \n"
|
|
+ " push %r15 \n"
|
|
+ // Pass 1st parameter (rdi) unchanged (Stack*).
|
|
+ // Pass 2nd parameter (rsi) unchanged (StackVisitor*).
|
|
+ // Save 3rd parameter (rdx; IterateStackCallback)
|
|
+ " mov %rdx, %r8 \n"
|
|
+ // Pass 3rd parameter as rsp (stack pointer).
|
|
+ " mov %rsp, %rdx \n"
|
|
+ // Call the callback.
|
|
+ " call *%r8 \n"
|
|
+ // Pop the callee-saved registers.
|
|
+ " add $48, %rsp \n"
|
|
+ // Restore rbp as it was used as frame pointer.
|
|
+ " pop %rbp \n"
|
|
+ " ret \n");
|
|
+
|
|
+#endif // !_WIN64
|
|
diff --git a/src/heap/base/asm/x64/push_registers_masm.asm b/src/heap/base/asm/x64/push_registers_masm.asm
|
|
new file mode 100644
|
|
index 0000000..a32e193
|
|
--- /dev/null
|
|
+++ b/v8/src/heap/base/asm/x64/push_registers_masm.asm
|
|
@@ -0,0 +1,57 @@
|
|
+;; Copyright 2020 the V8 project authors. All rights reserved.
|
|
+;; Use of this source code is governed by a BSD-style license that can be
|
|
+;; found in the LICENSE file.
|
|
+
|
|
+;; MASM syntax
|
|
+;; https://docs.microsoft.com/en-us/cpp/assembler/masm/microsoft-macro-assembler-reference?view=vs-2019
|
|
+
|
|
+public PushAllRegistersAndIterateStack
|
|
+
|
|
+.code
|
|
+PushAllRegistersAndIterateStack:
|
|
+ ;; Push all callee-saved registers to get them on the stack for conservative
|
|
+ ;; stack scanning.
|
|
+ ;;
|
|
+ ;; We maintain 16-byte alignment at calls. There is an 8-byte return address
|
|
+ ;; on the stack and we push 232 bytes which maintains 16-byte stack
|
|
+ ;; alignment at the call.
|
|
+ ;; Source: https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
|
|
+ ;;
|
|
+ ;; rbp is callee-saved. Maintain proper frame pointer for debugging.
|
|
+ push rbp
|
|
+ mov rbp, rsp
|
|
+ push 0CDCDCDh ;; Dummy for alignment.
|
|
+ push rsi
|
|
+ push rdi
|
|
+ push rbx
|
|
+ push r12
|
|
+ push r13
|
|
+ push r14
|
|
+ push r15
|
|
+ sub rsp, 160
|
|
+ ;; Use aligned instrs as we are certain that the stack is properly aligned.
|
|
+ movdqa xmmword ptr [rsp + 144], xmm6
|
|
+ movdqa xmmword ptr [rsp + 128], xmm7
|
|
+ movdqa xmmword ptr [rsp + 112], xmm8
|
|
+ movdqa xmmword ptr [rsp + 96], xmm9
|
|
+ movdqa xmmword ptr [rsp + 80], xmm10
|
|
+ movdqa xmmword ptr [rsp + 64], xmm11
|
|
+ movdqa xmmword ptr [rsp + 48], xmm12
|
|
+ movdqa xmmword ptr [rsp + 32], xmm13
|
|
+ movdqa xmmword ptr [rsp + 16], xmm14
|
|
+ movdqa xmmword ptr [rsp], xmm15
|
|
+ ;; Pass 1st parameter (rcx) unchanged (Stack*).
|
|
+ ;; Pass 2nd parameter (rdx) unchanged (StackVisitor*).
|
|
+ ;; Save 3rd parameter (r8; IterateStackCallback)
|
|
+ mov r9, r8
|
|
+ ;; Pass 3rd parameter as rsp (stack pointer).
|
|
+ mov r8, rsp
|
|
+ ;; Call the callback.
|
|
+ call r9
|
|
+ ;; Pop the callee-saved registers.
|
|
+ add rsp, 224
|
|
+ ;; Restore rbp as it was used as frame pointer.
|
|
+ pop rbp
|
|
+ ret
|
|
+
|
|
+end
|
|
diff --git a/src/heap/base/asm/x64/save_registers_asm.cc b/src/heap/base/asm/x64/save_registers_asm.cc
|
|
deleted file mode 100644
|
|
index 855a654..0000000
|
|
--- a/v8/src/heap/base/asm/x64/save_registers_asm.cc
|
|
+++ /dev/null
|
|
@@ -1,94 +0,0 @@
|
|
-// Copyright 2020 the V8 project authors. All rights reserved.
|
|
-// Use of this source code is governed by a BSD-style license that can be
|
|
-// found in the LICENSE file.
|
|
-
|
|
-#include <src/heap/base/stack.h>
|
|
-
|
|
-// Save all callee-saved registers in the specified buffer.
|
|
-// extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-//
|
|
-// We cannot rely on clang generating the function and right symbol mangling
|
|
-// as `__attribute__((naked))` does not prevent clang from generating TSAN
|
|
-// function entry stubs (`__tsan_func_entry`). Even with
|
|
-// `__attribute__((no_sanitize_thread)` annotation clang generates the entry
|
|
-// stub.
|
|
-// See https://bugs.llvm.org/show_bug.cgi?id=45400.
|
|
-//
|
|
-// Do not depend on V8_TARGET_OS_* defines as some embedders may override the
|
|
-// GN toolchain (e.g. ChromeOS) and not provide them.
|
|
-// _WIN64 Defined as 1 when the compilation target is 64-bit ARM or x64.
|
|
-// Otherwise, undefined.
|
|
-
|
|
-#ifdef _WIN64
|
|
-// Source: https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
|
|
-
|
|
-// 7 64-bit registers + 1 for alignment purposes = 8 * 1 = 8 intprt_t
|
|
-// 10 128-bit registers = 10 * 2 = 20 intptr_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 28,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 8, "Mismatch in word size");
|
|
-
|
|
-asm(".globl SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
- // %rcx: [ intptr_t* buffer ]
|
|
- // %rbp is callee-saved. Maintain proper frame pointer for debugging.
|
|
- " push %rbp \n"
|
|
- " mov %rsp, %rbp \n"
|
|
- // Save the callee-saved registers.
|
|
- " mov %rsi, 0(%rcx) \n"
|
|
- " mov %rdi, 8(%rcx) \n"
|
|
- " mov %rbx, 16(%rcx) \n"
|
|
- " mov %r12, 24(%rcx) \n"
|
|
- " mov %r13, 32(%rcx) \n"
|
|
- " mov %r14, 40(%rcx) \n"
|
|
- " mov %r15, 48(%rcx) \n"
|
|
- // Skip one slot to achieve proper alignment and use aligned instructions,
|
|
- // as we are sure that the buffer is properly aligned.
|
|
- " movdqa %xmm6, 64(%rcx) \n"
|
|
- " movdqa %xmm7, 80(%rcx) \n"
|
|
- " movdqa %xmm8, 96(%rcx) \n"
|
|
- " movdqa %xmm9, 112(%rcx) \n"
|
|
- " movdqa %xmm10, 128(%rcx) \n"
|
|
- " movdqa %xmm11, 144(%rcx) \n"
|
|
- " movdqa %xmm12, 160(%rcx) \n"
|
|
- " movdqa %xmm13, 176(%rcx) \n"
|
|
- " movdqa %xmm14, 192(%rcx) \n"
|
|
- " movdqa %xmm15, 208(%rcx) \n"
|
|
- // Return.
|
|
- " pop %rbp \n"
|
|
- " ret \n");
|
|
-
|
|
-#else // !_WIN64
|
|
-// Source: https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf
|
|
-
|
|
-// 5 64-bit registers = 5 intprt_t
|
|
-static_assert(heap::base::Stack::NumberOfCalleeSavedRegisters() == 5,
|
|
- "Mismatch in the number of callee-saved registers");
|
|
-static_assert(sizeof(intptr_t) == 8, "Mismatch in word size");
|
|
-
|
|
-asm(
|
|
-#ifdef __APPLE__
|
|
- ".globl _SaveCalleeSavedRegisters \n"
|
|
- ".private_extern _SaveCalleeSavedRegisters \n"
|
|
- "_SaveCalleeSavedRegisters: \n"
|
|
-#else // !__APPLE__
|
|
- ".globl SaveCalleeSavedRegisters \n"
|
|
- ".type SaveCalleeSavedRegisters, %function \n"
|
|
- ".hidden SaveCalleeSavedRegisters \n"
|
|
- "SaveCalleeSavedRegisters: \n"
|
|
-#endif // !__APPLE__
|
|
- // %rdi: [ intptr_t* buffer ]
|
|
- // %rbp is callee-saved. Maintain proper frame pointer for debugging.
|
|
- " push %rbp \n"
|
|
- " mov %rsp, %rbp \n"
|
|
- // Save the callee-saved registers.
|
|
- " mov %rbx, 0(%rdi) \n"
|
|
- " mov %r12, 8(%rdi) \n"
|
|
- " mov %r13, 16(%rdi) \n"
|
|
- " mov %r14, 24(%rdi) \n"
|
|
- " mov %r15, 32(%rdi) \n"
|
|
- // Restore %rbp as it was used as frame pointer and return.
|
|
- " pop %rbp \n"
|
|
- " ret \n");
|
|
-
|
|
-#endif // !_WIN64
|
|
diff --git a/src/heap/base/asm/x64/save_registers_masm.asm b/src/heap/base/asm/x64/save_registers_masm.asm
|
|
deleted file mode 100644
|
|
index 29946a4..0000000
|
|
--- a/v8/src/heap/base/asm/x64/save_registers_masm.asm
|
|
+++ /dev/null
|
|
@@ -1,43 +0,0 @@
|
|
-;; Copyright 2020 the V8 project authors. All rights reserved.
|
|
-;; Use of this source code is governed by a BSD-style license that can be
|
|
-;; found in the LICENSE file.
|
|
-
|
|
-;; MASM syntax
|
|
-;; https://docs.microsoft.com/en-us/cpp/assembler/masm/microsoft-macro-assembler-reference?view=vs-2019
|
|
-
|
|
-public SaveCalleeSavedRegisters
|
|
-
|
|
-.code
|
|
- ;; Save all callee-saved registers in the specified buffer.
|
|
- ;; extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
-
|
|
-SaveCalleeSavedRegisters:
|
|
- ;; %rcx: [ intptr_t* buffer ]
|
|
- ;; %rbp is callee-saved. Maintain proper frame pointer for debugging.
|
|
- push rbp
|
|
- mov rbp, rsp
|
|
- ;; Save the callee-saved registers.
|
|
- mov qword ptr [rcx], rsi
|
|
- mov qword ptr [rcx + 8], rdi
|
|
- mov qword ptr [rcx + 16], rbx
|
|
- mov qword ptr [rcx + 24], r12
|
|
- mov qword ptr [rcx + 32], r13
|
|
- mov qword ptr [rcx + 40], r14
|
|
- mov qword ptr [rcx + 48], r15
|
|
- ;; Skip one slot to achieve proper alignment and use aligned instructions,
|
|
- ;; as we are sure that the buffer is properly aligned.
|
|
- movdqa xmmword ptr [rcx + 64], xmm6
|
|
- movdqa xmmword ptr [rcx + 80], xmm7
|
|
- movdqa xmmword ptr [rcx + 96], xmm8
|
|
- movdqa xmmword ptr [rcx + 112], xmm9
|
|
- movdqa xmmword ptr [rcx + 128], xmm10
|
|
- movdqa xmmword ptr [rcx + 144], xmm11
|
|
- movdqa xmmword ptr [rcx + 160], xmm12
|
|
- movdqa xmmword ptr [rcx + 176], xmm13
|
|
- movdqa xmmword ptr [rcx + 192], xmm14
|
|
- movdqa xmmword ptr [rcx + 208], xmm15
|
|
- ;; Restore %rbp as it was used as frame pointer and return.
|
|
- pop rbp
|
|
- ret
|
|
-
|
|
-end
|
|
diff --git a/src/heap/base/stack.cc b/src/heap/base/stack.cc
|
|
index d8e618d..54a8697 100644
|
|
--- a/v8/src/heap/base/stack.cc
|
|
+++ b/v8/src/heap/base/stack.cc
|
|
@@ -6,18 +6,21 @@
|
|
|
|
#include <limits>
|
|
|
|
+#include "src/base/platform/platform.h"
|
|
#include "src/base/sanitizer/asan.h"
|
|
#include "src/base/sanitizer/msan.h"
|
|
#include "src/base/sanitizer/tsan.h"
|
|
|
|
namespace heap::base {
|
|
|
|
-Stack::Stack(const void* stack_start) : stack_start_(stack_start) {}
|
|
-
|
|
-void Stack::SetStackStart(const void* stack_start) {
|
|
- DCHECK(!context_);
|
|
- stack_start_ = stack_start;
|
|
-}
|
|
+// Function with architecture-specific implementation:
|
|
+// Pushes all callee-saved registers to the stack and invokes the callback,
|
|
+// passing the supplied pointers (stack and argument) and the intended stack
|
|
+// marker.
|
|
+using IterateStackCallback = void (*)(const Stack*, StackVisitor*, const void*);
|
|
+extern "C" void PushAllRegistersAndIterateStack(const Stack* stack,
|
|
+ StackVisitor* visitor,
|
|
+ IterateStackCallback callback);
|
|
|
|
bool Stack::IsOnStack(const void* slot) const {
|
|
DCHECK_NOT_NULL(stack_start_);
|
|
@@ -141,97 +144,62 @@
|
|
|
|
} // namespace
|
|
|
|
-void Stack::IteratePointers(StackVisitor* visitor) const {
|
|
- DCHECK_NOT_NULL(stack_start_);
|
|
- DCHECK(context_);
|
|
- DCHECK_NOT_NULL(context_->stack_marker);
|
|
-
|
|
+// static
|
|
+void Stack::IteratePointersImpl(const Stack* stack, StackVisitor* visitor,
|
|
+ const void* stack_end) {
|
|
#ifdef V8_USE_ADDRESS_SANITIZER
|
|
const void* asan_fake_stack = __asan_get_current_fake_stack();
|
|
#else
|
|
const void* asan_fake_stack = nullptr;
|
|
#endif // V8_USE_ADDRESS_SANITIZER
|
|
|
|
- // Iterate through the registers.
|
|
- for (intptr_t value : context_->registers) {
|
|
- const void* address = reinterpret_cast<const void*>(value);
|
|
- MSAN_MEMORY_IS_INITIALIZED(&address, sizeof(address));
|
|
- if (address == nullptr) continue;
|
|
- visitor->VisitPointer(address);
|
|
- IterateAsanFakeFrameIfNecessary(visitor, asan_fake_stack, stack_start_,
|
|
- context_->stack_marker, address);
|
|
- }
|
|
-
|
|
// Iterate through the stack.
|
|
// All supported platforms should have their stack aligned to at least
|
|
// sizeof(void*).
|
|
constexpr size_t kMinStackAlignment = sizeof(void*);
|
|
- CHECK_EQ(0u, reinterpret_cast<uintptr_t>(context_->stack_marker) &
|
|
- (kMinStackAlignment - 1));
|
|
- IteratePointersInStack(
|
|
- visitor, reinterpret_cast<const void* const*>(context_->stack_marker),
|
|
- stack_start_, asan_fake_stack);
|
|
+ CHECK_EQ(0u,
|
|
+ reinterpret_cast<uintptr_t>(stack_end) & (kMinStackAlignment - 1));
|
|
+ IteratePointersInStack(visitor,
|
|
+ reinterpret_cast<const void* const*>(stack_end),
|
|
+ stack->stack_start_, asan_fake_stack);
|
|
|
|
- for (const auto& stack : inactive_stacks_) {
|
|
- IteratePointersInStack(visitor, stack.top, stack.start, asan_fake_stack);
|
|
+ for (const auto& segment : stack->inactive_stacks_) {
|
|
+ IteratePointersInStack(visitor, segment.top, segment.start,
|
|
+ asan_fake_stack);
|
|
}
|
|
|
|
IterateUnsafeStackIfNecessary(visitor);
|
|
}
|
|
|
|
-namespace {
|
|
-// Function with architecture-specific implementation:
|
|
-// Saves all callee-saved registers in the specified buffer.
|
|
-extern "C" void SaveCalleeSavedRegisters(intptr_t* buffer);
|
|
+void Stack::IteratePointers(StackVisitor* visitor) const {
|
|
+ // TODO(v8:13493): Remove the implication as soon as IsOnCurrentStack is
|
|
+ // compatible with stack switching.
|
|
+ DCHECK_IMPLIES(!wasm_stack_switching_, IsOnCurrentStack(stack_start_));
|
|
+ PushAllRegistersAndIterateStack(this, visitor, &IteratePointersImpl);
|
|
+ // No need to deal with callee-saved registers as they will be kept alive by
|
|
+ // the regular conservative stack iteration.
|
|
+ // TODO(chromium:1056170): Add support for SIMD and/or filtering.
|
|
+ IterateUnsafeStackIfNecessary(visitor);
|
|
+}
|
|
+
|
|
+void Stack::IteratePointersUnsafe(StackVisitor* visitor,
|
|
+ const void* stack_end) const {
|
|
+ DCHECK_NOT_NULL(stack_start_);
|
|
+ DCHECK_NOT_NULL(stack_end);
|
|
+ DCHECK_GE(stack_start_, stack_end);
|
|
+ IteratePointersImpl(this, visitor, stack_end);
|
|
+}
|
|
|
|
#ifdef DEBUG
|
|
-
|
|
-bool IsOnCurrentStack(const void* ptr) {
|
|
+// static
|
|
+bool Stack::IsOnCurrentStack(const void* ptr) {
|
|
DCHECK_NOT_NULL(ptr);
|
|
const void* current_stack_start = v8::base::Stack::GetStackStart();
|
|
const void* current_stack_top = v8::base::Stack::GetCurrentStackPosition();
|
|
return ptr <= current_stack_start && ptr >= current_stack_top;
|
|
}
|
|
-
|
|
#endif // DEBUG
|
|
|
|
-} // namespace
|
|
-
|
|
-void Stack::SaveContext(bool check_invariant) {
|
|
- // TODO(v8:13493): Remove the method's parameter and the implication as soon
|
|
- // as IsOnCurrentStack is compatible with stack switching.
|
|
- DCHECK_IMPLIES(check_invariant, IsOnCurrentStack(stack_start_));
|
|
- // Contexts can be nested but the marker and the registers are only saved on
|
|
- // the first invocation.
|
|
- if (context_) {
|
|
- ++context_->nesting_counter;
|
|
- return;
|
|
- }
|
|
- // Allocate the context and set the marker.
|
|
- const void* stack_top = v8::base::Stack::GetCurrentStackPosition();
|
|
- DCHECK_NOT_NULL(stack_top);
|
|
- context_ = std::make_unique<Context>(stack_top);
|
|
- // TODO(v8:13493): Remove the implication as soon as IsValidMarker is
|
|
- // compatible with stack switching.
|
|
- DCHECK_IMPLIES(check_invariant, stack_top <= stack_start_);
|
|
- context_->stack_marker = stack_top;
|
|
- // Save the registers.
|
|
- SaveCalleeSavedRegisters(context_->registers.data());
|
|
-}
|
|
-
|
|
-void Stack::ClearContext(bool check_invariant) {
|
|
- // TODO(v8:13493): Remove the method's parameter and the implication as soon
|
|
- // as IsOnCurrentStack is compatible with stack switching.
|
|
- DCHECK_IMPLIES(check_invariant, IsOnCurrentStack(stack_start_));
|
|
- DCHECK(context_);
|
|
- // Skip clearing the context if that was a nested invocation.
|
|
- if (context_->nesting_counter > 0) {
|
|
- --context_->nesting_counter;
|
|
- return;
|
|
- }
|
|
- context_.reset();
|
|
-}
|
|
-
|
|
void Stack::AddStackSegment(const void* start, const void* top) {
|
|
DCHECK_LE(top, start);
|
|
inactive_stacks_.push_back({start, top});
|
|
diff --git a/src/heap/base/stack.h b/src/heap/base/stack.h
|
|
index 06edf4c..4b0a14e 100644
|
|
--- a/v8/src/heap/base/stack.h
|
|
+++ b/v8/src/heap/base/stack.h
|
|
@@ -5,10 +5,9 @@
|
|
#ifndef V8_HEAP_BASE_STACK_H_
|
|
#define V8_HEAP_BASE_STACK_H_
|
|
|
|
-#include <memory>
|
|
+#include <vector>
|
|
|
|
#include "src/base/macros.h"
|
|
-#include "src/base/platform/platform.h"
|
|
|
|
namespace heap::base {
|
|
|
|
@@ -30,96 +29,54 @@
|
|
// of relevant GC stack regions where interesting pointers can be found.
|
|
class V8_EXPORT_PRIVATE Stack final {
|
|
public:
|
|
- // The size of the buffer for storing the callee-saved registers is going to
|
|
- // be equal to kNumberOfCalleeSavedRegisters * sizeof(intptr_t).
|
|
- // This is architecture-specific.
|
|
- static constexpr int NumberOfCalleeSavedRegisters() {
|
|
- return Context::kNumberOfCalleeSavedRegisters;
|
|
- }
|
|
-
|
|
- explicit Stack(const void* stack_start = nullptr);
|
|
+ explicit Stack(const void* stack_start = nullptr,
|
|
+ bool wasm_stack_switching = false)
|
|
+ : stack_start_(stack_start),
|
|
+ wasm_stack_switching_(wasm_stack_switching) {}
|
|
|
|
// Sets the start of the stack.
|
|
- void SetStackStart(const void* stack_start);
|
|
+ void SetStackStart(const void* stack_start, bool wasm_stack_switching) {
|
|
+ stack_start_ = stack_start;
|
|
+ wasm_stack_switching_ = wasm_stack_switching;
|
|
+ }
|
|
|
|
// Returns true if |slot| is part of the stack and false otherwise.
|
|
bool IsOnStack(const void* slot) const;
|
|
|
|
- // Word-aligned iteration of the stack and the saved registers.
|
|
- // Slot values are passed on to `visitor`.
|
|
+ // Word-aligned iteration of the stack. Callee-saved registers are pushed to
|
|
+ // the stack before iterating pointers. Slot values are passed on to
|
|
+ // `visitor`.
|
|
void IteratePointers(StackVisitor* visitor) const;
|
|
|
|
- // Saves and clears the stack context, i.e., it sets the stack marker and
|
|
- // saves the registers.
|
|
- // TODO(v8:13493): The parameter is for suppressing the invariant check in
|
|
- // the case of WASM stack switching. It will be removed as soon as context
|
|
- // saving becomes compatible with stack switching.
|
|
- void SaveContext(bool check_invariant = true);
|
|
- void ClearContext(bool check_invariant = true);
|
|
+ // Word-aligned iteration of the stack, starting at `stack_end`. Slot values
|
|
+ // are passed on to `visitor`. This is intended to be used with verifiers that
|
|
+ // only visit a subset of the stack of IteratePointers().
|
|
+ //
|
|
+ // **Ignores:**
|
|
+ // - Callee-saved registers.
|
|
+ // - SafeStack.
|
|
+ void IteratePointersUnsafe(StackVisitor* visitor,
|
|
+ const void* stack_end) const;
|
|
|
|
void AddStackSegment(const void* start, const void* top);
|
|
void ClearStackSegments();
|
|
|
|
private:
|
|
- struct Context {
|
|
- // The following constant is architecture-specific.
|
|
-#if V8_HOST_ARCH_IA32
|
|
- // Must be consistent with heap/base/asm/ia32/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 3;
|
|
-#elif V8_HOST_ARCH_X64
|
|
-#ifdef _WIN64
|
|
- // Must be consistent with heap/base/asm/x64/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 28;
|
|
-#else // !_WIN64
|
|
- // Must be consistent with heap/base/asm/x64/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 5;
|
|
-#endif // !_WIN64
|
|
-#elif V8_HOST_ARCH_ARM64
|
|
- // Must be consistent with heap/base/asm/arm64/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 11;
|
|
-#elif V8_HOST_ARCH_ARM
|
|
- // Must be consistent with heap/base/asm/arm/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 8;
|
|
-#elif V8_HOST_ARCH_PPC64
|
|
- // Must be consistent with heap/base/asm/ppc/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 20;
|
|
-#elif V8_HOST_ARCH_PPC
|
|
- // Must be consistent with heap/base/asm/ppc/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 20;
|
|
-#elif V8_HOST_ARCH_MIPS64
|
|
- // Must be consistent with heap/base/asm/mips64el/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 9;
|
|
-#elif V8_HOST_ARCH_LOONG64
|
|
- // Must be consistent with heap/base/asm/loong64/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 11;
|
|
-#elif V8_HOST_ARCH_S390
|
|
- // Must be consistent with heap/base/asm/s390/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 10;
|
|
-#elif V8_HOST_ARCH_RISCV32
|
|
- // Must be consistent with heap/base/asm/riscv/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 12;
|
|
-#elif V8_HOST_ARCH_RISCV64
|
|
- // Must be consistent with heap/base/asm/riscv/.
|
|
- static constexpr int kNumberOfCalleeSavedRegisters = 12;
|
|
-#else
|
|
-#error Unknown architecture.
|
|
+#ifdef DEBUG
|
|
+ static bool IsOnCurrentStack(const void* ptr);
|
|
#endif
|
|
|
|
- explicit Context(const void* marker) : stack_marker(marker) {}
|
|
-
|
|
- int nesting_counter = 0;
|
|
- const void* stack_marker;
|
|
- // We always double-align this buffer, to support for longer registers,
|
|
- // e.g., 128-bit registers in WIN64.
|
|
- alignas(2 * sizeof(intptr_t))
|
|
- std::array<intptr_t, kNumberOfCalleeSavedRegisters> registers;
|
|
- };
|
|
+ static void IteratePointersImpl(const Stack* stack, StackVisitor* visitor,
|
|
+ const void* stack_end);
|
|
|
|
const void* stack_start_;
|
|
- std::unique_ptr<Context> context_;
|
|
|
|
- // Stack segments that may also contain pointers and should be
|
|
- // scanned.
|
|
+ // TODO(v8:13493): This is for suppressing the check that we are in the
|
|
+ // correct stack, in the case of WASM stack switching. It will be removed as
|
|
+ // soon as context saving becomes compatible with stack switching.
|
|
+ bool wasm_stack_switching_;
|
|
+
|
|
+ // Stack segments that may also contain pointers and should be scanned.
|
|
struct StackSegments {
|
|
const void* start;
|
|
const void* top;
|
|
diff --git a/src/heap/cppgc-js/cpp-heap.cc b/src/heap/cppgc-js/cpp-heap.cc
|
|
index c27c612..63c5212 100644
|
|
--- a/v8/src/heap/cppgc-js/cpp-heap.cc
|
|
+++ b/v8/src/heap/cppgc-js/cpp-heap.cc
|
|
@@ -16,6 +16,7 @@
|
|
#include "src/base/logging.h"
|
|
#include "src/base/macros.h"
|
|
#include "src/base/optional.h"
|
|
+#include "src/base/platform/platform.h"
|
|
#include "src/base/platform/time.h"
|
|
#include "src/execution/isolate-inl.h"
|
|
#include "src/flags/flags.h"
|
|
@@ -839,7 +840,7 @@
|
|
const size_t bytes_allocated_in_prefinalizers = ExecutePreFinalizers();
|
|
#if CPPGC_VERIFY_HEAP
|
|
UnifiedHeapMarkingVerifier verifier(*this, *collection_type_);
|
|
- verifier.Run(stack_state_of_prev_gc(),
|
|
+ verifier.Run(stack_state_of_prev_gc(), stack_end_of_current_gc(),
|
|
stats_collector()->marked_bytes_on_current_cycle() +
|
|
bytes_allocated_in_prefinalizers);
|
|
#endif // CPPGC_VERIFY_HEAP
|
|
@@ -942,7 +943,7 @@
|
|
// Finish sweeping in case it is still running.
|
|
sweeper().FinishIfRunning();
|
|
|
|
- SaveStackContextScope stack_context_scope(stack());
|
|
+ SetStackEndOfCurrentGC(v8::base::Stack::GetCurrentStackPosition());
|
|
|
|
if (isolate_) {
|
|
reinterpret_cast<v8::Isolate*>(isolate_)
|
|
diff --git a/src/heap/cppgc/heap-base.h b/src/heap/cppgc/heap-base.h
|
|
index ac1dd3f..29a88b2 100644
|
|
--- a/v8/src/heap/cppgc/heap-base.h
|
|
+++ b/v8/src/heap/cppgc/heap-base.h
|
|
@@ -183,6 +183,13 @@
|
|
stack_state_of_prev_gc_ = stack_state;
|
|
}
|
|
|
|
+ const void* stack_end_of_current_gc() const {
|
|
+ return stack_end_of_current_gc_;
|
|
+ }
|
|
+ void SetStackEndOfCurrentGC(const void* stack_end) {
|
|
+ stack_end_of_current_gc_ = stack_end;
|
|
+ }
|
|
+
|
|
void SetInAtomicPauseForTesting(bool value) { in_atomic_pause_ = value; }
|
|
|
|
virtual void StartIncrementalGarbageCollectionForTesting() = 0;
|
|
@@ -288,6 +295,10 @@
|
|
EmbedderStackState::kNoHeapPointers;
|
|
std::unique_ptr<EmbedderStackState> override_stack_state_;
|
|
|
|
+ // Marker that signals end of the interesting stack region in which on-heap
|
|
+ // pointers can be found.
|
|
+ const void* stack_end_of_current_gc_ = nullptr;
|
|
+
|
|
bool in_atomic_pause_ = false;
|
|
|
|
int creation_thread_id_ = v8::base::OS::GetCurrentThreadId();
|
|
diff --git a/src/heap/cppgc/heap.cc b/src/heap/cppgc/heap.cc
|
|
index 7769412..28a11fc 100644
|
|
--- a/v8/src/heap/cppgc/heap.cc
|
|
+++ b/v8/src/heap/cppgc/heap.cc
|
|
@@ -166,10 +166,9 @@
|
|
DCHECK(!in_no_gc_scope());
|
|
CHECK(!in_disallow_gc_scope());
|
|
config_.stack_state = stack_state;
|
|
+ SetStackEndOfCurrentGC(v8::base::Stack::GetCurrentStackPosition());
|
|
in_atomic_pause_ = true;
|
|
|
|
- stack()->SaveContext();
|
|
-
|
|
#if defined(CPPGC_YOUNG_GENERATION)
|
|
// Check if the young generation was enabled. We must enable young generation
|
|
// before calling the custom weak callbacks to make sure that the callbacks
|
|
@@ -188,7 +187,7 @@
|
|
const size_t bytes_allocated_in_prefinalizers = ExecutePreFinalizers();
|
|
#if CPPGC_VERIFY_HEAP
|
|
MarkingVerifier verifier(*this, config_.collection_type);
|
|
- verifier.Run(config_.stack_state,
|
|
+ verifier.Run(config_.stack_state, stack_end_of_current_gc(),
|
|
stats_collector()->marked_bytes_on_current_cycle() +
|
|
bytes_allocated_in_prefinalizers);
|
|
#endif // CPPGC_VERIFY_HEAP
|
|
@@ -197,8 +196,6 @@
|
|
#endif
|
|
USE(bytes_allocated_in_prefinalizers);
|
|
|
|
- stack()->ClearContext();
|
|
-
|
|
#if defined(CPPGC_YOUNG_GENERATION)
|
|
ResetRememberedSet();
|
|
#endif // defined(CPPGC_YOUNG_GENERATION)
|
|
diff --git a/src/heap/cppgc/marking-verifier.cc b/src/heap/cppgc/marking-verifier.cc
|
|
index 5508766..b7127c2 100644
|
|
--- a/v8/src/heap/cppgc/marking-verifier.cc
|
|
+++ b/v8/src/heap/cppgc/marking-verifier.cc
|
|
@@ -45,7 +45,8 @@
|
|
collection_type_(collection_type) {}
|
|
|
|
void MarkingVerifierBase::Run(
|
|
- StackState stack_state, v8::base::Optional<size_t> expected_marked_bytes) {
|
|
+ StackState stack_state, const void* stack_end,
|
|
+ v8::base::Optional<size_t> expected_marked_bytes) {
|
|
Traverse(heap_.raw_heap());
|
|
// Avoid verifying the stack when running with TSAN as the TSAN runtime changes
|
|
// stack contents when e.g. working with locks. Specifically, the marker uses
|
|
@@ -62,7 +63,7 @@
|
|
#if !defined(THREAD_SANITIZER) && !defined(CPPGC_POINTER_COMPRESSION)
|
|
if (stack_state == StackState::kMayContainHeapPointers) {
|
|
in_construction_objects_ = &in_construction_objects_stack_;
|
|
- heap_.stack()->IteratePointers(this);
|
|
+ heap_.stack()->IteratePointersUnsafe(this, stack_end);
|
|
// The objects found through the unsafe iteration are only a subset of the
|
|
// regular iteration as they miss objects held alive only from callee-saved
|
|
// registers that are never pushed on the stack and SafeStack.
|
|
diff --git a/src/heap/cppgc/marking-verifier.h b/src/heap/cppgc/marking-verifier.h
|
|
index 5132b3a..5136f29 100644
|
|
--- a/v8/src/heap/cppgc/marking-verifier.h
|
|
+++ b/v8/src/heap/cppgc/marking-verifier.h
|
|
@@ -41,7 +41,7 @@
|
|
MarkingVerifierBase(const MarkingVerifierBase&) = delete;
|
|
MarkingVerifierBase& operator=(const MarkingVerifierBase&) = delete;
|
|
|
|
- void Run(StackState, v8::base::Optional<size_t>);
|
|
+ void Run(StackState, const void*, v8::base::Optional<size_t>);
|
|
|
|
protected:
|
|
MarkingVerifierBase(HeapBase&, CollectionType, VerificationState&,
|
|
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
|
|
index 4994a3a..f4b7da0 100644
|
|
--- a/v8/src/heap/heap.cc
|
|
+++ b/v8/src/heap/heap.cc
|
|
@@ -1685,7 +1685,22 @@
|
|
DevToolsTraceEventScope devtools_trace_event_scope(
|
|
this, IsYoungGenerationCollector(collector) ? "MinorGC" : "MajorGC",
|
|
GarbageCollectionReasonToString(gc_reason));
|
|
- SaveStackContextScope stack_context_scope(&stack());
|
|
+
|
|
+ if (cpp_heap()) {
|
|
+ if (collector == GarbageCollector::MARK_COMPACTOR ||
|
|
+ (collector == GarbageCollector::MINOR_MARK_COMPACTOR &&
|
|
+ CppHeap::From(cpp_heap())->generational_gc_supported())) {
|
|
+ // CppHeap needs a stack marker at the top of all entry points to allow
|
|
+ // deterministic passes over the stack. E.g., a verifier that should
|
|
+ // only find a subset of references of the marker.
|
|
+ //
|
|
+ // TODO(chromium:1056170): Consider adding a component that keeps track
|
|
+ // of relevant GC stack regions where interesting pointers can be found.
|
|
+ static_cast<v8::internal::CppHeap*>(cpp_heap())
|
|
+ ->SetStackEndOfCurrentGC(
|
|
+ v8::base::Stack::GetCurrentStackPosition());
|
|
+ }
|
|
+ }
|
|
|
|
GarbageCollectionPrologue(gc_reason, gc_callback_flags);
|
|
{
|
|
@@ -2396,8 +2411,6 @@
|
|
DCHECK(incremental_marking_->IsStopped());
|
|
DCHECK_NOT_NULL(isolate()->global_safepoint());
|
|
|
|
- SaveStackContextScope stack_context_scope(&stack());
|
|
-
|
|
isolate()->global_safepoint()->IterateClientIsolates([](Isolate* client) {
|
|
client->heap()->FreeSharedLinearAllocationAreas();
|
|
|
|
@@ -5809,7 +5822,12 @@
|
|
}
|
|
|
|
void Heap::SetStackStart(void* stack_start) {
|
|
- stack().SetStackStart(stack_start);
|
|
+#if V8_ENABLE_WEBASSEMBLY
|
|
+ stack().SetStackStart(stack_start,
|
|
+ v8_flags.experimental_wasm_stack_switching);
|
|
+#else
|
|
+ stack().SetStackStart(stack_start, false);
|
|
+#endif // V8_ENABLE_WEBASSEMBLY
|
|
}
|
|
|
|
::heap::base::Stack& Heap::stack() {
|
|
@@ -6391,8 +6409,7 @@
|
|
filtering_(filtering),
|
|
filter_(nullptr),
|
|
space_iterator_(nullptr),
|
|
- object_iterator_(nullptr),
|
|
- stack_context_scope_(&heap->stack()) {
|
|
+ object_iterator_(nullptr) {
|
|
heap_->MakeHeapIterable();
|
|
// Start the iteration.
|
|
space_iterator_ = new SpaceIterator(heap_);
|
|
@@ -7371,28 +7388,5 @@
|
|
CppClassNamesAsHeapObjectNameScope::~CppClassNamesAsHeapObjectNameScope() =
|
|
default;
|
|
|
|
-SaveStackContextScope::SaveStackContextScope(::heap::base::Stack* stack)
|
|
- : stack_(stack) {
|
|
-#if V8_ENABLE_WEBASSEMBLY
|
|
- // TODO(v8:13493): Do not check the stack context invariant if WASM stack
|
|
- // switching is enabled. This will be removed as soon as context saving
|
|
- // becomes compatible with stack switching.
|
|
- stack_->SaveContext(!v8_flags.experimental_wasm_stack_switching);
|
|
-#else
|
|
- stack_->SaveContext();
|
|
-#endif // V8_ENABLE_WEBASSEMBLY
|
|
-}
|
|
-
|
|
-SaveStackContextScope::~SaveStackContextScope() {
|
|
-#if V8_ENABLE_WEBASSEMBLY
|
|
- // TODO(v8:13493): Do not check the stack context invariant if WASM stack
|
|
- // switching is enabled. This will be removed as soon as context saving
|
|
- // becomes compatible with stack switching.
|
|
- stack_->ClearContext(!v8_flags.experimental_wasm_stack_switching);
|
|
-#else
|
|
- stack_->ClearContext();
|
|
-#endif // V8_ENABLE_WEBASSEMBLY
|
|
-}
|
|
-
|
|
} // namespace internal
|
|
} // namespace v8
|
|
diff --git a/src/heap/heap.h b/src/heap/heap.h
|
|
index c93d89c..bc565ca 100644
|
|
--- a/v8/src/heap/heap.h
|
|
+++ b/v8/src/heap/heap.h
|
|
@@ -2633,17 +2633,6 @@
|
|
Heap* heap_;
|
|
};
|
|
|
|
-// TODO(v8:13493): This class will move to src/heap/base/stack.h once its
|
|
-// implementation no longer needs access to V8 flags.
|
|
-class V8_EXPORT_PRIVATE V8_NODISCARD SaveStackContextScope {
|
|
- public:
|
|
- explicit SaveStackContextScope(::heap::base::Stack* stack);
|
|
- ~SaveStackContextScope();
|
|
-
|
|
- protected:
|
|
- ::heap::base::Stack* stack_;
|
|
-};
|
|
-
|
|
class V8_NODISCARD DisableConservativeStackScanningScopeForTesting {
|
|
public:
|
|
explicit inline DisableConservativeStackScanningScopeForTesting(Heap* heap)
|
|
@@ -2695,7 +2684,6 @@
|
|
SpaceIterator* space_iterator_;
|
|
// Object iterator for the space currently being iterated.
|
|
std::unique_ptr<ObjectIterator> object_iterator_;
|
|
- SaveStackContextScope stack_context_scope_;
|
|
|
|
DISALLOW_GARBAGE_COLLECTION(no_heap_allocation_)
|
|
};
|
|
diff --git a/src/profiler/heap-snapshot-generator.cc b/src/profiler/heap-snapshot-generator.cc
|
|
index e076418..f0b3058 100644
|
|
--- a/v8/src/profiler/heap-snapshot-generator.cc
|
|
+++ b/v8/src/profiler/heap-snapshot-generator.cc
|
|
@@ -2055,16 +2055,14 @@
|
|
// its custom name to a generic builtin.
|
|
RootsReferencesExtractor extractor(this);
|
|
ReadOnlyRoots(heap_).Iterate(&extractor);
|
|
- {
|
|
- SaveStackContextScope scope(&heap_->stack());
|
|
- heap_->IterateRoots(&extractor, base::EnumSet<SkipRoot>{SkipRoot::kWeak});
|
|
- // TODO(v8:11800): The heap snapshot generator incorrectly considers the
|
|
- // weak string tables as strong retainers. Move IterateWeakRoots after
|
|
- // SetVisitingWeakRoots.
|
|
- heap_->IterateWeakRoots(&extractor, {});
|
|
- extractor.SetVisitingWeakRoots();
|
|
- heap_->IterateWeakGlobalHandles(&extractor);
|
|
- }
|
|
+ heap_->IterateRoots(&extractor, base::EnumSet<SkipRoot>{SkipRoot::kWeak});
|
|
+ // TODO(v8:11800): The heap snapshot generator incorrectly considers the weak
|
|
+ // string tables as strong retainers. Move IterateWeakRoots after
|
|
+ // SetVisitingWeakRoots.
|
|
+ heap_->IterateWeakRoots(&extractor, {});
|
|
+ extractor.SetVisitingWeakRoots();
|
|
+ heap_->IterateWeakGlobalHandles(&extractor);
|
|
+
|
|
bool interrupted = false;
|
|
|
|
CombinedHeapObjectIterator iterator(heap_,
|