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: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68984}
This commit is contained in:
Toan Pham 2020-07-22 02:13:00 -07:00 committed by Commit Bot
parent 991fc23962
commit 66ed564412
19 changed files with 451 additions and 219 deletions

View File

@ -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},

View File

@ -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);

View File

@ -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() ||

View File

@ -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_ = 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;
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() const { return embedded_blob_; }
uint32_t Isolate::embedded_blob_size() const { return embedded_blob_size_; }
// static
const uint8_t* Isolate::CurrentEmbeddedBlob() {
return current_embedded_blob_.load(std::memory_order::memory_order_relaxed);
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_;
}
// static
uint32_t Isolate::CurrentEmbeddedBlobSize() {
return current_embedded_blob_size_.load(
const uint8_t* Isolate::CurrentEmbeddedBlobCode() {
return current_embedded_blob_code_.load(
std::memory_order::memory_order_relaxed);
}
// static
uint32_t Isolate::CurrentEmbeddedBlobCodeSize() {
return current_embedded_blob_code_size_.load(
std::memory_order::memory_order_relaxed);
}
// static
const uint8_t* Isolate::CurrentEmbeddedBlobMetadata() {
return current_embedded_blob_metadata_.load(
std::memory_order::memory_order_relaxed);
}
// static
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_);
}

View File

@ -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_;

View File

@ -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 =

View File

@ -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);
}

View File

@ -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());

View File

@ -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();

View File

@ -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);

View File

@ -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));
*data = allocated_bytes;
*size = d.size();
std::memcpy(allocated_metadata_bytes, d.metadata(), d.metadata_size());
CHECK(SetPermissions(page_allocator, allocated_metadata_bytes,
allocation_metadata_size, PageAllocator::kRead));
*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]);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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) {