Revert "[snapshot] Emit the embedded blob as assembly instead of inline assembly"
This reverts commit 0b13f0f517
.
Reason for revert: https://ci.chromium.org/p/v8/builders/luci.v8.ci/V8%20Win32%20-%20debug/17373
Original change's description:
> [snapshot] Emit the embedded blob as assembly instead of inline assembly
>
> The motivation behind this is that MSVC doesn't support inline assembly
> on x64. Emitting the embedded blob as a plain assembly file will give us
> MSVC support (and possibly faster compilation times as a side-effect).
>
> Bug: v8:6666,v8:8349
> Change-Id: I2e6cf072faa9ef406fe721a05b63912c655546c2
> Reviewed-on: https://chromium-review.googlesource.com/c/1329205
> Commit-Queue: Jakob Gruber <jgruber@chromium.org>
> Reviewed-by: Michael Stanton <mvstanton@chromium.org>
> Reviewed-by: Yang Guo <yangguo@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#57524}
TBR=yangguo@chromium.org,mvstanton@chromium.org,jgruber@chromium.org
Change-Id: I35f7763f86b4de01e74827a95706b969b43af55e
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:6666, v8:8349
Reviewed-on: https://chromium-review.googlesource.com/c/1337574
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57528}
This commit is contained in:
parent
53d47216d9
commit
ec4b2be12d
25
BUILD.gn
25
BUILD.gn
@ -24,6 +24,8 @@ import("snapshot_toolchain.gni")
|
||||
is_target_simulator = (target_cpu != v8_target_cpu && !v8_multi_arch_build) ||
|
||||
(current_cpu != v8_current_cpu && v8_multi_arch_build)
|
||||
|
||||
is_msvc = is_win && !is_clang
|
||||
|
||||
declare_args() {
|
||||
# Print to stdout on Android.
|
||||
v8_android_log_stdout = false
|
||||
@ -83,8 +85,8 @@ declare_args() {
|
||||
v8_enable_fast_mksnapshot = false
|
||||
|
||||
# Enable embedded builtins.
|
||||
# TODO(v8:8043): Support aix.
|
||||
v8_enable_embedded_builtins = !is_aix
|
||||
# TODO(v8:6666): Support aix and MSVC.
|
||||
v8_enable_embedded_builtins = !is_aix && !is_msvc
|
||||
|
||||
# Enable code-generation-time checking of types in the CodeStubAssembler.
|
||||
v8_enable_verify_csa = false
|
||||
@ -1020,7 +1022,7 @@ action("generate_bytecode_builtins_list") {
|
||||
# Template to generate different V8 snapshots based on different runtime flags.
|
||||
# Can be invoked with run_mksnapshot(<name>). The target will resolve to
|
||||
# run_mksnapshot_<name>. If <name> is "default", no file suffixes will be used.
|
||||
# Otherwise files are suffixed, e.g. embedded_<name>.S and
|
||||
# Otherwise files are suffixed, e.g. embedded_<name>.cc and
|
||||
# snapshot_blob_<name>.bin.
|
||||
#
|
||||
# The template exposes the variables:
|
||||
@ -1059,10 +1061,10 @@ template("run_mksnapshot") {
|
||||
args += invoker.args
|
||||
|
||||
if (v8_enable_embedded_builtins) {
|
||||
outputs += [ "$target_gen_dir/embedded${suffix}.S" ]
|
||||
outputs += [ "$target_gen_dir/embedded${suffix}.cc" ]
|
||||
args += [
|
||||
"--embedded_src",
|
||||
rebase_path("$target_gen_dir/embedded${suffix}.S", root_build_dir),
|
||||
rebase_path("$target_gen_dir/embedded${suffix}.cc", root_build_dir),
|
||||
]
|
||||
if (invoker.embedded_variant != "") {
|
||||
args += [
|
||||
@ -1265,7 +1267,7 @@ if (v8_use_snapshot && !v8_use_external_startup_data) {
|
||||
]
|
||||
|
||||
if (v8_enable_embedded_builtins) {
|
||||
sources += [ "$target_gen_dir/embedded.S" ]
|
||||
sources += [ "$target_gen_dir/embedded.cc" ]
|
||||
} else {
|
||||
sources += [ "src/snapshot/embedded-empty.cc" ]
|
||||
}
|
||||
@ -1312,15 +1314,15 @@ if (v8_use_snapshot && v8_use_external_startup_data) {
|
||||
public = []
|
||||
|
||||
if (v8_enable_embedded_builtins) {
|
||||
sources += [ "$target_gen_dir/embedded.S" ]
|
||||
sources += [ "$target_gen_dir/embedded.cc" ]
|
||||
|
||||
if (v8_use_multi_snapshots) {
|
||||
sources += [ "$target_gen_dir/embedded_trusted.S" ]
|
||||
sources += [ "$target_gen_dir/embedded_trusted.cc" ]
|
||||
|
||||
if (use_jumbo_build == true) {
|
||||
jumbo_excluded_sources = [
|
||||
# Duplicated symbols with embedded.S
|
||||
"$target_gen_dir/embedded_trusted.S",
|
||||
# Duplicated symbols with embedded.cc
|
||||
"$target_gen_dir/embedded_trusted.cc",
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -2479,6 +2481,7 @@ v8_source_set("v8_base") {
|
||||
"src/snapshot/deserializer-allocator.h",
|
||||
"src/snapshot/deserializer.cc",
|
||||
"src/snapshot/deserializer.h",
|
||||
"src/snapshot/macros.h",
|
||||
"src/snapshot/natives-common.cc",
|
||||
"src/snapshot/natives.h",
|
||||
"src/snapshot/object-deserializer.cc",
|
||||
@ -3404,8 +3407,6 @@ if (v8_use_snapshot && current_toolchain == v8_snapshot_toolchain) {
|
||||
visibility = [ ":*" ] # Only targets in this file can depend on this.
|
||||
|
||||
sources = [
|
||||
"src/snapshot/embedded-file-writer.cc",
|
||||
"src/snapshot/embedded-file-writer.h",
|
||||
"src/snapshot/mksnapshot.cc",
|
||||
]
|
||||
|
||||
|
@ -74,9 +74,6 @@
|
||||
#include "unicode/uobject.h"
|
||||
#endif // V8_INTL_SUPPORT
|
||||
|
||||
extern "C" const uint8_t* v8_Default_embedded_blob_;
|
||||
extern "C" uint32_t v8_Default_embedded_blob_size_;
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
@ -92,15 +89,12 @@ namespace internal {
|
||||
#define TRACE_ISOLATE(tag)
|
||||
#endif
|
||||
|
||||
const uint8_t* DefaultEmbeddedBlob() { return v8_Default_embedded_blob_; }
|
||||
uint32_t DefaultEmbeddedBlobSize() { return v8_Default_embedded_blob_size_; }
|
||||
extern const uint8_t* DefaultEmbeddedBlob();
|
||||
extern uint32_t DefaultEmbeddedBlobSize();
|
||||
|
||||
#ifdef V8_MULTI_SNAPSHOTS
|
||||
extern "C" const uint8_t* v8_Trusted_embedded_blob_;
|
||||
extern "C" uint32_t v8_Trusted_embedded_blob_size_;
|
||||
|
||||
const uint8_t* TrustedEmbeddedBlob() { return v8_Trusted_embedded_blob_; }
|
||||
uint32_t TrustedEmbeddedBlobSize() { return v8_Trusted_embedded_blob_size_; }
|
||||
extern const uint8_t* TrustedEmbeddedBlob();
|
||||
extern uint32_t TrustedEmbeddedBlobSize();
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
@ -6,18 +6,16 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/base/macros.h"
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
extern "C" const uint8_t* v8_Default_embedded_blob_;
|
||||
extern "C" uint32_t v8_Default_embedded_blob_size_;
|
||||
|
||||
const uint8_t* v8_Default_embedded_blob_ = nullptr;
|
||||
uint32_t v8_Default_embedded_blob_size_ = 0;
|
||||
const uint8_t* DefaultEmbeddedBlob() { return nullptr; }
|
||||
uint32_t DefaultEmbeddedBlobSize() { return 0; }
|
||||
|
||||
#ifdef V8_MULTI_SNAPSHOTS
|
||||
extern "C" const uint8_t* v8_Trusted_embedded_blob_;
|
||||
extern "C" uint32_t v8_Trusted_embedded_blob_size_;
|
||||
|
||||
const uint8_t* v8_Trusted_embedded_blob_ = nullptr;
|
||||
uint32_t v8_Trusted_embedded_blob_size_ = 0;
|
||||
const uint8_t* TrustedEmbeddedBlob() { return nullptr; }
|
||||
uint32_t TrustedEmbeddedBlobSize() { return 0; }
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -1,402 +0,0 @@
|
||||
// Copyright 2018 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/snapshot/embedded-file-writer.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Platform-independent bits.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
||||
DataDirective PointerSizeDirective() {
|
||||
if (kPointerSize == 8) {
|
||||
return kQuad;
|
||||
} else {
|
||||
CHECK_EQ(4, kPointerSize);
|
||||
return kLong;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
const char* PlatformDependentEmbeddedFileWriter::DirectiveAsString(
|
||||
DataDirective directive) {
|
||||
#ifndef V8_OS_WIN
|
||||
switch (directive) {
|
||||
case kByte:
|
||||
return ".byte";
|
||||
case kLong:
|
||||
return ".long";
|
||||
case kQuad:
|
||||
return ".quad";
|
||||
case kOcta:
|
||||
return ".octa";
|
||||
}
|
||||
UNREACHABLE();
|
||||
#else
|
||||
switch (directive) {
|
||||
case kByte:
|
||||
return "BYTE";
|
||||
case kLong:
|
||||
return "DWORD";
|
||||
case kQuad:
|
||||
return "QWORD";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// V8_OS_MACOSX
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if defined(V8_OS_MACOSX)
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionText() {
|
||||
fprintf(fp_, ".text\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionData() {
|
||||
fprintf(fp_, ".data\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionRoData() {
|
||||
fprintf(fp_, ".const_data\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name,
|
||||
uint32_t value) {
|
||||
DeclareSymbolGlobal(name);
|
||||
DeclareLabel(name);
|
||||
IndentedDataDirective(kLong);
|
||||
fprintf(fp_, "%d", value);
|
||||
Newline();
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol(
|
||||
const char* name, const char* target) {
|
||||
DeclareSymbolGlobal(name);
|
||||
DeclareLabel(name);
|
||||
fprintf(fp_, " %s _%s\n", DirectiveAsString(PointerSizeDirective()), target);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal(
|
||||
const char* name) {
|
||||
// TODO(jgruber): Investigate switching to .globl. Using .private_extern
|
||||
// prevents something along the compilation chain from messing with the
|
||||
// embedded blob. Using .global here causes embedded blob hash verification
|
||||
// failures at runtime.
|
||||
fprintf(fp_, ".private_extern _%s\n", name);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() {
|
||||
fprintf(fp_, ".balign 32\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::Comment(const char* string) {
|
||||
fprintf(fp_, "// %s\n", string);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) {
|
||||
fprintf(fp_, "_%s:\n", name);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
|
||||
const char* name) {
|
||||
DeclareLabel(name);
|
||||
|
||||
// TODO(mvstanton): Investigate the proper incantations to mark the label as
|
||||
// a function on OSX.
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
|
||||
}
|
||||
|
||||
int PlatformDependentEmbeddedFileWriter::HexLiteral(int value) {
|
||||
return fprintf(fp_, "0x%x", value);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::FilePrologue() {}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::FileEpilogue() {}
|
||||
|
||||
int PlatformDependentEmbeddedFileWriter::IndentedDataDirective(
|
||||
DataDirective directive) {
|
||||
return fprintf(fp_, " %s ", DirectiveAsString(directive));
|
||||
}
|
||||
|
||||
// V8_OS_AIX
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#elif defined(V8_OS_AIX)
|
||||
|
||||
// TODO(aix): Update custom logic previously contained in section header macros.
|
||||
// See
|
||||
// https://cs.chromium.org/chromium/src/v8/src/snapshot/macros.h?l=81&rcl=31b2546b348e864539ade15897eac971b3c0e402
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionText() {
|
||||
fprintf(fp_, ".csect .text[PR]\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionData() {
|
||||
// TODO(aix): Confirm and update if needed.
|
||||
fprintf(fp_, ".csect .data[RW]\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionRoData() {
|
||||
fprintf(fp_, ".csect[RO]\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name,
|
||||
uint32_t value) {
|
||||
DeclareSymbolGlobal(name);
|
||||
DeclareLabel(name);
|
||||
IndentedDataDirective(kLong);
|
||||
fprintf(fp_, "%d", value);
|
||||
Newline();
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol(
|
||||
const char* name, const char* target) {
|
||||
DeclareSymbolGlobal(name);
|
||||
DeclareLabel(name);
|
||||
fprintf(fp_, " %s %s\n", DirectiveAsString(PointerSizeDirective()), target);
|
||||
Newline();
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal(
|
||||
const char* name) {
|
||||
fprintf(fp_, ".globl %s\n", name);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() {
|
||||
fprintf(fp_, ".balign 32\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::Comment(const char* string) {
|
||||
fprintf(fp_, "// %s\n", string);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) {
|
||||
fprintf(fp_, "%s:\n", name);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
|
||||
const char* name) {
|
||||
DeclareLabel(name);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
|
||||
}
|
||||
|
||||
int PlatformDependentEmbeddedFileWriter::HexLiteral(int value) {
|
||||
return fprintf(fp_, "0x%x", value);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::FilePrologue() {}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::FileEpilogue() {}
|
||||
|
||||
int PlatformDependentEmbeddedFileWriter::IndentedDataDirective(
|
||||
DataDirective directive) {
|
||||
return fprintf(fp_, " %s ", DirectiveAsString(directive));
|
||||
}
|
||||
|
||||
// V8_OS_WIN
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#elif defined(V8_OS_WIN)
|
||||
|
||||
// See https://docs.microsoft.com/en-us/cpp/assembler/masm/directives-reference.
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionText() {
|
||||
fprintf(fp_, ".CODE\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionData() {
|
||||
fprintf(fp_, ".DATA\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionRoData() {
|
||||
fprintf(fp_, ".CONST\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name,
|
||||
uint32_t value) {
|
||||
DeclareSymbolGlobal(name);
|
||||
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64)
|
||||
fprintf(fp_, "%s %s %d\n", name, DirectiveAsString(kLong), value);
|
||||
#else
|
||||
fprintf(fp_, "_%s %s %d\n", name, DirectiveAsString(kLong), value);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol(
|
||||
const char* name, const char* target) {
|
||||
DeclareSymbolGlobal(name);
|
||||
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64)
|
||||
fprintf(fp_, "%s %s %s\n", name, DirectiveAsString(PointerSizeDirective()),
|
||||
target);
|
||||
#else
|
||||
fprintf(fp_, "_%s %s _%s\n", name, DirectiveAsString(PointerSizeDirective()),
|
||||
target);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal(
|
||||
const char* name) {
|
||||
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64)
|
||||
fprintf(fp_, "PUBLIC %s\n", name);
|
||||
#else
|
||||
fprintf(fp_, "PUBLIC _%s\n", name);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() {
|
||||
// Diverges from other platforms due to compile error
|
||||
// 'invalid combination with segment alignment'.
|
||||
fprintf(fp_, "ALIGN 4\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::Comment(const char* string) {
|
||||
fprintf(fp_, "; %s\n", string);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) {
|
||||
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64)
|
||||
fprintf(fp_, "%s LABEL %s\n", name, DirectiveAsString(kByte));
|
||||
#else
|
||||
fprintf(fp_, "_%s LABEL %s\n", name, DirectiveAsString(kByte));
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
|
||||
const char* name) {
|
||||
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64)
|
||||
fprintf(fp_, "%s PROC\n", name);
|
||||
#else
|
||||
fprintf(fp_, "_%s PROC\n", name);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
|
||||
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64)
|
||||
fprintf(fp_, "%s ENDP\n", name);
|
||||
#else
|
||||
fprintf(fp_, "_%s ENDP\n", name);
|
||||
#endif
|
||||
}
|
||||
|
||||
int PlatformDependentEmbeddedFileWriter::HexLiteral(int value) {
|
||||
return fprintf(fp_, "0%xh", value);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::FilePrologue() {
|
||||
#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM64)
|
||||
fprintf(fp_, ".MODEL FLAT\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::FileEpilogue() {
|
||||
fprintf(fp_, "END\n");
|
||||
}
|
||||
|
||||
int PlatformDependentEmbeddedFileWriter::IndentedDataDirective(
|
||||
DataDirective directive) {
|
||||
return fprintf(fp_, " %s ", DirectiveAsString(directive));
|
||||
}
|
||||
|
||||
// Everything but AIX, Windows, or OSX.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#else
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionText() {
|
||||
#ifdef OS_CHROMEOS
|
||||
fprintf(fp_, ".section .text.hot.embedded\n");
|
||||
#else
|
||||
fprintf(fp_, ".section .text\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionData() {
|
||||
fprintf(fp_, ".section .data\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::SectionRoData() {
|
||||
fprintf(fp_, ".section .rodata\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name,
|
||||
uint32_t value) {
|
||||
DeclareSymbolGlobal(name);
|
||||
DeclareLabel(name);
|
||||
IndentedDataDirective(kLong);
|
||||
fprintf(fp_, "%d", value);
|
||||
Newline();
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol(
|
||||
const char* name, const char* target) {
|
||||
DeclareSymbolGlobal(name);
|
||||
DeclareLabel(name);
|
||||
fprintf(fp_, " %s %s\n", DirectiveAsString(PointerSizeDirective()), target);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal(
|
||||
const char* name) {
|
||||
fprintf(fp_, ".global %s\n", name);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() {
|
||||
fprintf(fp_, ".balign 32\n");
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::Comment(const char* string) {
|
||||
fprintf(fp_, "// %s\n", string);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) {
|
||||
fprintf(fp_, "%s:\n", name);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin(
|
||||
const char* name) {
|
||||
DeclareLabel(name);
|
||||
|
||||
#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_ARM64)
|
||||
// ELF format binaries on ARM use ".type <function name>, %function"
|
||||
// to create a DWARF subprogram entry.
|
||||
fprintf(fp_, ".type %s, %%function\n", name);
|
||||
#else
|
||||
// Other ELF Format binaries use ".type <function name>, @function"
|
||||
// to create a DWARF subprogram entry.
|
||||
fprintf(fp_, ".type %s, @function\n", name);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) {
|
||||
}
|
||||
|
||||
int PlatformDependentEmbeddedFileWriter::HexLiteral(int value) {
|
||||
return fprintf(fp_, "0x%x", value);
|
||||
}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::FilePrologue() {}
|
||||
|
||||
void PlatformDependentEmbeddedFileWriter::FileEpilogue() {}
|
||||
|
||||
int PlatformDependentEmbeddedFileWriter::IndentedDataDirective(
|
||||
DataDirective directive) {
|
||||
return fprintf(fp_, " %s ", DirectiveAsString(directive));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -1,290 +0,0 @@
|
||||
// Copyright 2018 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_SNAPSHOT_EMBEDDED_FILE_WRITER_H_
|
||||
#define V8_SNAPSHOT_EMBEDDED_FILE_WRITER_H_
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "src/globals.h"
|
||||
#include "src/snapshot/snapshot.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
enum DataDirective {
|
||||
kByte,
|
||||
kLong,
|
||||
kQuad,
|
||||
kOcta,
|
||||
};
|
||||
|
||||
static constexpr char kDefaultEmbeddedVariant[] = "Default";
|
||||
|
||||
// The platform-dependent logic for emitting assembly code for the generated
|
||||
// embedded.S file.
|
||||
class PlatformDependentEmbeddedFileWriter final {
|
||||
public:
|
||||
void SetFile(FILE* fp) { fp_ = fp; }
|
||||
|
||||
void SectionText();
|
||||
void SectionData();
|
||||
void SectionRoData();
|
||||
|
||||
void AlignToCodeAlignment();
|
||||
|
||||
void DeclareUint32(const char* name, uint32_t value);
|
||||
void DeclarePointerToSymbol(const char* name, const char* target);
|
||||
|
||||
void DeclareLabel(const char* name);
|
||||
|
||||
void DeclareFunctionBegin(const char* name);
|
||||
void DeclareFunctionEnd(const char* name);
|
||||
|
||||
// Returns the number of printed characters.
|
||||
int HexLiteral(int value);
|
||||
|
||||
void Comment(const char* string);
|
||||
void Newline() { fprintf(fp_, "\n"); }
|
||||
|
||||
void FilePrologue();
|
||||
void FileEpilogue();
|
||||
|
||||
int IndentedDataDirective(DataDirective directive);
|
||||
|
||||
FILE* fp() const { return fp_; }
|
||||
|
||||
private:
|
||||
void DeclareSymbolGlobal(const char* name);
|
||||
|
||||
static const char* DirectiveAsString(DataDirective directive);
|
||||
|
||||
private:
|
||||
FILE* fp_ = nullptr;
|
||||
};
|
||||
|
||||
// Generates the embedded.S file which is later compiled into the final v8
|
||||
// binary. Its contents are exported through two symbols:
|
||||
//
|
||||
// v8_<variant>_embedded_blob_ (intptr_t):
|
||||
// a pointer to the start of the embedded blob.
|
||||
// v8_<variant>_embedded_blob_size_ (uint32_t):
|
||||
// size of the embedded blob in bytes.
|
||||
//
|
||||
// The variant is usually "Default" but can be modified in multisnapshot builds.
|
||||
class EmbeddedFileWriter {
|
||||
public:
|
||||
void SetEmbeddedFile(const char* embedded_cpp_file) {
|
||||
embedded_cpp_path_ = embedded_cpp_file;
|
||||
}
|
||||
|
||||
void SetEmbeddedVariant(const char* embedded_variant) {
|
||||
embedded_variant_ = embedded_variant;
|
||||
}
|
||||
|
||||
void WriteEmbedded(const i::EmbeddedData* blob) const {
|
||||
MaybeWriteEmbeddedFile(blob);
|
||||
}
|
||||
|
||||
private:
|
||||
void MaybeWriteEmbeddedFile(const i::EmbeddedData* blob) const {
|
||||
if (embedded_cpp_path_ == nullptr) return;
|
||||
|
||||
FILE* fp = GetFileDescriptorOrDie(embedded_cpp_path_);
|
||||
|
||||
PlatformDependentEmbeddedFileWriter writer;
|
||||
writer.SetFile(fp);
|
||||
|
||||
WriteFilePrologue(&writer);
|
||||
WriteMetadataSection(&writer, blob);
|
||||
WriteInstructionStreams(&writer, blob);
|
||||
WriteFileEpilogue(&writer, blob);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static FILE* GetFileDescriptorOrDie(const char* filename) {
|
||||
FILE* fp = v8::base::OS::FOpen(filename, "wb");
|
||||
if (fp == nullptr) {
|
||||
i::PrintF("Unable to open file \"%s\" for writing.\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
static void WriteFilePrologue(PlatformDependentEmbeddedFileWriter* w) {
|
||||
w->Comment("Autogenerated file. Do not edit.");
|
||||
w->Newline();
|
||||
w->FilePrologue();
|
||||
}
|
||||
|
||||
// Fairly arbitrary but should fit all symbol names.
|
||||
static constexpr int kTemporaryStringLength = 256;
|
||||
|
||||
void WriteMetadataSection(PlatformDependentEmbeddedFileWriter* w,
|
||||
const i::EmbeddedData* blob) const {
|
||||
char embedded_blob_data_symbol[kTemporaryStringLength];
|
||||
i::SNPrintF(i::Vector<char>(embedded_blob_data_symbol),
|
||||
"v8_%s_embedded_blob_data_", embedded_variant_);
|
||||
|
||||
w->Comment("The embedded blob starts here. Metadata comes first, followed");
|
||||
w->Comment("by builtin instruction streams.");
|
||||
w->SectionText();
|
||||
w->AlignToCodeAlignment();
|
||||
w->DeclareLabel(embedded_blob_data_symbol);
|
||||
|
||||
WriteBinaryContentsAsInlineAssembly(w, blob->data(),
|
||||
i::EmbeddedData::RawDataOffset());
|
||||
}
|
||||
|
||||
void WriteInstructionStreams(PlatformDependentEmbeddedFileWriter* w,
|
||||
const i::EmbeddedData* blob) const {
|
||||
const bool is_default_variant =
|
||||
std::strcmp(embedded_variant_, kDefaultEmbeddedVariant) == 0;
|
||||
|
||||
for (int i = 0; i < i::Builtins::builtin_count; i++) {
|
||||
if (!blob->ContainsBuiltin(i)) continue;
|
||||
|
||||
char builtin_symbol[kTemporaryStringLength];
|
||||
if (is_default_variant) {
|
||||
// Create nicer symbol names for the default mode.
|
||||
i::SNPrintF(i::Vector<char>(builtin_symbol), "Builtins_%s",
|
||||
i::Builtins::name(i));
|
||||
} else {
|
||||
i::SNPrintF(i::Vector<char>(builtin_symbol), "%s_Builtins_%s",
|
||||
embedded_variant_, i::Builtins::name(i));
|
||||
}
|
||||
|
||||
// Labels created here will show up in backtraces. We check in
|
||||
// Isolate::SetEmbeddedBlob that the blob layout remains unchanged, i.e.
|
||||
// that labels do not insert bytes into the middle of the blob byte
|
||||
// stream.
|
||||
w->DeclareFunctionBegin(builtin_symbol);
|
||||
WriteBinaryContentsAsInlineAssembly(
|
||||
w,
|
||||
reinterpret_cast<const uint8_t*>(blob->InstructionStartOfBuiltin(i)),
|
||||
blob->PaddedInstructionSizeOfBuiltin(i));
|
||||
w->DeclareFunctionEnd(builtin_symbol);
|
||||
}
|
||||
w->Newline();
|
||||
}
|
||||
|
||||
void WriteFileEpilogue(PlatformDependentEmbeddedFileWriter* w,
|
||||
const i::EmbeddedData* blob) const {
|
||||
{
|
||||
char embedded_blob_data_symbol[kTemporaryStringLength];
|
||||
i::SNPrintF(i::Vector<char>(embedded_blob_data_symbol),
|
||||
"v8_%s_embedded_blob_data_", embedded_variant_);
|
||||
|
||||
char embedded_blob_symbol[kTemporaryStringLength];
|
||||
i::SNPrintF(i::Vector<char>(embedded_blob_symbol), "v8_%s_embedded_blob_",
|
||||
embedded_variant_);
|
||||
|
||||
w->Comment("Pointer to the beginning of the embedded blob.");
|
||||
w->SectionData();
|
||||
w->DeclarePointerToSymbol(embedded_blob_symbol,
|
||||
embedded_blob_data_symbol);
|
||||
w->Newline();
|
||||
}
|
||||
|
||||
{
|
||||
char embedded_blob_size_symbol[kTemporaryStringLength];
|
||||
i::SNPrintF(i::Vector<char>(embedded_blob_size_symbol),
|
||||
"v8_%s_embedded_blob_size_", embedded_variant_);
|
||||
|
||||
w->Comment("The size of the embedded blob in bytes.");
|
||||
w->SectionRoData();
|
||||
w->DeclareUint32(embedded_blob_size_symbol, blob->size());
|
||||
w->Newline();
|
||||
}
|
||||
|
||||
w->FileEpilogue();
|
||||
}
|
||||
|
||||
static int WriteOcta(FILE* fp, int current_line_length, const uint8_t* data) {
|
||||
const uint64_t* quad_ptr1 = reinterpret_cast<const uint64_t*>(data);
|
||||
const uint64_t* quad_ptr2 = reinterpret_cast<const uint64_t*>(data + 8);
|
||||
|
||||
#ifdef V8_TARGET_BIG_ENDIAN
|
||||
uint64_t part1 = *quad_ptr1;
|
||||
uint64_t part2 = *quad_ptr2;
|
||||
#else
|
||||
uint64_t part1 = *quad_ptr2;
|
||||
uint64_t part2 = *quad_ptr1;
|
||||
#endif // V8_TARGET_BIG_ENDIAN
|
||||
|
||||
if (part1 != 0) {
|
||||
current_line_length +=
|
||||
fprintf(fp, "0x%" PRIx64 "%016" PRIx64, part1, part2);
|
||||
} else {
|
||||
current_line_length += fprintf(fp, "0x%" PRIx64, part2);
|
||||
}
|
||||
return current_line_length;
|
||||
}
|
||||
|
||||
static int WriteDirectiveOrSeparator(PlatformDependentEmbeddedFileWriter* w,
|
||||
int current_line_length,
|
||||
DataDirective directive) {
|
||||
int printed_chars;
|
||||
if (current_line_length == 0) {
|
||||
printed_chars = w->IndentedDataDirective(directive);
|
||||
DCHECK_LT(0, printed_chars);
|
||||
} else {
|
||||
printed_chars = fprintf(w->fp(), ",");
|
||||
DCHECK_EQ(1, printed_chars);
|
||||
}
|
||||
return current_line_length + printed_chars;
|
||||
}
|
||||
|
||||
static int WriteLineEndIfNeeded(FILE* fp, int current_line_length,
|
||||
int write_size) {
|
||||
static const int kTextWidth = 80;
|
||||
// Check if adding ',0xFF...FF\n"' would force a line wrap. This doesn't use
|
||||
// the actual size of the string to be written to determine this so it's
|
||||
// more conservative than strictly needed.
|
||||
if (current_line_length + strlen(",0x") + write_size * 2 > kTextWidth) {
|
||||
fprintf(fp, "\n");
|
||||
return 0;
|
||||
} else {
|
||||
return current_line_length;
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteBinaryContentsAsInlineAssembly(
|
||||
PlatformDependentEmbeddedFileWriter* w, const uint8_t* data,
|
||||
uint32_t size) {
|
||||
int current_line_length = 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
#ifndef V8_OS_WIN
|
||||
const uint32_t size_of_octa = 16;
|
||||
for (; i <= size - size_of_octa; i += size_of_octa) {
|
||||
current_line_length =
|
||||
WriteDirectiveOrSeparator(w, current_line_length, kOcta);
|
||||
current_line_length = WriteOcta(w->fp(), current_line_length, data + i);
|
||||
current_line_length =
|
||||
WriteLineEndIfNeeded(w->fp(), current_line_length, size_of_octa);
|
||||
}
|
||||
if (current_line_length != 0) w->Newline();
|
||||
current_line_length = 0;
|
||||
#endif
|
||||
for (; i < size; i++) {
|
||||
current_line_length =
|
||||
WriteDirectiveOrSeparator(w, current_line_length, kByte);
|
||||
current_line_length += w->HexLiteral(data[i]);
|
||||
current_line_length =
|
||||
WriteLineEndIfNeeded(w->fp(), current_line_length, 1);
|
||||
}
|
||||
if (current_line_length != 0) w->Newline();
|
||||
}
|
||||
|
||||
const char* embedded_cpp_path_ = nullptr;
|
||||
const char* embedded_variant_ = kDefaultEmbeddedVariant;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_SNAPSHOT_EMBEDDED_FILE_WRITER_H_
|
110
src/snapshot/macros.h
Normal file
110
src/snapshot/macros.h
Normal file
@ -0,0 +1,110 @@
|
||||
// Copyright 2018 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_SNAPSHOT_MACROS_H_
|
||||
#define V8_SNAPSHOT_MACROS_H_
|
||||
|
||||
#include "include/v8config.h"
|
||||
|
||||
// .byte portability macros.
|
||||
|
||||
#if defined(V8_OS_MACOSX) // MACOSX
|
||||
#define V8_ASM_MANGLE_LABEL "_"
|
||||
#define V8_ASM_RODATA_SECTION ".const_data\n"
|
||||
#define V8_ASM_TEXT_SECTION ".text\n"
|
||||
#define V8_ASM_DECLARE(NAME) ".private_extern " V8_ASM_MANGLE_LABEL NAME "\n"
|
||||
#elif defined(V8_OS_AIX) // AIX
|
||||
#define V8_ASM_RODATA_SECTION ".csect[RO]\n"
|
||||
#define V8_ASM_TEXT_SECTION ".csect .text[PR]\n"
|
||||
#define V8_ASM_MANGLE_LABEL ""
|
||||
#define V8_ASM_DECLARE(NAME) ".globl " V8_ASM_MANGLE_LABEL NAME "\n"
|
||||
#elif defined(V8_OS_WIN) // WIN
|
||||
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64)
|
||||
#define V8_ASM_MANGLE_LABEL ""
|
||||
#else
|
||||
#define V8_ASM_MANGLE_LABEL "_"
|
||||
#endif
|
||||
#define V8_ASM_RODATA_SECTION ".section .rodata\n"
|
||||
#define V8_ASM_TEXT_SECTION ".section .text\n"
|
||||
#define V8_ASM_DECLARE(NAME)
|
||||
#else // !MACOSX && !WIN && !AIX
|
||||
#define V8_ASM_MANGLE_LABEL ""
|
||||
#define V8_ASM_RODATA_SECTION ".section .rodata\n"
|
||||
#if defined(OS_CHROMEOS) // ChromeOS
|
||||
#define V8_ASM_TEXT_SECTION ".section .text.hot.embedded\n"
|
||||
#else
|
||||
#define V8_ASM_TEXT_SECTION ".section .text\n"
|
||||
#endif
|
||||
#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)
|
||||
#define V8_ASM_DECLARE(NAME) ".global " V8_ASM_MANGLE_LABEL NAME "\n"
|
||||
#else
|
||||
#define V8_ASM_DECLARE(NAME) ".local " V8_ASM_MANGLE_LABEL NAME "\n"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Align to kCodeAlignment.
|
||||
#define V8_ASM_BALIGN32 ".balign 32\n"
|
||||
#define V8_ASM_LABEL(NAME) V8_ASM_MANGLE_LABEL NAME ":\n"
|
||||
|
||||
#if defined(V8_OS_WIN)
|
||||
// The directives for inserting debugging information on Windows come
|
||||
// from the PE (Portable Executable) and COFF (Common Object File Format)
|
||||
// standards. Documented here:
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format
|
||||
|
||||
#define V8_ASM_TYPE(NAME) \
|
||||
/* .scl 2 means StorageClass external. */ \
|
||||
/* .type 32 means Type Representation Function. */ \
|
||||
".def " V8_ASM_MANGLE_LABEL NAME "; .scl 2; .type 32; .endef;\n"
|
||||
|
||||
#elif defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_ARM64)
|
||||
|
||||
// ELF format binaries on ARM use ".type <function name>, %function"
|
||||
// to create a DWARF subprogram entry.
|
||||
#define V8_ASM_TYPE(NAME) ".type " V8_ASM_MANGLE_LABEL NAME ", %function\n"
|
||||
|
||||
#else
|
||||
|
||||
// Other ELF Format binaries use ".type <function name>, @function"
|
||||
// to create a DWARF subprogram entry.
|
||||
#define V8_ASM_TYPE(NAME) ".type " V8_ASM_MANGLE_LABEL NAME ", @function\n"
|
||||
#endif // !V8_OS_WIN
|
||||
|
||||
#define V8_ASM_DECLARE_FUNCTION(NAME) \
|
||||
V8_ASM_LABEL(NAME) \
|
||||
V8_ASM_TYPE(NAME)
|
||||
|
||||
// clang-format off
|
||||
#if defined(V8_OS_AIX)
|
||||
|
||||
#define V8_EMBEDDED_TEXT_HEADER(LABEL) \
|
||||
__asm__(V8_ASM_DECLARE(#LABEL) \
|
||||
".csect " #LABEL "[DS]\n" \
|
||||
#LABEL ":\n" \
|
||||
".llong ." #LABEL ", TOC[tc0], 0\n" \
|
||||
V8_ASM_TEXT_SECTION \
|
||||
"." #LABEL ":\n");
|
||||
|
||||
#define V8_EMBEDDED_RODATA_HEADER(LABEL) \
|
||||
__asm__(V8_ASM_RODATA_SECTION \
|
||||
V8_ASM_DECLARE(#LABEL) \
|
||||
".align 5\n" \
|
||||
V8_ASM_LABEL(#LABEL));
|
||||
|
||||
#else
|
||||
|
||||
#define V8_EMBEDDED_TEXT_HEADER(LABEL) \
|
||||
__asm__(V8_ASM_TEXT_SECTION \
|
||||
V8_ASM_DECLARE(#LABEL) \
|
||||
V8_ASM_BALIGN32 \
|
||||
V8_ASM_LABEL(#LABEL));
|
||||
|
||||
#define V8_EMBEDDED_RODATA_HEADER(LABEL) \
|
||||
__asm__(V8_ASM_RODATA_SECTION \
|
||||
V8_ASM_DECLARE(#LABEL) \
|
||||
V8_ASM_BALIGN32 \
|
||||
V8_ASM_LABEL(#LABEL));
|
||||
|
||||
#endif // #if defined(V8_OS_AIX)
|
||||
#endif // V8_SNAPSHOT_MACROS_H_
|
@ -11,16 +11,25 @@
|
||||
#include "src/base/platform/platform.h"
|
||||
#include "src/flags.h"
|
||||
#include "src/msan.h"
|
||||
#include "src/snapshot/embedded-file-writer.h"
|
||||
#include "src/snapshot/natives.h"
|
||||
#include "src/snapshot/partial-serializer.h"
|
||||
#include "src/snapshot/snapshot.h"
|
||||
#include "src/snapshot/startup-serializer.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class SnapshotFileWriter {
|
||||
class SnapshotWriter {
|
||||
public:
|
||||
SnapshotWriter()
|
||||
: snapshot_cpp_path_(nullptr), snapshot_blob_path_(nullptr) {}
|
||||
|
||||
void SetEmbeddedFile(const char* embedded_cpp_file) {
|
||||
embedded_cpp_path_ = embedded_cpp_file;
|
||||
}
|
||||
|
||||
void SetEmbeddedVariant(const char* embedded_variant) {
|
||||
embedded_variant_ = embedded_variant;
|
||||
}
|
||||
|
||||
void SetSnapshotFile(const char* snapshot_cpp_file) {
|
||||
snapshot_cpp_path_ = snapshot_cpp_file;
|
||||
}
|
||||
@ -40,6 +49,10 @@ class SnapshotFileWriter {
|
||||
MaybeWriteStartupBlob(blob_vector);
|
||||
}
|
||||
|
||||
void WriteEmbedded(const i::EmbeddedData* blob) const {
|
||||
MaybeWriteEmbeddedFile(blob);
|
||||
}
|
||||
|
||||
private:
|
||||
void MaybeWriteStartupBlob(const i::Vector<const i::byte>& blob) const {
|
||||
if (!snapshot_blob_path_) return;
|
||||
@ -103,6 +116,170 @@ class SnapshotFileWriter {
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
void MaybeWriteEmbeddedFile(const i::EmbeddedData* blob) const {
|
||||
if (embedded_cpp_path_ == nullptr) return;
|
||||
|
||||
FILE* fp = GetFileDescriptorOrDie(embedded_cpp_path_);
|
||||
|
||||
WriteEmbeddedFilePrefix(fp);
|
||||
WriteEmbeddedFileData(fp, blob, embedded_variant_);
|
||||
WriteEmbeddedFileSuffix(fp, embedded_variant_);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void WriteEmbeddedFilePrefix(FILE* fp) {
|
||||
fprintf(fp, "// Autogenerated file. Do not edit.\n\n");
|
||||
fprintf(fp, "#include <cstdint>\n\n");
|
||||
fprintf(fp, "#include \"src/snapshot/macros.h\"\n\n");
|
||||
fprintf(fp, "namespace v8 {\n");
|
||||
fprintf(fp, "namespace internal {\n\n");
|
||||
fprintf(fp, "namespace {\n\n");
|
||||
}
|
||||
|
||||
static void WriteEmbeddedFileSuffix(FILE* fp, const char* embedded_variant) {
|
||||
fprintf(fp, "} // namespace\n\n");
|
||||
fprintf(fp,
|
||||
"const uint8_t* %sEmbeddedBlob() { return "
|
||||
"v8_%s_embedded_blob_; }\n",
|
||||
embedded_variant, embedded_variant);
|
||||
fprintf(fp,
|
||||
"uint32_t %sEmbeddedBlobSize() { return "
|
||||
"v8_embedded_blob_size_; }\n\n",
|
||||
embedded_variant);
|
||||
fprintf(fp, "} // namespace internal\n");
|
||||
fprintf(fp, "} // namespace v8\n");
|
||||
}
|
||||
|
||||
static void WriteEmbeddedFileData(FILE* fp, const i::EmbeddedData* blob,
|
||||
const char* embedded_variant) {
|
||||
fprintf(fp, "V8_EMBEDDED_TEXT_HEADER(v8_%s_embedded_blob_)\n",
|
||||
embedded_variant);
|
||||
#ifdef V8_OS_MACOSX
|
||||
// Note: On some platforms (observed on mac64), inserting labels into the
|
||||
// .byte stream causes the compiler to reorder symbols, invalidating stored
|
||||
// offsets.
|
||||
// We either need to avoid doing so, or stop relying on our own offset table
|
||||
// and directly reference symbols instead. But there is another complication
|
||||
// there since the chrome build process on mac verifies the order of symbols
|
||||
// present in the binary.
|
||||
// For now, the straight-forward solution seems to be to just emit a pure
|
||||
// .byte stream on OSX.
|
||||
WriteBinaryContentsAsInlineAssembly(fp, blob->data(), blob->size());
|
||||
#else
|
||||
WriteBinaryContentsAsInlineAssembly(fp, blob->data(),
|
||||
i::EmbeddedData::RawDataOffset());
|
||||
WriteBuiltins(fp, blob, embedded_variant);
|
||||
#endif
|
||||
fprintf(fp, "extern \"C\" const uint8_t v8_%s_embedded_blob_[];\n",
|
||||
embedded_variant);
|
||||
fprintf(fp, "static const uint32_t v8_embedded_blob_size_ = %d;\n\n",
|
||||
blob->size());
|
||||
}
|
||||
|
||||
static void WriteBuiltins(FILE* fp, const i::EmbeddedData* blob,
|
||||
const char* embedded_variant) {
|
||||
const bool is_default_variant =
|
||||
std::strcmp(embedded_variant, "Default") == 0;
|
||||
for (int i = 0; i < i::Builtins::builtin_count; i++) {
|
||||
if (!blob->ContainsBuiltin(i)) continue;
|
||||
|
||||
// Labels created here will show up in backtraces. We check in
|
||||
// Isolate::SetEmbeddedBlob that the blob layout remains unchanged, i.e.
|
||||
// that labels do not insert bytes into the middle of the blob byte
|
||||
// stream.
|
||||
if (is_default_variant) {
|
||||
// Create nicer symbol names for the default mode.
|
||||
fprintf(fp, "__asm__(V8_ASM_DECLARE_FUNCTION(\"Builtins_%s\"));\n",
|
||||
i::Builtins::name(i));
|
||||
} else {
|
||||
fprintf(fp, "__asm__(V8_ASM_DECLARE_FUNCTION(\"%s_Builtins_%s\"));\n",
|
||||
embedded_variant, i::Builtins::name(i));
|
||||
}
|
||||
|
||||
WriteBinaryContentsAsInlineAssembly(
|
||||
fp,
|
||||
reinterpret_cast<const uint8_t*>(blob->InstructionStartOfBuiltin(i)),
|
||||
blob->PaddedInstructionSizeOfBuiltin(i));
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
static int WriteOcta(FILE* fp, int current_line_length, const uint8_t* data) {
|
||||
const uint64_t* quad_ptr1 = reinterpret_cast<const uint64_t*>(data);
|
||||
const uint64_t* quad_ptr2 = reinterpret_cast<const uint64_t*>(data + 8);
|
||||
|
||||
#ifdef V8_TARGET_BIG_ENDIAN
|
||||
uint64_t part1 = *quad_ptr1;
|
||||
uint64_t part2 = *quad_ptr2;
|
||||
#else
|
||||
uint64_t part1 = *quad_ptr2;
|
||||
uint64_t part2 = *quad_ptr1;
|
||||
#endif // V8_TARGET_BIG_ENDIAN
|
||||
|
||||
if (part1 != 0) {
|
||||
current_line_length +=
|
||||
fprintf(fp, "0x%" PRIx64 "%016" PRIx64, part1, part2);
|
||||
} else {
|
||||
current_line_length += fprintf(fp, "0x%" PRIx64, part2);
|
||||
}
|
||||
return current_line_length;
|
||||
}
|
||||
|
||||
static int WriteDirectiveOrSeparator(FILE* fp, int current_line_length,
|
||||
const char* directive) {
|
||||
int printed_chars;
|
||||
if (current_line_length == 0) {
|
||||
printed_chars = fprintf(fp, " \"%s ", directive);
|
||||
DCHECK_LT(0, printed_chars);
|
||||
} else {
|
||||
printed_chars = fprintf(fp, ",");
|
||||
DCHECK_EQ(1, printed_chars);
|
||||
}
|
||||
return current_line_length + printed_chars;
|
||||
}
|
||||
|
||||
static int WriteLineEndIfNeeded(FILE* fp, int current_line_length,
|
||||
int write_size) {
|
||||
static const int kTextWidth = 80;
|
||||
// Check if adding ',0xFF...FF\n"' would force a line wrap. This doesn't use
|
||||
// the actual size of the string to be written to determine this so it's
|
||||
// more conservative than strictly needed.
|
||||
if (current_line_length + strlen(",0x\\n\"") + write_size * 2 >
|
||||
kTextWidth) {
|
||||
fprintf(fp, "\\n\"\n");
|
||||
return 0;
|
||||
} else {
|
||||
return current_line_length;
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteBinaryContentsAsInlineAssembly(FILE* fp, const uint8_t* data,
|
||||
uint32_t size) {
|
||||
int current_line_length = 0;
|
||||
|
||||
fprintf(fp, "__asm__(\n");
|
||||
uint32_t i = 0;
|
||||
const uint32_t size_of_octa = 16;
|
||||
for (; i <= size - size_of_octa; i += size_of_octa) {
|
||||
current_line_length =
|
||||
WriteDirectiveOrSeparator(fp, current_line_length, ".octa");
|
||||
current_line_length = WriteOcta(fp, current_line_length, data + i);
|
||||
current_line_length =
|
||||
WriteLineEndIfNeeded(fp, current_line_length, size_of_octa);
|
||||
}
|
||||
if (current_line_length != 0) fprintf(fp, "\\n\"\n");
|
||||
current_line_length = 0;
|
||||
for (; i < size; i++) {
|
||||
current_line_length =
|
||||
WriteDirectiveOrSeparator(fp, current_line_length, ".byte");
|
||||
current_line_length += fprintf(fp, "0x%x", data[i]);
|
||||
current_line_length = WriteLineEndIfNeeded(fp, current_line_length, 1);
|
||||
}
|
||||
if (current_line_length != 0) fprintf(fp, "\\n\"\n");
|
||||
fprintf(fp, ");\n");
|
||||
}
|
||||
|
||||
static FILE* GetFileDescriptorOrDie(const char* filename) {
|
||||
FILE* fp = v8::base::OS::FOpen(filename, "wb");
|
||||
if (fp == nullptr) {
|
||||
@ -112,8 +289,10 @@ class SnapshotFileWriter {
|
||||
return fp;
|
||||
}
|
||||
|
||||
const char* snapshot_cpp_path_ = nullptr;
|
||||
const char* snapshot_blob_path_ = nullptr;
|
||||
const char* embedded_cpp_path_ = nullptr;
|
||||
const char* embedded_variant_ = "Default";
|
||||
const char* snapshot_cpp_path_;
|
||||
const char* snapshot_blob_path_;
|
||||
};
|
||||
|
||||
char* GetExtraCode(char* filename, const char* description) {
|
||||
@ -239,7 +418,7 @@ v8::StartupData WarmUpSnapshotDataBlob(v8::SnapshotCreator* snapshot_creator,
|
||||
return result;
|
||||
}
|
||||
|
||||
void WriteEmbeddedFile(i::EmbeddedFileWriter* writer) {
|
||||
void WriteEmbeddedFile(SnapshotWriter* writer) {
|
||||
i::EmbeddedData embedded_blob = i::EmbeddedData::FromBlob();
|
||||
writer->WriteEmbedded(&embedded_blob);
|
||||
}
|
||||
@ -268,13 +447,14 @@ int main(int argc, char** argv) {
|
||||
v8::V8::Initialize();
|
||||
|
||||
{
|
||||
SnapshotFileWriter snapshot_writer;
|
||||
snapshot_writer.SetSnapshotFile(i::FLAG_startup_src);
|
||||
snapshot_writer.SetStartupBlobFile(i::FLAG_startup_blob);
|
||||
|
||||
i::EmbeddedFileWriter embedded_writer;
|
||||
embedded_writer.SetEmbeddedFile(i::FLAG_embedded_src);
|
||||
embedded_writer.SetEmbeddedVariant(i::FLAG_embedded_variant);
|
||||
SnapshotWriter writer;
|
||||
if (i::FLAG_startup_src) writer.SetSnapshotFile(i::FLAG_startup_src);
|
||||
if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob);
|
||||
if (i::FLAG_embedded_builtins) {
|
||||
if (i::FLAG_embedded_src) writer.SetEmbeddedFile(i::FLAG_embedded_src);
|
||||
if (i::FLAG_embedded_variant)
|
||||
writer.SetEmbeddedVariant(i::FLAG_embedded_variant);
|
||||
}
|
||||
|
||||
std::unique_ptr<char> embed_script(
|
||||
GetExtraCode(argc >= 2 ? argv[1] : nullptr, "embedding"));
|
||||
@ -297,7 +477,7 @@ int main(int argc, char** argv) {
|
||||
i_isolate->heap()->ConfigureHeap(0, 0, code_range_size);
|
||||
}
|
||||
v8::SnapshotCreator snapshot_creator(isolate);
|
||||
if (i::FLAG_embedded_builtins) WriteEmbeddedFile(&embedded_writer);
|
||||
if (i::FLAG_embedded_builtins) WriteEmbeddedFile(&writer);
|
||||
blob = CreateSnapshotDataBlob(&snapshot_creator, embed_script.get());
|
||||
}
|
||||
|
||||
@ -310,7 +490,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
CHECK(blob.data);
|
||||
snapshot_writer.WriteSnapshot(blob);
|
||||
writer.WriteSnapshot(blob);
|
||||
delete[] blob.data;
|
||||
}
|
||||
i::FreeCurrentEmbeddedBlob();
|
||||
|
@ -196,6 +196,7 @@ v8_source_set("cctest_sources") {
|
||||
"test-inobject-slack-tracking.cc",
|
||||
"test-inspector.cc",
|
||||
"test-intl.cc",
|
||||
"test-isolate-independent-builtins.cc",
|
||||
"test-js-weak-refs.cc",
|
||||
"test-liveedit.cc",
|
||||
"test-lockers.cc",
|
||||
|
206
test/cctest/test-isolate-independent-builtins.cc
Normal file
206
test/cctest/test-isolate-independent-builtins.cc
Normal file
@ -0,0 +1,206 @@
|
||||
// Copyright 2018 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 "test/cctest/cctest.h"
|
||||
|
||||
#include "src/assembler-inl.h"
|
||||
#include "src/handles-inl.h"
|
||||
#include "src/isolate.h"
|
||||
#include "src/macro-assembler-inl.h"
|
||||
#include "src/simulator.h"
|
||||
#include "src/snapshot/macros.h"
|
||||
#include "src/snapshot/snapshot.h"
|
||||
#include "test/common/assembler-tester.h"
|
||||
|
||||
// To generate the binary files for the test function, enable this section and
|
||||
// run GenerateTestFunctionData once on each arch.
|
||||
#define GENERATE_TEST_FUNCTION_DATA false
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace test_isolate_independent_builtins {
|
||||
|
||||
// V8_CC_MSVC is true for both MSVC and clang on windows. clang can handle
|
||||
// __asm__-style inline assembly but MSVC cannot, and thus we need a more
|
||||
// precise compiler detection that can distinguish between the two. clang on
|
||||
// windows sets both __clang__ and _MSC_VER, MSVC sets only _MSC_VER.
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#define V8_COMPILER_IS_MSVC
|
||||
#endif
|
||||
|
||||
#ifndef V8_COMPILER_IS_MSVC
|
||||
#if GENERATE_TEST_FUNCTION_DATA
|
||||
|
||||
// Arch-specific defines.
|
||||
#if V8_TARGET_ARCH_IA32
|
||||
#define TEST_FUNCTION_FILE "f-ia32.bin"
|
||||
#elif V8_TARGET_ARCH_X64 && _WIN64
|
||||
#define TEST_FUNCTION_FILE "f-x64-win.bin"
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
#define TEST_FUNCTION_FILE "f-x64.bin"
|
||||
#elif V8_TARGET_ARCH_ARM64
|
||||
#define TEST_FUNCTION_FILE "f-arm64.bin"
|
||||
#elif V8_TARGET_ARCH_ARM
|
||||
#define TEST_FUNCTION_FILE "f-arm.bin"
|
||||
#elif V8_TARGET_ARCH_PPC
|
||||
#define TEST_FUNCTION_FILE "f-ppc.bin"
|
||||
#elif V8_TARGET_ARCH_MIPS
|
||||
#define TEST_FUNCTION_FILE "f-mips.bin"
|
||||
#elif V8_TARGET_ARCH_MIPS64
|
||||
#define TEST_FUNCTION_FILE "f-mips64.bin"
|
||||
#elif V8_TARGET_ARCH_S390
|
||||
#define TEST_FUNCTION_FILE "f-s390.bin"
|
||||
#else
|
||||
#error "Unknown architecture."
|
||||
#endif
|
||||
|
||||
#define __ masm.
|
||||
|
||||
TEST(GenerateTestFunctionData) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
#if V8_TARGET_ARCH_IA32
|
||||
v8::internal::byte buffer[256];
|
||||
Assembler masm(isolate, buffer, sizeof(buffer));
|
||||
|
||||
__ mov(eax, Operand(esp, 4));
|
||||
__ add(eax, Operand(esp, 8));
|
||||
__ ret(0);
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
size_t allocated;
|
||||
byte* buffer = AllocateAssemblerBuffer(&allocated);
|
||||
Assembler masm(isolate, buffer, static_cast<int>(allocated));
|
||||
|
||||
#ifdef _WIN64
|
||||
static const Register arg1 = rcx;
|
||||
static const Register arg2 = rdx;
|
||||
#else
|
||||
static const Register arg1 = rdi;
|
||||
static const Register arg2 = rsi;
|
||||
#endif
|
||||
|
||||
__ movq(rax, arg2);
|
||||
__ addq(rax, arg1);
|
||||
__ ret(0);
|
||||
#elif V8_TARGET_ARCH_ARM64
|
||||
MacroAssembler masm(isolate, nullptr, 0,
|
||||
v8::internal::CodeObjectRequired::kYes);
|
||||
|
||||
__ Add(x0, x0, x1);
|
||||
__ Ret();
|
||||
#elif V8_TARGET_ARCH_ARM
|
||||
Assembler masm(isolate, nullptr, 0);
|
||||
|
||||
__ add(r0, r0, Operand(r1));
|
||||
__ mov(pc, Operand(lr));
|
||||
#elif V8_TARGET_ARCH_PPC
|
||||
Assembler masm(isolate, nullptr, 0);
|
||||
|
||||
__ function_descriptor();
|
||||
__ add(r3, r3, r4);
|
||||
__ blr();
|
||||
#elif V8_TARGET_ARCH_MIPS
|
||||
MacroAssembler masm(isolate, nullptr, 0,
|
||||
v8::internal::CodeObjectRequired::kYes);
|
||||
|
||||
__ addu(v0, a0, a1);
|
||||
__ jr(ra);
|
||||
__ nop();
|
||||
#elif V8_TARGET_ARCH_MIPS64
|
||||
MacroAssembler masm(isolate, nullptr, 0,
|
||||
v8::internal::CodeObjectRequired::kYes);
|
||||
|
||||
__ addu(v0, a0, a1);
|
||||
__ jr(ra);
|
||||
__ nop();
|
||||
#elif V8_TARGET_ARCH_S390
|
||||
Assembler masm(isolate, nullptr, 0);
|
||||
|
||||
__ agr(r2, r3);
|
||||
__ b(r14);
|
||||
#else // Unknown architecture.
|
||||
#error "Unknown architecture."
|
||||
#endif // Target architecture.
|
||||
|
||||
CodeDesc desc;
|
||||
masm.GetCode(isolate, &desc);
|
||||
|
||||
std::ofstream of(TEST_FUNCTION_FILE, std::ios::out | std::ios::binary);
|
||||
of.write(reinterpret_cast<char*>(desc.buffer), desc.instr_size);
|
||||
}
|
||||
#undef __
|
||||
#endif // GENERATE_TEST_FUNCTION_DATA
|
||||
|
||||
#if V8_TARGET_ARCH_IA32
|
||||
#define FUNCTION_BYTES \
|
||||
".byte 0x8b, 0x44, 0x24, 0x04, 0x03, 0x44, 0x24, 0x08, 0xc3\n"
|
||||
#elif V8_TARGET_ARCH_X64 && _WIN64
|
||||
#define FUNCTION_BYTES ".byte 0x48, 0x8b, 0xc2, 0x48, 0x03, 0xc1, 0xc3\n"
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
#define FUNCTION_BYTES ".byte 0x48, 0x8b, 0xc6, 0x48, 0x03, 0xc7, 0xc3\n"
|
||||
#elif V8_TARGET_ARCH_ARM64
|
||||
#define FUNCTION_BYTES ".byte 0x00, 0x00, 0x01, 0x8b, 0xc0, 0x03, 0x5f, 0xd6\n"
|
||||
#elif V8_TARGET_ARCH_ARM
|
||||
#define FUNCTION_BYTES ".byte 0x01, 0x00, 0x80, 0xe0, 0x0e, 0xf0, 0xa0, 0xe1\n"
|
||||
#elif V8_TARGET_ARCH_PPC
|
||||
#if defined(V8_OS_AIX)
|
||||
#define FUNCTION_BYTES ".byte 0x7c, 0x64, 0x1a, 0x14, 0x4e, 0x80, 0x00, 0x20\n"
|
||||
#else
|
||||
#define FUNCTION_BYTES ".byte 0x14, 0x22, 0x63, 0x7c, 0x20, 0x00, 0x80, 0x4e\n"
|
||||
#endif
|
||||
#elif defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)
|
||||
#if defined(V8_TARGET_BIG_ENDIAN)
|
||||
#define FUNCTION_BYTES \
|
||||
".byte 0x00, 0x85, 0x10, 0x21, 0x03, 0xe0, 0x00, " \
|
||||
"0x08, 0x00, 0x00, 0x00, 0x00\n"
|
||||
#else
|
||||
#define FUNCTION_BYTES \
|
||||
".byte 0x21, 0x10, 0x85, 0x00, 0x08, 0x00, 0xe0, " \
|
||||
"0x03, 0x00, 0x00, 0x00, 0x00\n"
|
||||
#endif
|
||||
#elif V8_TARGET_ARCH_S390
|
||||
#define FUNCTION_BYTES \
|
||||
".byte 0xb9, 0x08, 0x00, 0x23, 0x07, 0xfe\n"
|
||||
#else
|
||||
#error "Unknown architecture."
|
||||
#endif
|
||||
|
||||
V8_EMBEDDED_RODATA_HEADER(test_string0_bytes)
|
||||
__asm__(".byte 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37\n"
|
||||
".byte 0x38, 0x39, 0x0a, 0x00\n");
|
||||
extern "C" V8_ALIGNED(16) const char test_string0_bytes[];
|
||||
|
||||
V8_EMBEDDED_TEXT_HEADER(test_function0_bytes)
|
||||
__asm__(FUNCTION_BYTES);
|
||||
extern "C" V8_ALIGNED(16) const char test_function0_bytes[];
|
||||
// clang-format on
|
||||
|
||||
// A historical note: We use .byte over .incbin since the latter leads to
|
||||
// complications involving generation of build-time dependencies. Goma parses
|
||||
// #include statements, and clang has -MD/-MMD. Neither recognize .incbin.
|
||||
|
||||
TEST(ByteInRodata) {
|
||||
CHECK_EQ(0, std::strcmp("0123456789\n", test_string0_bytes));
|
||||
}
|
||||
|
||||
TEST(ByteInText) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
auto f = GeneratedCode<int(int, int)>::FromAddress(
|
||||
isolate, reinterpret_cast<Address>(&test_function0_bytes[0]));
|
||||
CHECK_EQ(7, f.Call(3, 4));
|
||||
CHECK_EQ(11, f.Call(5, 6));
|
||||
}
|
||||
#endif // #ifndef V8_COMPILER_IS_MSVC
|
||||
#undef V8_COMPILER_IS_MSVC
|
||||
|
||||
#undef FUNCTION_BYTES
|
||||
#undef GENERATE_TEST_FUNCTION_DATA
|
||||
#undef TEST_FUNCTION_FILE
|
||||
|
||||
} // namespace test_isolate_independent_builtins
|
||||
} // namespace internal
|
||||
} // namespace v8
|
Loading…
Reference in New Issue
Block a user