Commit 66ed5644 authored by Toan Pham's avatar Toan Pham Committed by Commit Bot

Separate metadata from code in the embedded data blob

Some platforms disable reading of bytes in the .text section,
so move the metadata into a separate .rodata section.

Bug: v8:10707
Change-Id: I30ef7a180f489f175c31f9d4dcd02115c9f516c2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2301113
Commit-Queue: Toan Pham <toanpham@google.com>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68984}
parent 991fc239
......@@ -8887,9 +8887,9 @@ UnwindState Isolate::GetUnwindState() {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
unwind_state.embedded_code_range.start =
reinterpret_cast<const void*>(isolate->embedded_blob());
reinterpret_cast<const void*>(isolate->embedded_blob_code());
unwind_state.embedded_code_range.length_in_bytes =
isolate->embedded_blob_size();
isolate->embedded_blob_code_size();
std::array<std::pair<i::Builtins::Name, JSEntryStub*>, 3> entry_stubs = {
{{i::Builtins::kJSEntry, &unwind_state.js_entry_stub},
......
......@@ -350,8 +350,8 @@ constexpr int OffHeapTrampolineGenerator::kBufferSize;
Handle<Code> Builtins::GenerateOffHeapTrampolineFor(
Isolate* isolate, Address off_heap_entry, int32_t kind_specfic_flags,
bool generate_jump_to_instruction_stream) {
DCHECK_NOT_NULL(isolate->embedded_blob());
DCHECK_NE(0, isolate->embedded_blob_size());
DCHECK_NOT_NULL(isolate->embedded_blob_code());
DCHECK_NE(0, isolate->embedded_blob_code_size());
OffHeapTrampolineGenerator generator(isolate);
......
......@@ -237,7 +237,7 @@ bool SafeStackFrameIterator::IsNoFrameBytecodeHandlerPc(Isolate* isolate,
Address pc,
Address fp) const {
// Return false for builds with non-embedded bytecode handlers.
if (Isolate::CurrentEmbeddedBlob() == nullptr) return false;
if (Isolate::CurrentEmbeddedBlobCode() == nullptr) return false;
EmbeddedData d = EmbeddedData::FromBlob();
if (pc < d.InstructionStartOfBytecodeHandlers() ||
......
......@@ -98,8 +98,10 @@
#include "src/diagnostics/unwinding-info-win64.h"
#endif // V8_OS_WIN64
extern "C" const uint8_t* v8_Default_embedded_blob_;
extern "C" uint32_t v8_Default_embedded_blob_size_;
extern "C" const uint8_t* v8_Default_embedded_blob_code_;
extern "C" uint32_t v8_Default_embedded_blob_code_size_;
extern "C" const uint8_t* v8_Default_embedded_blob_metadata_;
extern "C" uint32_t v8_Default_embedded_blob_metadata_size_;
namespace v8 {
namespace internal {
......@@ -116,15 +118,37 @@ 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_; }
const uint8_t* DefaultEmbeddedBlobCode() {
return v8_Default_embedded_blob_code_;
}
uint32_t DefaultEmbeddedBlobCodeSize() {
return v8_Default_embedded_blob_code_size_;
}
const uint8_t* DefaultEmbeddedBlobMetadata() {
return v8_Default_embedded_blob_metadata_;
}
uint32_t DefaultEmbeddedBlobMetadataSize() {
return v8_Default_embedded_blob_metadata_size_;
}
#ifdef V8_MULTI_SNAPSHOTS
extern "C" const uint8_t* v8_Trusted_embedded_blob_;
extern "C" uint32_t v8_Trusted_embedded_blob_size_;
extern "C" const uint8_t* v8_Trusted_embedded_blob_code_;
extern "C" uint32_t v8_Trusted_embedded_blob_code_size_;
extern "C" const uint8_t* v8_Trusted_embedded_blob_metadata_;
extern "C" uint32_t v8_Trusted_embedded_blob_metadata_size_;
const uint8_t* TrustedEmbeddedBlob() { return v8_Trusted_embedded_blob_; }
uint32_t TrustedEmbeddedBlobSize() { return v8_Trusted_embedded_blob_size_; }
const uint8_t* TrustedEmbeddedBlobCode() {
return v8_Trusted_embedded_blob_code_;
}
uint32_t TrustedEmbeddedBlobCodeSize() {
return v8_Trusted_embedded_blob_code_size_;
}
const uint8_t* TrustedEmbeddedBlobMetadata() {
return v8_Trusted_embedded_blob_metadata_;
}
uint32_t TrustedEmbeddedBlobMetadataSize() {
return v8_Trusted_embedded_blob_metadata_size_;
}
#endif
namespace {
......@@ -136,8 +160,10 @@ namespace {
// variables before accessing them. Different threads may race, but this is fine
// since they all attempt to set the same values of the blob pointer and size.
std::atomic<const uint8_t*> current_embedded_blob_(nullptr);
std::atomic<uint32_t> current_embedded_blob_size_(0);
std::atomic<const uint8_t*> current_embedded_blob_code_(nullptr);
std::atomic<uint32_t> current_embedded_blob_code_size_(0);
std::atomic<const uint8_t*> current_embedded_blob_metadata_(nullptr);
std::atomic<uint32_t> current_embedded_blob_metadata_size_(0);
// The various workflows around embedded snapshots are fairly complex. We need
// to support plain old snapshot builds, nosnap builds, and the requirements of
......@@ -161,24 +187,39 @@ std::atomic<uint32_t> current_embedded_blob_size_(0);
// - Nosnapshot builds set the sticky blob and enable refcounting.
// This mutex protects access to the following variables:
// - sticky_embedded_blob_
// - sticky_embedded_blob_size_
// - sticky_embedded_blob_code_
// - sticky_embedded_blob_code_size_
// - sticky_embedded_blob_metadata_
// - sticky_embedded_blob_metadata_size_
// - enable_embedded_blob_refcounting_
// - current_embedded_blob_refs_
base::LazyMutex current_embedded_blob_refcount_mutex_ = LAZY_MUTEX_INITIALIZER;
const uint8_t* sticky_embedded_blob_ = nullptr;
uint32_t sticky_embedded_blob_size_ = 0;
const uint8_t* sticky_embedded_blob_code_ = nullptr;
uint32_t sticky_embedded_blob_code_size_ = 0;
const uint8_t* sticky_embedded_blob_metadata_ = nullptr;
uint32_t sticky_embedded_blob_metadata_size_ = 0;
bool enable_embedded_blob_refcounting_ = true;
int current_embedded_blob_refs_ = 0;
const uint8_t* StickyEmbeddedBlob() { return sticky_embedded_blob_; }
uint32_t StickyEmbeddedBlobSize() { return sticky_embedded_blob_size_; }
const uint8_t* StickyEmbeddedBlobCode() { return sticky_embedded_blob_code_; }
uint32_t StickyEmbeddedBlobCodeSize() {
return sticky_embedded_blob_code_size_;
}
const uint8_t* StickyEmbeddedBlobMetadata() {
return sticky_embedded_blob_metadata_;
}
uint32_t StickyEmbeddedBlobMetadataSize() {
return sticky_embedded_blob_metadata_size_;
}
void SetStickyEmbeddedBlob(const uint8_t* blob, uint32_t blob_size) {
sticky_embedded_blob_ = blob;
sticky_embedded_blob_size_ = blob_size;
void SetStickyEmbeddedBlob(const uint8_t* code, uint32_t code_size,
const uint8_t* metadata, uint32_t metadata_size) {
sticky_embedded_blob_code_ = code;
sticky_embedded_blob_code_size_ = code_size;
sticky_embedded_blob_metadata_ = metadata;
sticky_embedded_blob_metadata_size_ = metadata_size;
}
} // namespace
......@@ -192,18 +233,26 @@ void FreeCurrentEmbeddedBlob() {
CHECK(!enable_embedded_blob_refcounting_);
base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
if (StickyEmbeddedBlob() == nullptr) return;
if (StickyEmbeddedBlobCode() == nullptr) return;
CHECK_EQ(StickyEmbeddedBlob(), Isolate::CurrentEmbeddedBlob());
CHECK_EQ(StickyEmbeddedBlobCode(), Isolate::CurrentEmbeddedBlobCode());
CHECK_EQ(StickyEmbeddedBlobMetadata(),
Isolate::CurrentEmbeddedBlobMetadata());
InstructionStream::FreeOffHeapInstructionStream(
const_cast<uint8_t*>(Isolate::CurrentEmbeddedBlob()),
Isolate::CurrentEmbeddedBlobSize());
const_cast<uint8_t*>(Isolate::CurrentEmbeddedBlobCode()),
Isolate::CurrentEmbeddedBlobCodeSize(),
const_cast<uint8_t*>(Isolate::CurrentEmbeddedBlobMetadata()),
Isolate::CurrentEmbeddedBlobMetadataSize());
current_embedded_blob_.store(nullptr, std::memory_order_relaxed);
current_embedded_blob_size_.store(0, std::memory_order_relaxed);
sticky_embedded_blob_ = nullptr;
sticky_embedded_blob_size_ = 0;
current_embedded_blob_code_.store(nullptr, std::memory_order_relaxed);
current_embedded_blob_code_size_.store(0, std::memory_order_relaxed);
current_embedded_blob_metadata_.store(nullptr, std::memory_order_relaxed);
current_embedded_blob_metadata_size_.store(0, std::memory_order_relaxed);
sticky_embedded_blob_code_ = nullptr;
sticky_embedded_blob_code_size_ = 0;
sticky_embedded_blob_metadata_ = nullptr;
sticky_embedded_blob_metadata_size_ = 0;
}
// static
......@@ -213,22 +262,29 @@ bool Isolate::CurrentEmbeddedBlobIsBinaryEmbedded() {
// See blob lifecycle controls above for descriptions of when the current
// embedded blob may change (e.g. in tests or mksnapshot). If the blob is
// binary-embedded, it is immortal immovable.
const uint8_t* blob =
current_embedded_blob_.load(std::memory_order::memory_order_relaxed);
if (blob == nullptr) return false;
const uint8_t* code =
current_embedded_blob_code_.load(std::memory_order::memory_order_relaxed);
if (code == nullptr) return false;
#ifdef V8_MULTI_SNAPSHOTS
if (blob == TrustedEmbeddedBlob()) return true;
if (code == TrustedEmbeddedBlobCode()) return true;
#endif
return blob == DefaultEmbeddedBlob();
return code == DefaultEmbeddedBlobCode();
}
void Isolate::SetEmbeddedBlob(const uint8_t* blob, uint32_t blob_size) {
CHECK_NOT_NULL(blob);
void Isolate::SetEmbeddedBlob(const uint8_t* code, uint32_t code_size,
const uint8_t* metadata, uint32_t metadata_size) {
CHECK_NOT_NULL(code);
CHECK_NOT_NULL(metadata);
embedded_blob_ = blob;
embedded_blob_size_ = blob_size;
current_embedded_blob_.store(blob, std::memory_order_relaxed);
current_embedded_blob_size_.store(blob_size, std::memory_order_relaxed);
embedded_blob_code_ = code;
embedded_blob_code_size_ = code_size;
embedded_blob_metadata_ = metadata;
embedded_blob_metadata_size_ = metadata_size;
current_embedded_blob_code_.store(code, std::memory_order_relaxed);
current_embedded_blob_code_size_.store(code_size, std::memory_order_relaxed);
current_embedded_blob_metadata_.store(metadata, std::memory_order_relaxed);
current_embedded_blob_metadata_size_.store(metadata_size,
std::memory_order_relaxed);
#ifdef DEBUG
// Verify that the contents of the embedded blob are unchanged from
......@@ -243,34 +299,65 @@ void Isolate::SetEmbeddedBlob(const uint8_t* blob, uint32_t blob_size) {
#endif // DEBUG
if (FLAG_experimental_flush_embedded_blob_icache) {
FlushInstructionCache(const_cast<uint8_t*>(blob), blob_size);
FlushInstructionCache(const_cast<uint8_t*>(code), code_size);
}
}
void Isolate::ClearEmbeddedBlob() {
CHECK(enable_embedded_blob_refcounting_);
CHECK_EQ(embedded_blob_, CurrentEmbeddedBlob());
CHECK_EQ(embedded_blob_, StickyEmbeddedBlob());
CHECK_EQ(embedded_blob_code_, CurrentEmbeddedBlobCode());
CHECK_EQ(embedded_blob_code_, StickyEmbeddedBlobCode());
CHECK_EQ(embedded_blob_metadata_, CurrentEmbeddedBlobMetadata());
CHECK_EQ(embedded_blob_metadata_, StickyEmbeddedBlobMetadata());
embedded_blob_code_ = nullptr;
embedded_blob_code_size_ = 0;
embedded_blob_metadata_ = nullptr;
embedded_blob_metadata_size_ = 0;
current_embedded_blob_code_.store(nullptr, std::memory_order_relaxed);
current_embedded_blob_code_size_.store(0, std::memory_order_relaxed);
current_embedded_blob_metadata_.store(nullptr, std::memory_order_relaxed);
current_embedded_blob_metadata_size_.store(0, std::memory_order_relaxed);
sticky_embedded_blob_code_ = nullptr;
sticky_embedded_blob_code_size_ = 0;
sticky_embedded_blob_metadata_ = nullptr;
sticky_embedded_blob_metadata_size_ = 0;
}
const uint8_t* Isolate::embedded_blob_code() const {
return embedded_blob_code_;
}
uint32_t Isolate::embedded_blob_code_size() const {
return embedded_blob_code_size_;
}
const uint8_t* Isolate::embedded_blob_metadata() const {
return embedded_blob_metadata_;
}
uint32_t Isolate::embedded_blob_metadata_size() const {
return embedded_blob_metadata_size_;
}
embedded_blob_ = nullptr;
embedded_blob_size_ = 0;
current_embedded_blob_.store(nullptr, std::memory_order_relaxed);
current_embedded_blob_size_.store(0, std::memory_order_relaxed);
sticky_embedded_blob_ = nullptr;
sticky_embedded_blob_size_ = 0;
// static
const uint8_t* Isolate::CurrentEmbeddedBlobCode() {
return current_embedded_blob_code_.load(
std::memory_order::memory_order_relaxed);
}
const uint8_t* Isolate::embedded_blob() const { return embedded_blob_; }
uint32_t Isolate::embedded_blob_size() const { return embedded_blob_size_; }
// static
uint32_t Isolate::CurrentEmbeddedBlobCodeSize() {
return current_embedded_blob_code_size_.load(
std::memory_order::memory_order_relaxed);
}
// static
const uint8_t* Isolate::CurrentEmbeddedBlob() {
return current_embedded_blob_.load(std::memory_order::memory_order_relaxed);
const uint8_t* Isolate::CurrentEmbeddedBlobMetadata() {
return current_embedded_blob_metadata_.load(
std::memory_order::memory_order_relaxed);
}
// static
uint32_t Isolate::CurrentEmbeddedBlobSize() {
return current_embedded_blob_size_.load(
uint32_t Isolate::CurrentEmbeddedBlobMetadataSize() {
return current_embedded_blob_metadata_size_.load(
std::memory_order::memory_order_relaxed);
}
......@@ -3205,8 +3292,10 @@ void Isolate::InitializeLoggingAndCounters() {
namespace {
void CreateOffHeapTrampolines(Isolate* isolate) {
DCHECK_NOT_NULL(isolate->embedded_blob());
DCHECK_NE(0, isolate->embedded_blob_size());
DCHECK_NOT_NULL(isolate->embedded_blob_code());
DCHECK_NE(0, isolate->embedded_blob_code_size());
DCHECK_NOT_NULL(isolate->embedded_blob_metadata());
DCHECK_NE(0, isolate->embedded_blob_metadata_size());
HandleScope scope(isolate);
Builtins* builtins = isolate->builtins();
......@@ -3236,30 +3325,36 @@ bool IsolateIsCompatibleWithEmbeddedBlob(Isolate* isolate) {
} // namespace
void Isolate::InitializeDefaultEmbeddedBlob() {
const uint8_t* blob = DefaultEmbeddedBlob();
uint32_t size = DefaultEmbeddedBlobSize();
const uint8_t* code = DefaultEmbeddedBlobCode();
uint32_t code_size = DefaultEmbeddedBlobCodeSize();
const uint8_t* metadata = DefaultEmbeddedBlobMetadata();
uint32_t metadata_size = DefaultEmbeddedBlobMetadataSize();
#ifdef V8_MULTI_SNAPSHOTS
if (!FLAG_untrusted_code_mitigations) {
blob = TrustedEmbeddedBlob();
size = TrustedEmbeddedBlobSize();
code = TrustedEmbeddedBlobCode();
code_size = TrustedEmbeddedBlobCodeSize();
metadata = TrustedEmbeddedBlobMetadata();
metadata_size = TrustedEmbeddedBlobMetadataSize();
}
#endif
if (StickyEmbeddedBlob() != nullptr) {
if (StickyEmbeddedBlobCode() != nullptr) {
base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
// Check again now that we hold the lock.
if (StickyEmbeddedBlob() != nullptr) {
blob = StickyEmbeddedBlob();
size = StickyEmbeddedBlobSize();
if (StickyEmbeddedBlobCode() != nullptr) {
code = StickyEmbeddedBlobCode();
code_size = StickyEmbeddedBlobCodeSize();
metadata = StickyEmbeddedBlobMetadata();
metadata_size = StickyEmbeddedBlobMetadataSize();
current_embedded_blob_refs_++;
}
}
if (blob == nullptr) {
CHECK_EQ(0, size);
if (code == nullptr) {
CHECK_EQ(0, code_size);
} else {
SetEmbeddedBlob(blob, size);
SetEmbeddedBlob(code, code_size, metadata, metadata_size);
}
}
......@@ -3269,21 +3364,27 @@ void Isolate::CreateAndSetEmbeddedBlob() {
PrepareBuiltinSourcePositionMap();
// If a sticky blob has been set, we reuse it.
if (StickyEmbeddedBlob() != nullptr) {
CHECK_EQ(embedded_blob(), StickyEmbeddedBlob());
CHECK_EQ(CurrentEmbeddedBlob(), StickyEmbeddedBlob());
if (StickyEmbeddedBlobCode() != nullptr) {
CHECK_EQ(embedded_blob_code(), StickyEmbeddedBlobCode());
CHECK_EQ(embedded_blob_metadata(), StickyEmbeddedBlobMetadata());
CHECK_EQ(CurrentEmbeddedBlobCode(), StickyEmbeddedBlobCode());
CHECK_EQ(CurrentEmbeddedBlobMetadata(), StickyEmbeddedBlobMetadata());
} else {
// Create and set a new embedded blob.
uint8_t* data;
uint32_t size;
InstructionStream::CreateOffHeapInstructionStream(this, &data, &size);
uint8_t* code;
uint32_t code_size;
uint8_t* metadata;
uint32_t metadata_size;
InstructionStream::CreateOffHeapInstructionStream(
this, &code, &code_size, &metadata, &metadata_size);
CHECK_EQ(0, current_embedded_blob_refs_);
const uint8_t* const_data = const_cast<const uint8_t*>(data);
SetEmbeddedBlob(const_data, size);
const uint8_t* const_code = const_cast<const uint8_t*>(code);
const uint8_t* const_metadata = const_cast<const uint8_t*>(metadata);
SetEmbeddedBlob(const_code, code_size, const_metadata, metadata_size);
current_embedded_blob_refs_++;
SetStickyEmbeddedBlob(const_data, size);
SetStickyEmbeddedBlob(code, code_size, metadata, metadata_size);
}
CreateOffHeapTrampolines(this);
......@@ -3291,17 +3392,21 @@ void Isolate::CreateAndSetEmbeddedBlob() {
void Isolate::TearDownEmbeddedBlob() {
// Nothing to do in case the blob is embedded into the binary or unset.
if (StickyEmbeddedBlob() == nullptr) return;
if (StickyEmbeddedBlobCode() == nullptr) return;
CHECK_EQ(embedded_blob(), StickyEmbeddedBlob());
CHECK_EQ(CurrentEmbeddedBlob(), StickyEmbeddedBlob());
CHECK_EQ(embedded_blob_code(), StickyEmbeddedBlobCode());
CHECK_EQ(embedded_blob_metadata(), StickyEmbeddedBlobMetadata());
CHECK_EQ(CurrentEmbeddedBlobCode(), StickyEmbeddedBlobCode());
CHECK_EQ(CurrentEmbeddedBlobMetadata(), StickyEmbeddedBlobMetadata());
base::MutexGuard guard(current_embedded_blob_refcount_mutex_.Pointer());
current_embedded_blob_refs_--;
if (current_embedded_blob_refs_ == 0 && enable_embedded_blob_refcounting_) {
// We own the embedded blob and are the last holder. Free it.
InstructionStream::FreeOffHeapInstructionStream(
const_cast<uint8_t*>(embedded_blob()), embedded_blob_size());
const_cast<uint8_t*>(embedded_blob_code()), embedded_blob_code_size(),
const_cast<uint8_t*>(embedded_blob_metadata()),
embedded_blob_metadata_size());
ClearEmbeddedBlob();
}
}
......@@ -3344,8 +3449,9 @@ void Isolate::AddCrashKeysForIsolateAndHeapPointers() {
void Isolate::InitializeCodeRanges() {
DCHECK_NULL(GetCodePages());
MemoryRange embedded_range{reinterpret_cast<const void*>(embedded_blob()),
embedded_blob_size()};
MemoryRange embedded_range{
reinterpret_cast<const void*>(embedded_blob_code()),
embedded_blob_code_size()};
code_pages_buffer1_.push_back(embedded_range);
SetCodePages(&code_pages_buffer1_);
}
......
......@@ -1372,14 +1372,18 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
// builtins constants table to remain unchanged from build-time.
size_t HashIsolateForEmbeddedBlob();
static const uint8_t* CurrentEmbeddedBlob();
static uint32_t CurrentEmbeddedBlobSize();
static const uint8_t* CurrentEmbeddedBlobCode();
static uint32_t CurrentEmbeddedBlobCodeSize();
static const uint8_t* CurrentEmbeddedBlobMetadata();
static uint32_t CurrentEmbeddedBlobMetadataSize();
static bool CurrentEmbeddedBlobIsBinaryEmbedded();
// These always return the same result as static methods above, but don't
// access the global atomic variable (and thus *might be* slightly faster).
const uint8_t* embedded_blob() const;
uint32_t embedded_blob_size() const;
const uint8_t* embedded_blob_code() const;
uint32_t embedded_blob_code_size() const;
const uint8_t* embedded_blob_metadata() const;
uint32_t embedded_blob_metadata_size() const;
void set_array_buffer_allocator(v8::ArrayBuffer::Allocator* allocator) {
array_buffer_allocator_ = allocator;
......@@ -1811,11 +1815,14 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
void CreateAndSetEmbeddedBlob();
void TearDownEmbeddedBlob();
void SetEmbeddedBlob(const uint8_t* blob, uint32_t blob_size);
void SetEmbeddedBlob(const uint8_t* code, uint32_t code_size,
const uint8_t* metadata, uint32_t metadata_size);
void ClearEmbeddedBlob();
const uint8_t* embedded_blob_ = nullptr;
uint32_t embedded_blob_size_ = 0;
const uint8_t* embedded_blob_code_ = nullptr;
uint32_t embedded_blob_code_size_ = 0;
const uint8_t* embedded_blob_metadata_ = nullptr;
uint32_t embedded_blob_metadata_size_ = 0;
v8::ArrayBuffer::Allocator* array_buffer_allocator_ = nullptr;
std::shared_ptr<v8::ArrayBuffer::Allocator> array_buffer_allocator_shared_;
......
......@@ -2105,8 +2105,8 @@ Handle<CodeDataContainer> Factory::NewCodeDataContainer(
Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
Address off_heap_entry) {
CHECK_NOT_NULL(isolate()->embedded_blob());
CHECK_NE(0, isolate()->embedded_blob_size());
CHECK_NOT_NULL(isolate()->embedded_blob_code());
CHECK_NE(0, isolate()->embedded_blob_code_size());
CHECK(Builtins::IsIsolateIndependentBuiltin(*code));
bool generate_jump_to_instruction_stream =
......
......@@ -561,8 +561,9 @@ Code Code::GetCodeFromTargetAddress(Address address) {
{
// TODO(jgruber,v8:6666): Support embedded builtins here. We'd need to pass
// in the current isolate.
Address start = reinterpret_cast<Address>(Isolate::CurrentEmbeddedBlob());
Address end = start + Isolate::CurrentEmbeddedBlobSize();
Address start =
reinterpret_cast<Address>(Isolate::CurrentEmbeddedBlobCode());
Address end = start + Isolate::CurrentEmbeddedBlobCodeSize();
CHECK(address < start || address >= end);
}
......
......@@ -143,21 +143,24 @@ SafepointEntry Code::GetSafepointEntry(Address pc) {
int Code::OffHeapInstructionSize() const {
DCHECK(is_off_heap_trampoline());
if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_size();
if (Isolate::CurrentEmbeddedBlobCode() == nullptr)
return raw_instruction_size();
EmbeddedData d = EmbeddedData::FromBlob();
return d.InstructionSizeOfBuiltin(builtin_index());
}
Address Code::OffHeapInstructionStart() const {
DCHECK(is_off_heap_trampoline());
if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_start();
if (Isolate::CurrentEmbeddedBlobCode() == nullptr)
return raw_instruction_start();
EmbeddedData d = EmbeddedData::FromBlob();
return d.InstructionStartOfBuiltin(builtin_index());
}
Address Code::OffHeapInstructionEnd() const {
DCHECK(is_off_heap_trampoline());
if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_end();
if (Isolate::CurrentEmbeddedBlobCode() == nullptr)
return raw_instruction_end();
EmbeddedData d = EmbeddedData::FromBlob();
return d.InstructionStartOfBuiltin(builtin_index()) +
d.InstructionSizeOfBuiltin(builtin_index());
......
......@@ -848,10 +848,9 @@ RUNTIME_FUNCTION(Runtime_ProfileCreateSnapshotDataBlob) {
// Track the embedded blob size as well.
{
int embedded_blob_size = 0;
i::EmbeddedData d = i::EmbeddedData::FromBlob();
embedded_blob_size = static_cast<int>(d.size());
PrintF("Embedded blob is %d bytes\n", embedded_blob_size);
PrintF("Embedded blob is %d bytes\n",
static_cast<int>(d.code_size() + d.metadata_size()));
}
FreeCurrentEmbeddedBlob();
......
......@@ -501,7 +501,7 @@ void Deserializer::VisitOffHeapTarget(Code host, RelocInfo* rinfo) {
int builtin_index = source_.GetInt();
DCHECK(Builtins::IsBuiltinId(builtin_index));
CHECK_NOT_NULL(isolate()->embedded_blob());
CHECK_NOT_NULL(isolate()->embedded_blob_code());
EmbeddedData d = EmbeddedData::FromBlob();
Address address = d.InstructionStartOfBuiltin(builtin_index);
CHECK_NE(kNullAddress, address);
......
......@@ -15,8 +15,9 @@ namespace internal {
// static
bool InstructionStream::PcIsOffHeap(Isolate* isolate, Address pc) {
const Address start = reinterpret_cast<Address>(isolate->embedded_blob());
return start <= pc && pc < start + isolate->embedded_blob_size();
const Address start =
reinterpret_cast<Address>(isolate->embedded_blob_code());
return start <= pc && pc < start + isolate->embedded_blob_code_size();
}
// static
......@@ -49,9 +50,9 @@ Code InstructionStream::TryLookupCode(Isolate* isolate, Address address) {
}
// static
void InstructionStream::CreateOffHeapInstructionStream(Isolate* isolate,
uint8_t** data,
uint32_t* size) {
void InstructionStream::CreateOffHeapInstructionStream(
Isolate* isolate, uint8_t** code, uint32_t* code_size, uint8_t** metadata,
uint32_t* metadata_size) {
// Create the embedded blob from scratch using the current Isolate's heap.
EmbeddedData d = EmbeddedData::FromIsolate(isolate);
......@@ -62,14 +63,22 @@ void InstructionStream::CreateOffHeapInstructionStream(Isolate* isolate,
const uint32_t alignment =
static_cast<uint32_t>(page_allocator->AllocatePageSize());
void* const requested_allocation_address =
void* const requested_allocation_code_address =
AlignedAddress(isolate->heap()->GetRandomMmapAddr(), alignment);
const uint32_t allocation_size = RoundUp(d.size(), alignment);
const uint32_t allocation_code_size = RoundUp(d.code_size(), alignment);
uint8_t* allocated_code_bytes = static_cast<uint8_t*>(AllocatePages(
page_allocator, requested_allocation_code_address, allocation_code_size,
alignment, PageAllocator::kReadWrite));
CHECK_NOT_NULL(allocated_code_bytes);
uint8_t* allocated_bytes = static_cast<uint8_t*>(
AllocatePages(page_allocator, requested_allocation_address,
allocation_size, alignment, PageAllocator::kReadWrite));
CHECK_NOT_NULL(allocated_bytes);
void* const requested_allocation_metadata_address =
AlignedAddress(isolate->heap()->GetRandomMmapAddr(), alignment);
const uint32_t allocation_metadata_size =
RoundUp(d.metadata_size(), alignment);
uint8_t* allocated_metadata_bytes = static_cast<uint8_t*>(AllocatePages(
page_allocator, requested_allocation_metadata_address,
allocation_metadata_size, alignment, PageAllocator::kReadWrite));
CHECK_NOT_NULL(allocated_metadata_bytes);
// Copy the embedded blob into the newly allocated backing store. Switch
// permissions to read-execute since builtin code is immutable from now on
......@@ -79,23 +88,32 @@ void InstructionStream::CreateOffHeapInstructionStream(Isolate* isolate,
// the difference between a 'real' embedded build (where the blob is embedded
// in the binary) and what we are currently setting up here (where the blob is
// on the native heap).
std::memcpy(allocated_bytes, d.data(), d.size());
CHECK(SetPermissions(page_allocator, allocated_bytes, allocation_size,
PageAllocator::kReadExecute));
std::memcpy(allocated_code_bytes, d.code(), d.code_size());
CHECK(SetPermissions(page_allocator, allocated_code_bytes,
allocation_code_size, PageAllocator::kReadExecute));
std::memcpy(allocated_metadata_bytes, d.metadata(), d.metadata_size());
CHECK(SetPermissions(page_allocator, allocated_metadata_bytes,
allocation_metadata_size, PageAllocator::kRead));
*data = allocated_bytes;
*size = d.size();
*code = allocated_code_bytes;
*code_size = d.code_size();
*metadata = allocated_metadata_bytes;
*metadata_size = d.metadata_size();
d.Dispose();
}
// static
void InstructionStream::FreeOffHeapInstructionStream(uint8_t* data,
uint32_t size) {
void InstructionStream::FreeOffHeapInstructionStream(uint8_t* code,
uint32_t code_size,
uint8_t* metadata,
uint32_t metadata_size) {
v8::PageAllocator* page_allocator = v8::internal::GetPlatformPageAllocator();
const uint32_t page_size =
static_cast<uint32_t>(page_allocator->AllocatePageSize());
CHECK(FreePages(page_allocator, data, RoundUp(size, page_size)));
CHECK(FreePages(page_allocator, code, RoundUp(code_size, page_size)));
CHECK(FreePages(page_allocator, metadata, RoundUp(metadata_size, page_size)));
}
namespace {
......@@ -190,7 +208,7 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
std::vector<struct Metadata> metadata(kTableSize);
bool saw_unsafe_builtin = false;
uint32_t raw_data_size = 0;
uint32_t raw_code_size = 0;
for (int i = 0; i < Builtins::builtin_count; i++) {
Code code = builtins->builtin(i);
......@@ -209,14 +227,14 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
uint32_t length = static_cast<uint32_t>(code.raw_instruction_size());
DCHECK_EQ(0, raw_data_size % kCodeAlignment);
metadata[i].instructions_offset = raw_data_size;
DCHECK_EQ(0, raw_code_size % kCodeAlignment);
metadata[i].instructions_offset = raw_code_size;
metadata[i].instructions_length = length;
// Align the start of each instruction stream.
raw_data_size += PadAndAlign(length);
raw_code_size += PadAndAlign(length);
} else {
metadata[i].instructions_offset = raw_data_size;
metadata[i].instructions_offset = raw_code_size;
}
}
CHECK_WITH_MSG(
......@@ -225,38 +243,42 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
"isolate-dependent code or aliases the off-heap trampoline register. "
"If in doubt, ask jgruber@");
const uint32_t blob_size = RawDataOffset() + raw_data_size;
uint8_t* const blob = new uint8_t[blob_size];
uint8_t* const raw_data_start = blob + RawDataOffset();
const uint32_t blob_code_size = RawCodeOffset() + raw_code_size;
uint8_t* const blob_code = new uint8_t[blob_code_size];
uint8_t* const raw_code_start = blob_code + RawCodeOffset();
const uint32_t blob_metadata_size =
MetadataTableOffset() + MetadataTableSize();
uint8_t* const blob_metadata = new uint8_t[blob_metadata_size];
// Initially zap the entire blob, effectively padding the alignment area
// between two builtins with int3's (on x64/ia32).
ZapCode(reinterpret_cast<Address>(blob), blob_size);
ZapCode(reinterpret_cast<Address>(blob_code), blob_code_size);
// Hash relevant parts of the Isolate's heap and store the result.
{
STATIC_ASSERT(IsolateHashSize() == kSizetSize);
const size_t hash = isolate->HashIsolateForEmbeddedBlob();
std::memcpy(blob + IsolateHashOffset(), &hash, IsolateHashSize());
std::memcpy(blob_metadata + IsolateHashOffset(), &hash, IsolateHashSize());
}
// Write the metadata tables.
DCHECK_EQ(MetadataSize(), sizeof(metadata[0]) * metadata.size());
std::memcpy(blob + MetadataOffset(), metadata.data(), MetadataSize());
DCHECK_EQ(MetadataTableSize(), sizeof(metadata[0]) * metadata.size());
std::memcpy(blob_metadata + MetadataTableOffset(), metadata.data(),
MetadataTableSize());
// Write the raw data section.
for (int i = 0; i < Builtins::builtin_count; i++) {
if (!Builtins::IsIsolateIndependent(i)) continue;
Code code = builtins->builtin(i);
uint32_t offset = metadata[i].instructions_offset;
uint8_t* dst = raw_data_start + offset;
DCHECK_LE(RawDataOffset() + offset + code.raw_instruction_size(),
blob_size);
uint8_t* dst = raw_code_start + offset;
DCHECK_LE(RawCodeOffset() + offset + code.raw_instruction_size(),
blob_code_size);
std::memcpy(dst, reinterpret_cast<uint8_t*>(code.raw_instruction_start()),
code.raw_instruction_size());
}
EmbeddedData d(blob, blob_size);
EmbeddedData d(blob_code, blob_code_size, blob_metadata, blob_metadata_size);
// Fix up call targets that point to other embedded builtins.
FinalizeEmbeddedCodeTargets(isolate, &d);
......@@ -265,7 +287,8 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
{
STATIC_ASSERT(EmbeddedBlobHashSize() == kSizetSize);
const size_t hash = d.CreateEmbeddedBlobHash();
std::memcpy(blob + EmbeddedBlobHashOffset(), &hash, EmbeddedBlobHashSize());
std::memcpy(blob_metadata + EmbeddedBlobHashOffset(), &hash,
EmbeddedBlobHashSize());
DCHECK_EQ(hash, d.CreateEmbeddedBlobHash());
DCHECK_EQ(hash, d.EmbeddedBlobHash());
......@@ -279,9 +302,10 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
Address EmbeddedData::InstructionStartOfBuiltin(int i) const {
DCHECK(Builtins::IsBuiltinId(i));
const struct Metadata* metadata = Metadata();
const uint8_t* result = RawData() + metadata[i].instructions_offset;
DCHECK_LE(result, data_ + size_);
DCHECK_IMPLIES(result == data_ + size_, InstructionSizeOfBuiltin(i) == 0);
const uint8_t* result = RawCode() + metadata[i].instructions_offset;
DCHECK_LE(result, code_ + code_size_);
DCHECK_IMPLIES(result == code_ + code_size_,
InstructionSizeOfBuiltin(i) == 0);
return reinterpret_cast<Address>(result);
}
......@@ -308,9 +332,10 @@ size_t EmbeddedData::CreateEmbeddedBlobHash() const {
STATIC_ASSERT(EmbeddedBlobHashOffset() == 0);
STATIC_ASSERT(EmbeddedBlobHashSize() == kSizetSize);
// Hash the entire blob except the hash field itself.
Vector<const byte> payload(data_ + EmbeddedBlobHashSize(),
size_ - EmbeddedBlobHashSize());
return Checksum(payload);
Vector<const byte> payload1(metadata_ + EmbeddedBlobHashSize(),
metadata_size_ - EmbeddedBlobHashSize());
Vector<const byte> payload2(code_, code_size_);
return Checksum(payload1, payload2);
}
void EmbeddedData::PrintStatistics() const {
......@@ -337,16 +362,14 @@ void EmbeddedData::PrintStatistics() const {
const int k90th = embedded_count * 0.90;
const int k99th = embedded_count * 0.99;
const int metadata_size = static_cast<int>(
EmbeddedBlobHashSize() + IsolateHashSize() + MetadataSize());
PrintF("EmbeddedData:\n");
PrintF(" Total size: %d\n",
static_cast<int>(size()));
PrintF(" Metadata size: %d\n", metadata_size);
static_cast<int>(code_size() + metadata_size()));
PrintF(" Metadata size: %d\n",
static_cast<int>(metadata_size()));
PrintF(" Instruction size: %d\n", instruction_size);
PrintF(" Padding: %d\n",
static_cast<int>(size() - metadata_size - instruction_size));
static_cast<int>(code_size() - instruction_size));
PrintF(" Embedded builtin count: %d\n", embedded_count);
PrintF(" Instruction size (50th percentile): %d\n", sizes[k50th]);
PrintF(" Instruction size (75th percentile): %d\n", sizes[k75th]);
......
......@@ -30,9 +30,13 @@ class InstructionStream final : public AllStatic {
// containing all off-heap code. The area is guaranteed to be contiguous.
// Note that this only applies when building the snapshot, e.g. for
// mksnapshot. Otherwise, off-heap code is embedded directly into the binary.
static void CreateOffHeapInstructionStream(Isolate* isolate, uint8_t** data,
uint32_t* size);
static void FreeOffHeapInstructionStream(uint8_t* data, uint32_t size);
static void CreateOffHeapInstructionStream(Isolate* isolate, uint8_t** code,
uint32_t* code_size,
uint8_t** metadata,
uint32_t* metadata_size);
static void FreeOffHeapInstructionStream(uint8_t* code, uint32_t code_size,
uint8_t* metadata,
uint32_t metadata_size);
};
class EmbeddedData final {
......@@ -40,19 +44,30 @@ class EmbeddedData final {
static EmbeddedData FromIsolate(Isolate* isolate);
static EmbeddedData FromBlob() {
return EmbeddedData(Isolate::CurrentEmbeddedBlob(),
Isolate::CurrentEmbeddedBlobSize());
return EmbeddedData(Isolate::CurrentEmbeddedBlobCode(),
Isolate::CurrentEmbeddedBlobCodeSize(),
Isolate::CurrentEmbeddedBlobMetadata(),
Isolate::CurrentEmbeddedBlobMetadataSize());
}
static EmbeddedData FromBlob(Isolate* isolate) {
return EmbeddedData(isolate->embedded_blob(),
isolate->embedded_blob_size());
return EmbeddedData(isolate->embedded_blob_code(),
isolate->embedded_blob_code_size(),
isolate->embedded_blob_metadata(),
isolate->embedded_blob_metadata_size());
}
const uint8_t* data() const { return data_; }
uint32_t size() const { return size_; }
const uint8_t* code() const { return code_; }
uint32_t code_size() const { return code_size_; }
const uint8_t* metadata() const { return metadata_; }
uint32_t metadata_size() const { return metadata_size_; }
void Dispose() { delete[] data_; }
void Dispose() {
delete[] code_;
code_ = nullptr;
delete[] metadata_;
metadata_ = nullptr;
}
Address InstructionStartOfBuiltin(int i) const;
uint32_t InstructionSizeOfBuiltin(int i) const;
......@@ -63,8 +78,8 @@ class EmbeddedData final {
bool ContainsBuiltin(int i) const { return InstructionSizeOfBuiltin(i) > 0; }
uint32_t AddressForHashing(Address addr) {
Address start = reinterpret_cast<Address>(data_);
DCHECK(base::IsInRange(addr, start, start + size_));
Address start = reinterpret_cast<Address>(code_);
DCHECK(base::IsInRange(addr, start, start + code_size_));
return static_cast<uint32_t>(addr - start);
}
......@@ -76,11 +91,12 @@ class EmbeddedData final {
size_t CreateEmbeddedBlobHash() const;
size_t EmbeddedBlobHash() const {
return *reinterpret_cast<const size_t*>(data_ + EmbeddedBlobHashOffset());
return *reinterpret_cast<const size_t*>(metadata_ +
EmbeddedBlobHashOffset());
}
size_t IsolateHash() const {
return *reinterpret_cast<const size_t*>(data_ + IsolateHashOffset());
return *reinterpret_cast<const size_t*>(metadata_ + IsolateHashOffset());
}
struct Metadata {
......@@ -94,10 +110,14 @@ class EmbeddedData final {
// The layout of the blob is as follows:
//
// metadata:
// [0] hash of the remaining blob
// [1] hash of embedded-blob-relevant heap objects
// [2] metadata of instruction stream 0
// ... metadata
//
// code:
// [0] instruction streams 0
// ... instruction streams
static constexpr uint32_t kTableSize = Builtins::builtin_count;
......@@ -107,26 +127,32 @@ class EmbeddedData final {
return EmbeddedBlobHashOffset() + EmbeddedBlobHashSize();
}
static constexpr uint32_t IsolateHashSize() { return kSizetSize; }
static constexpr uint32_t MetadataOffset() {
static constexpr uint32_t MetadataTableOffset() {
return IsolateHashOffset() + IsolateHashSize();
}
static constexpr uint32_t MetadataSize() {
static constexpr uint32_t MetadataTableSize() {
return sizeof(struct Metadata) * kTableSize;
}
static constexpr uint32_t RawDataOffset() {
return PadAndAlign(MetadataOffset() + MetadataSize());
}
static constexpr uint32_t RawCodeOffset() { return 0; }
private:
EmbeddedData(const uint8_t* data, uint32_t size) : data_(data), size_(size) {
DCHECK_NOT_NULL(data);
DCHECK_LT(0, size);
EmbeddedData(const uint8_t* code, uint32_t code_size, const uint8_t* metadata,
uint32_t metadata_size)
: code_(code),
code_size_(code_size),
metadata_(metadata),
metadata_size_(metadata_size) {
DCHECK_NOT_NULL(code);
DCHECK_LT(0, code_size);
DCHECK_NOT_NULL(metadata);
DCHECK_LT(0, metadata_size);
}
const Metadata* Metadata() const {
return reinterpret_cast<const struct Metadata*>(data_ + MetadataOffset());
return reinterpret_cast<const struct Metadata*>(metadata_ +
MetadataTableOffset());
}
const uint8_t* RawData() const { return data_ + RawDataOffset(); }
const uint8_t* RawCode() const { return code_ + RawCodeOffset(); }
static constexpr int PadAndAlign(int size) {
// Ensure we have at least one byte trailing the actual builtin
......@@ -136,8 +162,14 @@ class EmbeddedData final {
void PrintStatistics() const;
const uint8_t* data_;
uint32_t size_;
// This points to code for builtins. The contents are potentially unreadable
// on platforms that disallow reads from the .text section.
const uint8_t* code_;
uint32_t code_size_;
// This is metadata for the code.
const uint8_t* metadata_;
uint32_t metadata_size_;
};
} // namespace internal
......
......@@ -8,16 +8,24 @@
#include "src/base/macros.h"
extern "C" const uint8_t* v8_Default_embedded_blob_;
extern "C" uint32_t v8_Default_embedded_blob_size_;
extern "C" const uint8_t* v8_Default_embedded_blob_code_;
extern "C" uint32_t v8_Default_embedded_blob_code_size_;
extern "C" const uint8_t* v8_Default_embedded_blob_metadata_;
extern "C" uint32_t v8_Default_embedded_blob_metadata_size_;
const uint8_t* v8_Default_embedded_blob_ = nullptr;
uint32_t v8_Default_embedded_blob_size_ = 0;
const uint8_t* v8_Default_embedded_blob_code_ = nullptr;
uint32_t v8_Default_embedded_blob_code_size_ = 0;
const uint8_t* v8_Default_embedded_blob_metadata_ = nullptr;
uint32_t v8_Default_embedded_blob_metadata_size_ = 0;
#ifdef V8_MULTI_SNAPSHOTS
extern "C" const uint8_t* v8_Trusted_embedded_blob_;
extern "C" uint32_t v8_Trusted_embedded_blob_size_;
extern "C" const uint8_t* v8_Trusted_embedded_blob_code_;
extern "C" uint32_t v8_Trusted_embedded_blob_code_size_;
extern "C" const uint8_t* v8_Trusted_embedded_blob_metadata_;
extern "C" uint32_t v8_Trusted_embedded_blob_metadata_size_;
const uint8_t* v8_Trusted_embedded_blob_ = nullptr;
uint32_t v8_Trusted_embedded_blob_size_ = 0;
const uint8_t* v8_Trusted_embedded_blob_code_ = nullptr;
uint32_t v8_Trusted_embedded_blob_code_size_ = 0;
const uint8_t* v8_Trusted_embedded_blob_metadata_ = nullptr;
uint32_t v8_Trusted_embedded_blob_metadata_size_ = 0;
#endif
......@@ -73,27 +73,49 @@ void EmbeddedFileWriter::WriteBuiltin(PlatformEmbeddedFileWriterBase* w,
void EmbeddedFileWriter::WriteFileEpilogue(PlatformEmbeddedFileWriterBase* w,
const i::EmbeddedData* blob) const {
{
i::EmbeddedVector<char, kTemporaryStringLength> embedded_blob_symbol;
i::SNPrintF(embedded_blob_symbol, "v8_%s_embedded_blob_",
i::EmbeddedVector<char, kTemporaryStringLength> embedded_blob_code_symbol;
i::SNPrintF(embedded_blob_code_symbol, "v8_%s_embedded_blob_code_",
embedded_variant_);
w->Comment("Pointer to the beginning of the embedded blob.");
w->Comment("Pointer to the beginning of the embedded blob code.");
w->SectionData();
w->AlignToDataAlignment();
w->DeclarePointerToSymbol(embedded_blob_symbol.begin(),
EmbeddedBlobDataSymbol().c_str());
w->DeclarePointerToSymbol(embedded_blob_code_symbol.begin(),
EmbeddedBlobCodeDataSymbol().c_str());
w->Newline();
i::EmbeddedVector<char, kTemporaryStringLength>
embedded_blob_metadata_symbol;
i::SNPrintF(embedded_blob_metadata_symbol, "v8_%s_embedded_blob_metadata_",
embedded_variant_);
w->Comment("Pointer to the beginning of the embedded blob metadata.");
w->AlignToDataAlignment();
w->DeclarePointerToSymbol(embedded_blob_metadata_symbol.begin(),
EmbeddedBlobMetadataDataSymbol().c_str());
w->Newline();
}
{
i::EmbeddedVector<char, kTemporaryStringLength> embedded_blob_size_symbol;
i::SNPrintF(embedded_blob_size_symbol, "v8_%s_embedded_blob_size_",
embedded_variant_);
i::EmbeddedVector<char, kTemporaryStringLength>
embedded_blob_code_size_symbol;
i::SNPrintF(embedded_blob_code_size_symbol,
"v8_%s_embedded_blob_code_size_", embedded_variant_);
w->Comment("The size of the embedded blob in bytes.");
w->Comment("The size of the embedded blob code in bytes.");
w->SectionRoData();
w->AlignToDataAlignment();
w->DeclareUint32(embedded_blob_size_symbol.begin(), blob->size());
w->DeclareUint32(embedded_blob_code_size_symbol.begin(), blob->code_size());
w->Newline();
i::EmbeddedVector<char, kTemporaryStringLength>
embedded_blob_metadata_size_symbol;
i::SNPrintF(embedded_blob_metadata_size_symbol,
"v8_%s_embedded_blob_metadata_size_", embedded_variant_);
w->Comment("The size of the embedded blob metadata in bytes.");
w->DeclareUint32(embedded_blob_metadata_size_symbol.begin(),
blob->metadata_size());
w->Newline();
}
......@@ -104,7 +126,7 @@ void EmbeddedFileWriter::WriteFileEpilogue(PlatformEmbeddedFileWriterBase* w,
embedded_variant_);
w->MaybeEmitUnwindData(unwind_info_symbol.begin(),
EmbeddedBlobDataSymbol().c_str(), blob,
EmbeddedBlobCodeDataSymbol().c_str(), blob,
reinterpret_cast<const void*>(&unwind_infos_[0]));
}
#endif // V8_OS_WIN64
......
......@@ -142,23 +142,31 @@ class EmbeddedFileWriter : public EmbeddedFileWriterInterface {
// Fairly arbitrary but should fit all symbol names.
static constexpr int kTemporaryStringLength = 256;
std::string EmbeddedBlobDataSymbol() const {
i::EmbeddedVector<char, kTemporaryStringLength> embedded_blob_data_symbol;
i::SNPrintF(embedded_blob_data_symbol, "v8_%s_embedded_blob_data_",
embedded_variant_);
return std::string{embedded_blob_data_symbol.begin()};
std::string EmbeddedBlobCodeDataSymbol() const {
i::EmbeddedVector<char, kTemporaryStringLength>
embedded_blob_code_data_symbol;
i::SNPrintF(embedded_blob_code_data_symbol,
"v8_%s_embedded_blob_code_data_", embedded_variant_);
return std::string{embedded_blob_code_data_symbol.begin()};
}
std::string EmbeddedBlobMetadataDataSymbol() const {
i::EmbeddedVector<char, kTemporaryStringLength>
embedded_blob_metadata_data_symbol;
i::SNPrintF(embedded_blob_metadata_data_symbol,
"v8_%s_embedded_blob_metadata_data_", embedded_variant_);
return std::string{embedded_blob_metadata_data_symbol.begin()};
}
void WriteMetadataSection(PlatformEmbeddedFileWriterBase* w,
const i::EmbeddedData* blob) const {
w->Comment("The embedded blob starts here. Metadata comes first, followed");
w->Comment("by builtin instruction streams.");
w->SectionText();
w->AlignToCodeAlignment();
w->DeclareLabel(EmbeddedBlobDataSymbol().c_str());
w->Comment("The embedded blob metadata starts here.");
w->SectionRoData();
w->AlignToDataAlignment();
w->DeclareLabel(EmbeddedBlobMetadataDataSymbol().c_str());
WriteBinaryContentsAsInlineAssembly(w, blob->data(),
i::EmbeddedData::RawDataOffset());
WriteBinaryContentsAsInlineAssembly(w, blob->metadata(),
blob->metadata_size());
}
void WriteBuiltin(PlatformEmbeddedFileWriterBase* w,
......@@ -166,6 +174,12 @@ class EmbeddedFileWriter : public EmbeddedFileWriterInterface {
void WriteInstructionStreams(PlatformEmbeddedFileWriterBase* w,
const i::EmbeddedData* blob) const {
w->Comment("The embedded blob data starts here. It contains the builtin");
w->Comment("instruction streams.");
w->SectionText();
w->AlignToCodeAlignment();
w->DeclareLabel(EmbeddedBlobCodeDataSymbol().c_str());
for (int i = 0; i < i::Builtins::builtin_count; i++) {
if (!blob->ContainsBuiltin(i)) continue;
......
......@@ -118,7 +118,7 @@ void EmitUnwindData(PlatformEmbeddedFileWriterWin* w,
if (unwind_infos[i].is_leaf_function()) continue;
uint64_t builtin_start_offset = blob->InstructionStartOfBuiltin(i) -
reinterpret_cast<Address>(blob->data());
reinterpret_cast<Address>(blob->code());
uint32_t builtin_size = blob->InstructionSizeOfBuiltin(i);
const std::vector<int>& xdata_desc = unwind_infos[i].fp_offsets();
......@@ -198,7 +198,7 @@ void EmitUnwindData(PlatformEmbeddedFileWriterWin* w,
if (unwind_infos[i].is_leaf_function()) continue;
uint64_t builtin_start_offset = blob->InstructionStartOfBuiltin(i) -
reinterpret_cast<Address>(blob->data());
reinterpret_cast<Address>(blob->code());
uint32_t builtin_size = blob->InstructionSizeOfBuiltin(i);
const std::vector<int>& xdata_desc = unwind_infos[i].fp_offsets();
......
......@@ -21,5 +21,20 @@ uint32_t Checksum(Vector<const byte> payload) {
return static_cast<uint32_t>(adler32(0, payload.begin(), payload.length()));
}
V8_EXPORT_PRIVATE uint32_t Checksum(Vector<const byte> payload1,
Vector<const byte> payload2) {
#ifdef MEMORY_SANITIZER
// Computing the checksum includes padding bytes for objects like strings.
// Mark every object as initialized in the code serializer.
MSAN_MEMORY_IS_INITIALIZED(payload1.begin(), payload1.length());
MSAN_MEMORY_IS_INITIALIZED(payload2.begin(), payload2.length());
#endif // MEMORY_SANITIZER
// Priming the adler32 call so it can see what CPU features are available.
adler32(0, nullptr, 0);
auto sum = adler32(0, payload1.begin(), payload1.length());
sum = adler32(sum, payload2.begin(), payload2.length());
return static_cast<uint32_t>(sum);
}
} // namespace internal
} // namespace v8
......@@ -11,6 +11,8 @@ namespace v8 {
namespace internal {
V8_EXPORT_PRIVATE uint32_t Checksum(Vector<const byte> payload);
V8_EXPORT_PRIVATE uint32_t Checksum(Vector<const byte> payload1,
Vector<const byte> payload2);
} // namespace internal
} // namespace v8
......
......@@ -98,9 +98,9 @@ TEST(CodeRangeCorrectContents) {
// We should only have the code range and the embedded code range.
CHECK_EQ(2, pages->size());
CHECK(PagesHasExactPage(pages, code_range.begin(), code_range.size()));
CHECK(PagesHasExactPage(pages,
reinterpret_cast<Address>(i_isolate->embedded_blob()),
i_isolate->embedded_blob_size()));
CHECK(PagesHasExactPage(
pages, reinterpret_cast<Address>(i_isolate->embedded_blob_code()),
i_isolate->embedded_blob_code_size()));
}
TEST(CodePagesCorrectContents) {
......@@ -120,9 +120,9 @@ TEST(CodePagesCorrectContents) {
// We should have the embedded code range even when there is no regular code
// range.
CHECK(PagesHasExactPage(pages,
reinterpret_cast<Address>(i_isolate->embedded_blob()),
i_isolate->embedded_blob_size()));
CHECK(PagesHasExactPage(
pages, reinterpret_cast<Address>(i_isolate->embedded_blob_code()),
i_isolate->embedded_blob_code_size()));
}
TEST(OptimizedCodeWithCodeRange) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment