cppgc: Use inline asm to generate x64 stack scanning trampoline

Use inline asm to generate the x64 PushAllRegistersAndIterateStack
which is the trampoline for conservative stack scanning. Keep the
function definition as C code to allow clang to generate the correct
mangling for each platform.

This approach has the benefit that it immediately works for all
platforms that support clang.

Bug: chromium:1056170
Change-Id: Ic7a1c1b57e67ae1442bd8bda4e55d89112facfc7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2132787
Reviewed-by: Omer Katz <omerkatz@chromium.org>
Reviewed-by: Anton Bikineev <bikineev@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66958}
This commit is contained in:
Michael Lippautz 2020-04-02 00:11:38 +02:00 committed by Commit Bot
parent 7cba1ed502
commit be7e57665e
5 changed files with 99 additions and 66 deletions

View File

@ -346,6 +346,15 @@ config("libbase_config") {
}
}
# This config should be applied to code using the cppgc_base.
config("cppgc_base_config") {
if (target_cpu == "x64") {
if (is_clang) {
defines = [ "CPPGC_SUPPORTS_CONSERVATIVE_STACK_SCAN" ]
}
}
}
# This config should be applied to code using the libsampler.
config("libsampler_config") {
include_dirs = [ "include" ]
@ -3955,12 +3964,15 @@ v8_source_set("cppgc_base") {
]
if (target_cpu == "x64") {
if (!is_win) {
sources += [ "src/heap/cppgc/asm/x64/push_registers.S" ]
if (is_clang) {
sources += [ "src/heap/cppgc/asm/x64/push_registers_clang.cc" ]
}
}
configs = [ ":internal_config" ]
configs = [
":internal_config",
":cppgc_base_config",
]
public_deps = [ ":v8_libbase" ]
}

View File

@ -1,52 +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.
.att_syntax
.text
#if defined(V8_TARGET_OS_MACOSX) || defined(V8_TARGET_OS_IOS)
.globl _PushAllRegistersAndIterateStack
_PushAllRegistersAndIterateStack:
#else // !(defined(V8_TARGET_OS_MACOSX) || defined(V8_TARGET_OS_IOS))
.type PushAllRegistersAndIterateStack, %function
.global PushAllRegistersAndIterateStack
.hidden PushAllRegistersAndIterateStack
PushAllRegistersAndIterateStack:
#endif // !(defined(V8_TARGET_OS_MACOSX) || defined(V8_TARGET_OS_IOS))
// 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 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
//
// rbp is callee-saved. Maintain proper frame pointer for debugging.
push %rbp
mov %rsp, %rbp
push $0xCDCDCD // Dummy for alignment.
push %rbx
push %r12
push %r13
push %r14
push %r15
// Pass 1st parameter (rdi) unchanged (Stack*).
// Pass 2nd parameter (rsi) unchanged (StackVisitor*).
// Save 3rd parameter (rdx; IterateStackCallback)
mov %rdx, %r8
// Pass 3rd parameter as rsp (stack pointer).
mov %rsp, %rdx
// Call the callback.
call *%r8
// Pop the callee-saved registers.
add $48, %rsp
// Restore rbp as it was used as frame pointer.
pop %rbp
ret

View File

@ -0,0 +1,83 @@
// 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.
#ifndef V8_HAVE_TARGET_OS
#error "File assumes V8_TARGET_OS_* defines are present"
#endif // V8_HAVE_TARGET_OS
// Push all callee-saved registers to get them on the stack for conservative
// stack scanning.
//
// Do not add any C code to the function. The function is naked to avoid
// emitting a prologue/epilogue that could violate alginment computations.
extern "C" __attribute__((naked, noinline)) void
PushAllRegistersAndIterateStack(void* /* {Stack*} */,
void* /* {StackVisitor*} */,
void* /* {IterateStackCallback} */) {
#ifdef V8_TARGET_OS_WIN
// 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.
// Source: https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
asm volatile(
// 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"
// 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 $64, %rsp \n"
// Restore rbp as it was used as frame pointer.
" pop %rbp \n"
" ret \n");
#else // !V8_TARGET_OS_WIN
// 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 volatile(
// 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 // !V8_TARGET_OS_WIN
}

View File

@ -7,17 +7,6 @@
#include "src/base/macros.h"
// TODO(chromium:1056170): Implement all platforms.
// TODO(chromium:1056170): Should use HOST arch instead of target arch. Fix
// requires fixing e.g. simulator platforms.
#ifdef __clang__
#if defined(V8_TARGET_ARCH_X64)
#if !defined(V8_TARGET_OS_WIN)
#define CPPGC_SUPPORTS_CONSERVATIVE_STACK_SCAN 1
#endif
#endif
#endif
namespace cppgc {
namespace internal {

View File

@ -58,6 +58,7 @@ v8_source_set("cppgc_unittests_sources") {
configs = [
"../..:external_config",
"../..:internal_config_base",
"../..:cppgc_base_config",
]
deps = [