diff --git a/BUILD.gn b/BUILD.gn index 6fccfa7353..283c7f6a6d 100644 --- a/BUILD.gn +++ b/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(). The target will resolve to # run_mksnapshot_. If is "default", no file suffixes will be used. -# Otherwise files are suffixed, e.g. embedded_.S and +# Otherwise files are suffixed, e.g. embedded_.cc and # snapshot_blob_.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", ] diff --git a/src/isolate.cc b/src/isolate.cc index f012ce278b..c8252b8b0a 100644 --- a/src/isolate.cc +++ b/src/isolate.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 { diff --git a/src/snapshot/embedded-empty.cc b/src/snapshot/embedded-empty.cc index 9ffb3458d3..77e83b73ce 100644 --- a/src/snapshot/embedded-empty.cc +++ b/src/snapshot/embedded-empty.cc @@ -6,18 +6,16 @@ #include -#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 diff --git a/src/snapshot/embedded-file-writer.cc b/src/snapshot/embedded-file-writer.cc deleted file mode 100644 index 201e2a2a13..0000000000 --- a/src/snapshot/embedded-file-writer.cc +++ /dev/null @@ -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" - // to create a DWARF subprogram entry. - fprintf(fp_, ".type %s, %%function\n", name); -#else - // Other ELF Format binaries use ".type , @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 diff --git a/src/snapshot/embedded-file-writer.h b/src/snapshot/embedded-file-writer.h deleted file mode 100644 index 15d1d0ab63..0000000000 --- a/src/snapshot/embedded-file-writer.h +++ /dev/null @@ -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 -#include - -#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__embedded_blob_ (intptr_t): -// a pointer to the start of the embedded blob. -// v8__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(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(builtin_symbol), "Builtins_%s", - i::Builtins::name(i)); - } else { - i::SNPrintF(i::Vector(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(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(embedded_blob_data_symbol), - "v8_%s_embedded_blob_data_", embedded_variant_); - - char embedded_blob_symbol[kTemporaryStringLength]; - i::SNPrintF(i::Vector(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(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(data); - const uint64_t* quad_ptr2 = reinterpret_cast(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_ diff --git a/src/snapshot/macros.h b/src/snapshot/macros.h new file mode 100644 index 0000000000..74c6cae23b --- /dev/null +++ b/src/snapshot/macros.h @@ -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" +// 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" +// 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_ diff --git a/src/snapshot/mksnapshot.cc b/src/snapshot/mksnapshot.cc index 624d3cac40..f11c753ba7 100644 --- a/src/snapshot/mksnapshot.cc +++ b/src/snapshot/mksnapshot.cc @@ -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& 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 \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(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(data); + const uint64_t* quad_ptr2 = reinterpret_cast(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 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(); diff --git a/test/cctest/BUILD.gn b/test/cctest/BUILD.gn index 97d0674dc1..e188917a32 100644 --- a/test/cctest/BUILD.gn +++ b/test/cctest/BUILD.gn @@ -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", diff --git a/test/cctest/test-isolate-independent-builtins.cc b/test/cctest/test-isolate-independent-builtins.cc new file mode 100644 index 0000000000..4b4babdb37 --- /dev/null +++ b/test/cctest/test-isolate-independent-builtins.cc @@ -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(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(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::FromAddress( + isolate, reinterpret_cast
(&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