[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}
This commit is contained in:
parent
562b65a86e
commit
472429e623
20
BUILD.bazel
20
BUILD.bazel
@ -3201,16 +3201,16 @@ filegroup(
|
||||
# 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"],
|
||||
}),
|
||||
)
|
||||
|
||||
|
24
BUILD.gn
24
BUILD.gn
@ -5989,31 +5989,31 @@ v8_source_set("v8_heap_base") {
|
||||
|
||||
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" ]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3075,8 +3075,7 @@ void Isolate::RecordStackSwitchForScanning() {
|
||||
.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 @@ void Isolate::Delete(Isolate* isolate) {
|
||||
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_;
|
||||
|
@ -44,10 +44,13 @@ void ThreadLocalTop::Initialize(Isolate* isolate) {
|
||||
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);
|
||||
|
39
src/heap/base/asm/arm/push_registers_asm.cc
Normal file
39
src/heap/base/asm/arm/push_registers_asm.cc
Normal file
@ -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");
|
@ -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");
|
62
src/heap/base/asm/arm64/push_registers_asm.cc
Normal file
62
src/heap/base/asm/arm64/push_registers_asm.cc
Normal file
@ -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");
|
32
src/heap/base/asm/arm64/push_registers_masm.S
Normal file
32
src/heap/base/asm/arm64/push_registers_masm.S
Normal file
@ -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
|
@ -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");
|
@ -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
|
53
src/heap/base/asm/ia32/push_registers_asm.cc
Normal file
53
src/heap/base/asm/ia32/push_registers_asm.cc
Normal file
@ -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");
|
48
src/heap/base/asm/ia32/push_registers_masm.asm
Normal file
48
src/heap/base/asm/ia32/push_registers_masm.asm
Normal file
@ -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
|
@ -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");
|
@ -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
|
48
src/heap/base/asm/loong64/push_registers_asm.cc
Normal file
48
src/heap/base/asm/loong64/push_registers_asm.cc
Normal file
@ -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");
|
@ -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");
|
49
src/heap/base/asm/mips64/push_registers_asm.cc
Normal file
49
src/heap/base/asm/mips64/push_registers_asm.cc
Normal file
@ -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");
|
@ -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");
|
97
src/heap/base/asm/ppc/push_registers_asm.cc
Normal file
97
src/heap/base/asm/ppc/push_registers_asm.cc
Normal file
@ -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");
|
@ -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__
|
93
src/heap/base/asm/riscv/push_registers_asm.cc
Normal file
93
src/heap/base/asm/riscv/push_registers_asm.cc
Normal file
@ -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
|
@ -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
|
37
src/heap/base/asm/s390/push_registers_asm.cc
Normal file
37
src/heap/base/asm/s390/push_registers_asm.cc
Normal file
@ -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");
|
@ -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");
|
106
src/heap/base/asm/x64/push_registers_asm.cc
Normal file
106
src/heap/base/asm/x64/push_registers_asm.cc
Normal file
@ -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
|
57
src/heap/base/asm/x64/push_registers_masm.asm
Normal file
57
src/heap/base/asm/x64/push_registers_masm.asm
Normal file
@ -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
|
@ -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
|
@ -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
|
@ -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 @@ void IteratePointersInStack(StackVisitor* visitor, const void* top,
|
||||
|
||||
} // 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});
|
||||
|
@ -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 @@ class StackVisitor {
|
||||
// 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;
|
||||
|
@ -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 @@ void CppHeap::TraceEpilogue() {
|
||||
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 @@ void CppHeap::CollectGarbageForTesting(CollectionType collection_type,
|
||||
// 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_)
|
||||
|
@ -183,6 +183,13 @@ class V8_EXPORT_PRIVATE HeapBase : public cppgc::HeapHandle {
|
||||
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 @@ class V8_EXPORT_PRIVATE HeapBase : public cppgc::HeapHandle {
|
||||
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();
|
||||
|
@ -166,10 +166,9 @@ void Heap::FinalizeGarbageCollection(StackState stack_state) {
|
||||
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 @@ void Heap::FinalizeGarbageCollection(StackState stack_state) {
|
||||
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 @@ void Heap::FinalizeGarbageCollection(StackState stack_state) {
|
||||
#endif
|
||||
USE(bytes_allocated_in_prefinalizers);
|
||||
|
||||
stack()->ClearContext();
|
||||
|
||||
#if defined(CPPGC_YOUNG_GENERATION)
|
||||
ResetRememberedSet();
|
||||
#endif // defined(CPPGC_YOUNG_GENERATION)
|
||||
|
@ -45,7 +45,8 @@ MarkingVerifierBase::MarkingVerifierBase(
|
||||
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 @@ void MarkingVerifierBase::Run(
|
||||
#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.
|
||||
|
@ -41,7 +41,7 @@ class V8_EXPORT_PRIVATE MarkingVerifierBase
|
||||
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&,
|
||||
|
@ -1685,7 +1685,22 @@ bool Heap::CollectGarbage(AllocationSpace space,
|
||||
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 @@ void Heap::PerformSharedGarbageCollection(Isolate* initiator,
|
||||
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 @@ const cppgc::EmbedderStackState* Heap::overriden_stack_state() const {
|
||||
}
|
||||
|
||||
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 @@ HeapObjectIterator::HeapObjectIterator(
|
||||
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(
|
||||
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
|
||||
|
@ -2633,17 +2633,6 @@ class V8_NODISCARD IgnoreLocalGCRequests {
|
||||
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_;
|
||||
};
|
||||
|
||||
// Space iterator for iterating over all the paged spaces of the heap: Map
|
||||
// space, old space and code space. Returns each space in turn, and null when it
|
||||
// is done.
|
||||
@ -2695,7 +2684,6 @@ class V8_EXPORT_PRIVATE HeapObjectIterator {
|
||||
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_)
|
||||
};
|
||||
|
@ -2055,16 +2055,14 @@ bool V8HeapExplorer::IterateAndExtractReferences(
|
||||
// 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_,
|
||||
|
@ -75,6 +75,8 @@ TEST(ExternalString_ExternalBackingStoreSizeDecreases) {
|
||||
Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
|
||||
ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;
|
||||
|
||||
i::DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap);
|
||||
|
||||
const size_t backing_store_before =
|
||||
heap->old_space()->ExternalBackingStoreBytes(type);
|
||||
|
||||
@ -104,6 +106,8 @@ TEST(ExternalString_ExternalBackingStoreSizeIncreasesMarkCompact) {
|
||||
heap::AbandonCurrentlyFreeMemory(heap->old_space());
|
||||
ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;
|
||||
|
||||
i::DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap);
|
||||
|
||||
const size_t backing_store_before =
|
||||
heap->old_space()->ExternalBackingStoreBytes(type);
|
||||
|
||||
@ -139,6 +143,8 @@ TEST(ExternalString_ExternalBackingStoreSizeIncreasesAfterExternalization) {
|
||||
ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;
|
||||
size_t old_backing_store_before = 0, new_backing_store_before = 0;
|
||||
|
||||
i::DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap);
|
||||
|
||||
{
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
@ -166,9 +172,9 @@ TEST(ExternalString_ExternalBackingStoreSizeIncreasesAfterExternalization) {
|
||||
}
|
||||
|
||||
heap::GcAndSweep(heap, OLD_SPACE);
|
||||
|
||||
CHECK_EQ(0, heap->old_space()->ExternalBackingStoreBytes(type) -
|
||||
old_backing_store_before);
|
||||
const size_t backing_store_after =
|
||||
heap->old_space()->ExternalBackingStoreBytes(type);
|
||||
CHECK_EQ(0, backing_store_after - old_backing_store_before);
|
||||
}
|
||||
|
||||
TEST(ExternalString_PromotedThinString) {
|
||||
|
@ -6873,27 +6873,33 @@ UNINITIALIZED_TEST(RestoreHeapLimit) {
|
||||
reinterpret_cast<Isolate*>(v8::Isolate::New(create_params));
|
||||
Heap* heap = isolate->heap();
|
||||
Factory* factory = isolate->factory();
|
||||
OutOfMemoryState state;
|
||||
state.heap = heap;
|
||||
state.oom_triggered = false;
|
||||
heap->AddNearHeapLimitCallback(NearHeapLimitCallback, &state);
|
||||
heap->AutomaticallyRestoreInitialHeapLimit(0.5);
|
||||
const int kFixedArrayLength = 1000000;
|
||||
|
||||
{
|
||||
HandleScope handle_scope(isolate);
|
||||
while (!state.oom_triggered) {
|
||||
factory->NewFixedArray(kFixedArrayLength);
|
||||
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap);
|
||||
|
||||
OutOfMemoryState state;
|
||||
state.heap = heap;
|
||||
state.oom_triggered = false;
|
||||
heap->AddNearHeapLimitCallback(NearHeapLimitCallback, &state);
|
||||
heap->AutomaticallyRestoreInitialHeapLimit(0.5);
|
||||
const int kFixedArrayLength = 1000000;
|
||||
{
|
||||
HandleScope handle_scope(isolate);
|
||||
while (!state.oom_triggered) {
|
||||
factory->NewFixedArray(kFixedArrayLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
heap->MemoryPressureNotification(MemoryPressureLevel::kCritical, true);
|
||||
state.oom_triggered = false;
|
||||
{
|
||||
HandleScope handle_scope(isolate);
|
||||
while (!state.oom_triggered) {
|
||||
factory->NewFixedArray(kFixedArrayLength);
|
||||
heap->MemoryPressureNotification(MemoryPressureLevel::kCritical, true);
|
||||
state.oom_triggered = false;
|
||||
{
|
||||
HandleScope handle_scope(isolate);
|
||||
while (!state.oom_triggered) {
|
||||
factory->NewFixedArray(kFixedArrayLength);
|
||||
}
|
||||
}
|
||||
CHECK_EQ(state.current_heap_limit, state.initial_heap_limit);
|
||||
}
|
||||
CHECK_EQ(state.current_heap_limit, state.initial_heap_limit);
|
||||
|
||||
reinterpret_cast<v8::Isolate*>(isolate)->Dispose();
|
||||
}
|
||||
|
||||
|
@ -29110,6 +29110,9 @@ TEST(TriggerMainThreadMetricsEvent) {
|
||||
using v8::Local;
|
||||
using v8::MaybeLocal;
|
||||
|
||||
i::DisableConservativeStackScanningScopeForTesting no_stack_scanning(
|
||||
CcTest::heap());
|
||||
|
||||
// Set up isolate and context.
|
||||
v8::Isolate* iso = CcTest::isolate();
|
||||
i::Isolate* i_iso = reinterpret_cast<i::Isolate*>(iso);
|
||||
|
@ -86,8 +86,7 @@ TEST_F(ConservativeStackVisitorTest, DirectBasePointer) {
|
||||
volatile Address ptr = recorder->base_address();
|
||||
|
||||
ConservativeStackVisitor stack_visitor(isolate(), recorder.get());
|
||||
SaveStackContextScope stack_context_scope(&heap()->stack());
|
||||
isolate()->heap()->stack().IteratePointers(&stack_visitor);
|
||||
heap()->stack().IteratePointers(&stack_visitor);
|
||||
|
||||
// Make sure to keep the pointer alive.
|
||||
EXPECT_NE(kNullAddress, ptr);
|
||||
@ -108,8 +107,7 @@ TEST_F(ConservativeStackVisitorTest, TaggedBasePointer) {
|
||||
volatile Address ptr = recorder->tagged_address();
|
||||
|
||||
ConservativeStackVisitor stack_visitor(isolate(), recorder.get());
|
||||
SaveStackContextScope stack_context_scope(&heap()->stack());
|
||||
isolate()->heap()->stack().IteratePointers(&stack_visitor);
|
||||
heap()->stack().IteratePointers(&stack_visitor);
|
||||
|
||||
// Make sure to keep the pointer alive.
|
||||
EXPECT_NE(kNullAddress, ptr);
|
||||
@ -130,8 +128,7 @@ TEST_F(ConservativeStackVisitorTest, InnerPointer) {
|
||||
volatile Address ptr = recorder->inner_address();
|
||||
|
||||
ConservativeStackVisitor stack_visitor(isolate(), recorder.get());
|
||||
SaveStackContextScope stack_context_scope(&heap()->stack());
|
||||
isolate()->heap()->stack().IteratePointers(&stack_visitor);
|
||||
heap()->stack().IteratePointers(&stack_visitor);
|
||||
|
||||
// Make sure to keep the pointer alive.
|
||||
EXPECT_NE(kNullAddress, ptr);
|
||||
@ -154,8 +151,7 @@ TEST_F(ConservativeStackVisitorTest, HalfWord1) {
|
||||
volatile uint32_t ptr[] = {recorder->compr_address(), 0};
|
||||
|
||||
ConservativeStackVisitor stack_visitor(isolate(), recorder.get());
|
||||
SaveStackContextScope stack_context_scope(&heap()->stack());
|
||||
isolate()->heap()->stack().IteratePointers(&stack_visitor);
|
||||
heap()->stack().IteratePointers(&stack_visitor);
|
||||
|
||||
// Make sure to keep the pointer alive.
|
||||
EXPECT_NE(static_cast<uint32_t>(0), ptr[0]);
|
||||
@ -176,8 +172,7 @@ TEST_F(ConservativeStackVisitorTest, HalfWord2) {
|
||||
volatile uint32_t ptr[] = {0, recorder->compr_address()};
|
||||
|
||||
ConservativeStackVisitor stack_visitor(isolate(), recorder.get());
|
||||
SaveStackContextScope stack_context_scope(&heap()->stack());
|
||||
isolate()->heap()->stack().IteratePointers(&stack_visitor);
|
||||
heap()->stack().IteratePointers(&stack_visitor);
|
||||
|
||||
// Make sure to keep the pointer alive.
|
||||
EXPECT_NE(static_cast<uint32_t>(0), ptr[1]);
|
||||
@ -198,8 +193,7 @@ TEST_F(ConservativeStackVisitorTest, InnerHalfWord1) {
|
||||
volatile uint32_t ptr[] = {recorder->compr_inner(), 0};
|
||||
|
||||
ConservativeStackVisitor stack_visitor(isolate(), recorder.get());
|
||||
SaveStackContextScope stack_context_scope(&heap()->stack());
|
||||
isolate()->heap()->stack().IteratePointers(&stack_visitor);
|
||||
heap()->stack().IteratePointers(&stack_visitor);
|
||||
|
||||
// Make sure to keep the pointer alive.
|
||||
EXPECT_NE(static_cast<uint32_t>(0), ptr[0]);
|
||||
@ -220,8 +214,7 @@ TEST_F(ConservativeStackVisitorTest, InnerHalfWord2) {
|
||||
volatile uint32_t ptr[] = {0, recorder->compr_inner()};
|
||||
|
||||
ConservativeStackVisitor stack_visitor(isolate(), recorder.get());
|
||||
SaveStackContextScope stack_context_scope(&heap()->stack());
|
||||
isolate()->heap()->stack().IteratePointers(&stack_visitor);
|
||||
heap()->stack().IteratePointers(&stack_visitor);
|
||||
|
||||
// Make sure to keep the pointer alive.
|
||||
EXPECT_NE(static_cast<uint32_t>(0), ptr[1]);
|
||||
|
@ -29,9 +29,7 @@ class MarkerTest : public testing::TestWithHeap {
|
||||
const MarkingConfig config = {CollectionType::kMajor, stack_state};
|
||||
auto* heap = Heap::From(GetHeap());
|
||||
InitializeMarker(*heap, GetPlatformHandle().get(), config);
|
||||
heap->stack()->SaveContext();
|
||||
marker_->FinishMarking(stack_state);
|
||||
heap->stack()->ClearContext();
|
||||
// Pretend do finish sweeping as StatsCollector verifies that Notify*
|
||||
// methods are called in the right order.
|
||||
heap->stats_collector()->NotifySweepingCompleted(
|
||||
@ -252,9 +250,7 @@ TEST_F(MarkerTest, InConstructionObjectIsEventuallyMarkedEmptyStack) {
|
||||
marker->Visitor().Trace(member);
|
||||
});
|
||||
EXPECT_FALSE(HeapObjectHeader::FromObject(object).IsMarked());
|
||||
Heap::From(GetHeap())->stack()->SaveContext();
|
||||
marker()->FinishMarking(StackState::kMayContainHeapPointers);
|
||||
Heap::From(GetHeap())->stack()->ClearContext();
|
||||
EXPECT_TRUE(HeapObjectHeader::FromObject(object).IsMarked());
|
||||
}
|
||||
|
||||
@ -263,14 +259,11 @@ TEST_F(MarkerTest, InConstructionObjectIsEventuallyMarkedNonEmptyStack) {
|
||||
StackState::kMayContainHeapPointers};
|
||||
InitializeMarker(*Heap::From(GetHeap()), GetPlatformHandle().get(), config);
|
||||
MakeGarbageCollected<GCedWithCallback>(
|
||||
GetAllocationHandle(), [stack = Heap::From(GetHeap())->stack(),
|
||||
marker = marker()](GCedWithCallback* obj) {
|
||||
GetAllocationHandle(), [marker = marker()](GCedWithCallback* obj) {
|
||||
Member<GCedWithCallback> member(obj);
|
||||
marker->Visitor().Trace(member);
|
||||
EXPECT_FALSE(HeapObjectHeader::FromObject(obj).IsMarked());
|
||||
stack->SaveContext();
|
||||
marker->FinishMarking(StackState::kMayContainHeapPointers);
|
||||
stack->ClearContext();
|
||||
EXPECT_TRUE(HeapObjectHeader::FromObject(obj).IsMarked());
|
||||
});
|
||||
}
|
||||
@ -327,9 +320,7 @@ TEST_F(MarkerTest,
|
||||
RegisterInConstructionObject(GetAllocationHandle(), marker()->Visitor(),
|
||||
storage);
|
||||
EXPECT_FALSE(HeapObjectHeader::FromObject(storage.object()).IsMarked());
|
||||
Heap::From(GetHeap())->stack()->SaveContext();
|
||||
marker()->FinishMarking(StackState::kMayContainHeapPointers);
|
||||
Heap::From(GetHeap())->stack()->ClearContext();
|
||||
EXPECT_TRUE(HeapObjectHeader::FromObject(storage.object()).IsMarked());
|
||||
}
|
||||
|
||||
@ -409,9 +400,7 @@ class IncrementalMarkingTest : public testing::TestWithHeap {
|
||||
}
|
||||
|
||||
void FinishMarking() {
|
||||
Heap::From(GetHeap())->stack()->SaveContext();
|
||||
GetMarkerRef()->FinishMarking(StackState::kMayContainHeapPointers);
|
||||
Heap::From(GetHeap())->stack()->ClearContext();
|
||||
// Pretend do finish sweeping as StatsCollector verifies that Notify*
|
||||
// methods are called in the right order.
|
||||
GetMarkerRef().reset();
|
||||
|
@ -23,10 +23,9 @@ class MarkingVerifierTest : public testing::TestWithHeap {
|
||||
V8_NOINLINE void VerifyMarking(HeapBase& heap, StackState stack_state,
|
||||
size_t expected_marked_bytes) {
|
||||
Heap::From(GetHeap())->object_allocator().ResetLinearAllocationBuffers();
|
||||
Heap::From(GetHeap())->stack()->SaveContext();
|
||||
MarkingVerifier verifier(heap, CollectionType::kMajor);
|
||||
verifier.Run(stack_state, expected_marked_bytes);
|
||||
Heap::From(GetHeap())->stack()->ClearContext();
|
||||
verifier.Run(stack_state, v8::base::Stack::GetCurrentStackPosition(),
|
||||
expected_marked_bytes);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -83,9 +83,7 @@ TEST_F(GCStackTest, IteratePointersFindsOnStackValue) {
|
||||
{
|
||||
int* volatile tmp = scanner->needle();
|
||||
USE(tmp);
|
||||
GetStack()->SaveContext();
|
||||
GetStack()->IteratePointers(scanner.get());
|
||||
GetStack()->ClearContext();
|
||||
EXPECT_TRUE(scanner->found());
|
||||
}
|
||||
}
|
||||
@ -100,9 +98,7 @@ TEST_F(GCStackTest, IteratePointersFindsOnStackValuePotentiallyUnaligned) {
|
||||
USE(a);
|
||||
int* volatile tmp = scanner->needle();
|
||||
USE(tmp);
|
||||
GetStack()->SaveContext();
|
||||
GetStack()->IteratePointers(scanner.get());
|
||||
GetStack()->ClearContext();
|
||||
EXPECT_TRUE(scanner->found());
|
||||
}
|
||||
}
|
||||
@ -147,9 +143,7 @@ V8_NOINLINE void* RecursivelyPassOnParameterImpl(void* p1, void* p2, void* p3,
|
||||
nullptr, nullptr, nullptr, p7, stack,
|
||||
visitor);
|
||||
} else if (p8) {
|
||||
stack->SaveContext();
|
||||
stack->IteratePointers(visitor);
|
||||
stack->ClearContext();
|
||||
return p8;
|
||||
}
|
||||
return nullptr;
|
||||
@ -160,9 +154,7 @@ V8_NOINLINE void* RecursivelyPassOnParameter(size_t num, void* parameter,
|
||||
StackVisitor* visitor) {
|
||||
switch (num) {
|
||||
case 0:
|
||||
stack->SaveContext();
|
||||
stack->IteratePointers(visitor);
|
||||
stack->ClearContext();
|
||||
return parameter;
|
||||
case 1:
|
||||
return RecursivelyPassOnParameterImpl(nullptr, nullptr, nullptr, nullptr,
|
||||
@ -298,9 +290,7 @@ extern "C" V8_NOINLINE
|
||||
#endif // defined(__clang__)
|
||||
void
|
||||
IteratePointersNoMangling(Stack* stack, StackVisitor* visitor) {
|
||||
stack->SaveContext();
|
||||
stack->IteratePointers(visitor);
|
||||
stack->ClearContext();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -478,9 +468,7 @@ class CheckStackAlignmentVisitor final : public StackVisitor {
|
||||
|
||||
TEST_F(GCStackTest, StackAlignment) {
|
||||
auto checker = std::make_unique<CheckStackAlignmentVisitor>();
|
||||
GetStack()->SaveContext();
|
||||
GetStack()->IteratePointers(checker.get());
|
||||
GetStack()->ClearContext();
|
||||
}
|
||||
#endif // V8_OS_LINUX && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
|
||||
|
||||
|
@ -29,9 +29,7 @@ class WeakContainerTest : public testing::TestWithHeap {
|
||||
}
|
||||
|
||||
void FinishMarking(StackState stack_state) {
|
||||
Heap::From(GetHeap())->stack()->SaveContext();
|
||||
GetMarkerRef()->FinishMarking(stack_state);
|
||||
Heap::From(GetHeap())->stack()->ClearContext();
|
||||
marked_bytes_ =
|
||||
Heap::From(GetHeap())->AsBase().stats_collector()->marked_bytes();
|
||||
GetMarkerRef().reset();
|
||||
|
@ -26,9 +26,7 @@ class V8_NODISCARD IncrementalMarkingScope {
|
||||
explicit IncrementalMarkingScope(MarkerBase* marker) : marker_(marker) {}
|
||||
|
||||
~IncrementalMarkingScope() V8_NOEXCEPT {
|
||||
marker_->heap().stack()->SaveContext();
|
||||
marker_->FinishMarking(kIncrementalConfig.stack_state);
|
||||
marker_->heap().stack()->ClearContext();
|
||||
}
|
||||
|
||||
static constexpr MarkingConfig kIncrementalConfig{
|
||||
|
Loading…
Reference in New Issue
Block a user