[build] Define V8_TARGET_OS_ and consider it in x64 codegen

This CL allows us to distinguish between the host- and target OS. The
host OS is defined by V8_OS_ macros (e.g. V8_OS_WIN). The target OS is
defined by V8_TARGET_OS_ macros (e.g. V8_TARGET_OS_WIN).

V8_TARGET_OS_ macros are defined by gn, based on the `target_os` gn
variable. If a V8_TARGET_OS_ is set, we also define V8_HAVE_TARGET_OS
(this determines fall-back behavior in V8; if it is not defined, we set
V8_TARGET_OS_ to equal the equivalent V8_OS_ define).

Besides adding the defines, this CL also adds logic to consider the
target OS in codegen. Specifically, x64 builds now look at the
V8_TARGET_OS_WIN define instead of V8_OS_WIN or _WIN64. This
effectively makes cross-compilation to x64 Windows in mksnapshot
possible.

In future work, we could add similar support for cross-compiling to
other platforms such as ia32 Windows.

Bug: v8:9736,chromium:803591
Change-Id: I689f3de8c206b743c4bef703f5ade0bba32ce995
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1809374
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63892}
This commit is contained in:
Jakob Gruber 2019-09-19 13:26:15 +02:00 committed by Commit Bot
parent ce304db8dc
commit 99d31b432f
13 changed files with 136 additions and 37 deletions

View File

@ -644,6 +644,30 @@ config("toolchain") {
defines += [ "V8_ANDROID_LOG_STDOUT" ]
}
# V8_TARGET_OS_ defines. The target OS may differ from host OS e.g. in
# mksnapshot. We additionally set V8_HAVE_TARGET_OS to determine that a
# target OS has in fact been set; otherwise we internally assume that target
# OS == host OS (see v8config.h).
if (target_os == "android") {
defines += [ "V8_HAVE_TARGET_OS" ]
defines += [ "V8_TARGET_OS_ANDROID" ]
} else if (target_os == "fuchsia") {
defines += [ "V8_HAVE_TARGET_OS" ]
defines += [ "V8_TARGET_OS_FUCHSIA" ]
} else if (target_os == "ios") {
defines += [ "V8_HAVE_TARGET_OS" ]
defines += [ "V8_TARGET_OS_IOS" ]
} else if (target_os == "linux") {
defines += [ "V8_HAVE_TARGET_OS" ]
defines += [ "V8_TARGET_OS_LINUX" ]
} else if (target_os == "mac") {
defines += [ "V8_HAVE_TARGET_OS" ]
defines += [ "V8_TARGET_OS_MACOSX" ]
} else if (target_os == "win") {
defines += [ "V8_HAVE_TARGET_OS" ]
defines += [ "V8_TARGET_OS_WIN" ]
}
# TODO(jochen): Support v8_enable_prof on Windows.
# TODO(jochen): Add support for compiling with simulators.

View File

@ -54,7 +54,7 @@
// -----------------------------------------------------------------------------
// Operating system detection
// Operating system detection (host)
//
// V8_OS_ANDROID - Android
// V8_OS_BSD - BSDish (Mac OS X, Net/Free/Open/DragonFlyBSD)
@ -122,6 +122,67 @@
# define V8_OS_WIN 1
#endif
// -----------------------------------------------------------------------------
// Operating system detection (target)
//
// V8_TARGET_OS_ANDROID
// V8_TARGET_OS_FUCHSIA
// V8_TARGET_OS_IOS
// V8_TARGET_OS_LINUX
// V8_TARGET_OS_MACOSX
// V8_TARGET_OS_WIN
//
// If not set explicitly, these fall back to corresponding V8_OS_ values.
#ifdef V8_HAVE_TARGET_OS
// The target OS is provided, just check that at least one known value is set.
# if !defined(V8_TARGET_OS_ANDROID) \
&& !defined(V8_TARGET_OS_FUCHSIA) \
&& !defined(V8_TARGET_OS_IOS) \
&& !defined(V8_TARGET_OS_LINUX) \
&& !defined(V8_TARGET_OS_MACOSX) \
&& !defined(V8_TARGET_OS_WIN)
# error No known target OS defined.
# endif
#else // V8_HAVE_TARGET_OS
# if defined(V8_TARGET_OS_ANDROID) \
|| defined(V8_TARGET_OS_FUCHSIA) \
|| defined(V8_TARGET_OS_IOS) \
|| defined(V8_TARGET_OS_LINUX) \
|| defined(V8_TARGET_OS_MACOSX) \
|| defined(V8_TARGET_OS_WIN)
# error A target OS is defined but V8_HAVE_TARGET_OS is unset.
# endif
// Fall back to the detected host OS.
#ifdef V8_OS_ANDROID
# define V8_TARGET_OS_ANDROID
#endif
#ifdef V8_OS_FUCHSIA
# define V8_TARGET_OS_FUCHSIA
#endif
#ifdef V8_OS_IOS
# define V8_TARGET_OS_IOS
#endif
#ifdef V8_OS_LINUX
# define V8_TARGET_OS_LINUX
#endif
#ifdef V8_OS_MACOSX
# define V8_TARGET_OS_MACOSX
#endif
#ifdef V8_OS_WIN
# define V8_TARGET_OS_WIN
#endif
#endif // V8_HAVE_TARGET_OS
// -----------------------------------------------------------------------------
// C library detection

View File

@ -401,13 +401,13 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
__ pushq(r13);
__ pushq(r14);
__ pushq(r15);
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
__ pushq(rdi); // Only callee save in Win64 ABI, argument in AMD64 ABI.
__ pushq(rsi); // Only callee save in Win64 ABI, argument in AMD64 ABI.
#endif
__ pushq(rbx);
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// On Win64 XMM6-XMM15 are callee-save.
__ AllocateStackSpace(EntryFrameConstants::kXMMRegistersBlockSize);
__ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0), xmm6);
@ -507,7 +507,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
}
// Restore callee-saved registers (X64 conventions).
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// On Win64 XMM6-XMM15 are callee-save
__ movdqu(xmm6, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0));
__ movdqu(xmm7, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1));
@ -523,7 +523,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
#endif
__ popq(rbx);
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI.
__ popq(rsi);
__ popq(rdi);
@ -611,17 +611,17 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
__ Push(rdi);
__ Push(arg_reg_4);
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// Load the previous frame pointer to access C arguments on stack
__ movq(kScratchRegister, Operand(rbp, 0));
// Load the number of arguments and setup pointer to the arguments.
__ movq(rax, Operand(kScratchRegister, EntryFrameConstants::kArgcOffset));
__ movq(rbx, Operand(kScratchRegister, EntryFrameConstants::kArgvOffset));
#else // _WIN64
#else // V8_TARGET_OS_WIN
// Load the number of arguments and setup pointer to the arguments.
__ movq(rax, r8);
__ movq(rbx, r9);
#endif // _WIN64
#endif // V8_TARGET_OS_WIN
// Current stack contents:
// [rsp + 2 * kSystemPointerSize ... ] : Internal frame
@ -2716,7 +2716,7 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
// If argv_mode == kArgvInRegister:
// r15: pointer to the first argument
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9. It requires the
// stack to be aligned to 16 bytes. It only allows a single-word to be
// returned in register rax. Larger return sizes must be written to an address
@ -2738,7 +2738,7 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
const Register kCCallArg3 = rcx;
const int kArgExtraStackSpace = 0;
const int kMaxRegisterResultSize = 2;
#endif // _WIN64
#endif // V8_TARGET_OS_WIN
// Enter the exit frame that transitions from JavaScript to C++.
int arg_stack_space =

View File

@ -102,7 +102,7 @@ class V8_EXPORT_PRIVATE TurboAssemblerBase : public Assembler {
static bool IsAddressableThroughRootRegister(
Isolate* isolate, const ExternalReference& reference);
#if V8_OS_WIN
#if V8_TARGET_OS_WIN
// Minimum page size. We must touch memory once per page when expanding the
// stack, to avoid access violations.
static constexpr int kStackPageSize = 4 * KB;

View File

@ -2441,7 +2441,7 @@ void TurboAssembler::LeaveFrame(StackFrame::Type type) {
popq(rbp);
}
#ifdef V8_OS_WIN
#ifdef V8_TARGET_OS_WIN
void TurboAssembler::AllocateStackSpace(Register bytes_scratch) {
// In windows, we cannot increment the stack size by more than one page
// (minimum page size is 4KB) without accessing at least one byte on the
@ -2509,7 +2509,7 @@ void MacroAssembler::EnterExitFramePrologue(bool save_rax,
void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space,
bool save_doubles) {
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
const int kShadowSpace = 4;
arg_stack_space += kShadowSpace;
#endif
@ -2613,7 +2613,7 @@ void MacroAssembler::LeaveExitFrameEpilogue() {
movq(c_entry_fp_operand, Immediate(0));
}
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
static const int kRegisterPassedArguments = 4;
#else
static const int kRegisterPassedArguments = 6;
@ -2632,7 +2632,7 @@ int TurboAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) {
// On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers
// and the caller does not reserve stack slots for them.
DCHECK_GE(num_arguments, 0);
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
const int kMinimumStackSlots = kRegisterPassedArguments;
if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
return num_arguments;

View File

@ -414,7 +414,7 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
// stack check, do it before calling this function because this function may
// write into the newly allocated space. It may also overwrite the given
// register's value, in the version that takes a register.
#ifdef V8_OS_WIN
#ifdef V8_TARGET_OS_WIN
void AllocateStackSpace(Register bytes_scratch);
void AllocateStackSpace(int bytes);
#else
@ -917,7 +917,7 @@ inline Operand NativeContextOperand() {
// Provides access to exit frame stack space (not GCed).
inline Operand StackSpaceOperand(int index) {
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
const int kShaddowSpace = 4;
return Operand(rsp, (index + kShaddowSpace) * kSystemPointerSize);
#else

View File

@ -88,7 +88,7 @@ constexpr int kNumJSCallerSaved = 5;
// Number of registers for which space is reserved in safepoints.
constexpr int kNumSafepointRegisters = 16;
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// Windows calling convention
constexpr Register arg_reg_1 = rcx;
constexpr Register arg_reg_2 = rdx;
@ -100,7 +100,7 @@ constexpr Register arg_reg_1 = rdi;
constexpr Register arg_reg_2 = rsi;
constexpr Register arg_reg_3 = rdx;
constexpr Register arg_reg_4 = rcx;
#endif // _WIN64
#endif // V8_TARGET_OS_WIN
#define DOUBLE_REGISTERS(V) \
V(xmm0) \

View File

@ -27,7 +27,7 @@ namespace {
// == x64 ====================================================================
// ===========================================================================
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// == x64 windows ============================================================
#define STACK_SHADOW_WORDS 4
#define PARAM_REGISTERS rcx, rdx, r8, r9
@ -39,12 +39,12 @@ namespace {
(1 << xmm9.code()) | (1 << xmm10.code()) | (1 << xmm11.code()) | \
(1 << xmm12.code()) | (1 << xmm13.code()) | (1 << xmm14.code()) | \
(1 << xmm15.code())
#else
#else // V8_TARGET_OS_WIN
// == x64 other ==============================================================
#define PARAM_REGISTERS rdi, rsi, rdx, rcx, r8, r9
#define CALLEE_SAVE_REGISTERS \
rbx.bit() | r12.bit() | r13.bit() | r14.bit() | r15.bit()
#endif
#endif // V8_TARGET_OS_WIN
#elif V8_TARGET_ARCH_ARM
// ===========================================================================

View File

@ -81,7 +81,7 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
// On windows put the arguments on the stack (PrepareCallCFunction
// has created space for this). On linux pass the arguments in r8 and r9.
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
__ movq(Operand(rsp, 4 * kSystemPointerSize), arg5);
__ LoadAddress(arg5, ExternalReference::isolate_address(isolate));
__ movq(Operand(rsp, 5 * kSystemPointerSize), arg5);

View File

@ -115,15 +115,26 @@ class GeneratedCode {
#ifdef USE_SIMULATOR
// Defined in simulator-base.h.
Return Call(Args... args) {
#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
FATAL("Generated code execution not possible during cross-compilation.");
#endif // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
return Simulator::current(isolate_)->template Call<Return>(
reinterpret_cast<Address>(fn_ptr_), args...);
}
DISABLE_CFI_ICALL Return CallIrregexp(Args... args) { return Call(args...); }
DISABLE_CFI_ICALL Return CallIrregexp(Args... args) {
#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
FATAL("Generated code execution not possible during cross-compilation.");
#endif // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
return Call(args...);
}
#else
DISABLE_CFI_ICALL Return Call(Args... args) {
// When running without a simulator we call the entry directly.
#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
FATAL("Generated code execution not possible during cross-compilation.");
#endif // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
#if V8_OS_AIX
// AIX ABI requires function descriptors (FD). Artificially create a pseudo
// FD to ensure correct dispatch to generated code. The 'volatile'
@ -141,6 +152,9 @@ class GeneratedCode {
DISABLE_CFI_ICALL Return CallIrregexp(Args... args) {
// When running without a simulator we call the entry directly.
#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
FATAL("Generated code execution not possible during cross-compilation.");
#endif // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
return fn_ptr_(args...);
}
#endif // USE_SIMULATOR

View File

@ -13,7 +13,7 @@ namespace internal {
class EntryFrameConstants : public AllStatic {
public:
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
static constexpr int kCalleeSaveXMMRegisters = 10;
static constexpr int kXMMRegisterSize = 16;
static constexpr int kXMMRegistersBlockSize =

View File

@ -296,7 +296,7 @@ void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase(
} else {
DCHECK(mode_ == UC16);
// Save important/volatile registers before calling C function.
#ifndef _WIN64
#ifndef V8_TARGET_OS_WIN
// Caller save on Linux and callee save in Windows.
__ pushq(rsi);
__ pushq(rdi);
@ -311,7 +311,7 @@ void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase(
// Address byte_offset2 - Address of current character position.
// size_t byte_length - length of capture in bytes(!)
// Isolate* isolate or 0 if unicode flag.
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
DCHECK(rcx == arg_reg_1);
DCHECK(rdx == arg_reg_2);
// Compute and set byte_offset1 (start of capture).
@ -333,7 +333,7 @@ void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase(
if (read_backward) {
__ subq(rsi, rbx);
}
#endif // _WIN64
#endif // V8_TARGET_OS_WIN
// Set byte_length.
__ movq(arg_reg_3, rbx);
@ -358,7 +358,7 @@ void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase(
// Restore original values before reacting on result value.
__ Move(code_object_pointer(), masm_.CodeObject());
__ popq(backtrack_stackpointer());
#ifndef _WIN64
#ifndef V8_TARGET_OS_WIN
__ popq(rdi);
__ popq(rsi);
#endif
@ -683,7 +683,7 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
__ movq(rbp, rsp);
// Save parameters and callee-save registers. Order here should correspond
// to order of kBackup_ebx etc.
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots.
// Store register parameters in pre-allocated stack slots,
__ movq(Operand(rbp, kInputString), rcx);
@ -890,7 +890,7 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
}
__ bind(&return_rax);
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// Restore callee save registers.
__ leaq(rsp, Operand(rbp, kLastCalleeSaveRegister));
__ popq(rbx);
@ -943,7 +943,7 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
// Reached if the backtrack-stack limit has been hit.
// Save registers before calling C function
#ifndef _WIN64
#ifndef V8_TARGET_OS_WIN
// Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI.
__ pushq(rsi);
__ pushq(rdi);
@ -952,7 +952,7 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
// Call GrowStack(backtrack_stackpointer())
static const int num_arguments = 3;
__ PrepareCallCFunction(num_arguments);
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// Microsoft passes parameters in rcx, rdx, r8.
// First argument, backtrack stackpointer, is already in rcx.
__ leaq(rdx, Operand(rbp, kStackHighEnd)); // Second argument
@ -974,7 +974,7 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
__ movq(backtrack_stackpointer(), rax);
// Restore saved registers and continue.
__ Move(code_object_pointer(), masm_.CodeObject());
#ifndef _WIN64
#ifndef V8_TARGET_OS_WIN
__ popq(rdi);
__ popq(rsi);
#endif
@ -1159,7 +1159,7 @@ void RegExpMacroAssemblerX64::CallCheckStackGuardState() {
// store anything volatile in a C call or overwritten by this function.
static const int num_arguments = 3;
__ PrepareCallCFunction(num_arguments);
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// Second argument: Code of self. (Do this before overwriting r8).
__ movq(rdx, code_object_pointer());
// Third argument: RegExp code frame pointer.

View File

@ -92,7 +92,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerX64
static const int kReturn_eip = kFramePointer + kSystemPointerSize;
static const int kFrameAlign = kReturn_eip + kSystemPointerSize;
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// Parameters (first four passed as registers, but with room on stack).
// In Microsoft 64-bit Calling Convention, there is room on the callers
// stack (before the return address) to spill parameter registers. We
@ -131,7 +131,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerX64
static const int kIsolate = kDirectCall + kSystemPointerSize;
#endif
#ifdef _WIN64
#ifdef V8_TARGET_OS_WIN
// Microsoft calling convention has three callee-saved registers
// (that we are using). We push these after the frame pointer.
static const int kBackup_rsi = kFramePointer - kSystemPointerSize;