Revert "[builtins] Remove off-heap builtins from the snapshot"

This reverts commit f1b1ec70a6.

Reason for revert: Tentative revert for https://logs.chromium.org/v/?s=chromium%2Fbb%2Fclient.v8.fyi%2FV8-Blink_Mac%2F13696%2F%2B%2Frecipes%2Fsteps%2Fwebkit_unit_tests%2F0%2Fstdout

Original change's description:
> [builtins] Remove off-heap builtins from the snapshot
> 
> This CL is the final major step towards shipping off-heap-safe builtins
> embedded into the binary.
> 
> Prior to snapshot serialization, we now:
> * create the embedded blob containing off-heap instruction streams,
> * use that to generate embedded.cc (containing embedded binary data),
> * replace off-heap-safe builtins with trampolines,
> * and serialize those into the final snapshot.
> 
> The new RelocInfo::OFF_HEAP_TARGET kind is used to fix up trampoline
> targets on deserialization.
> 
> Bug: v8:6666
> Change-Id: Ib07aea9e3bd7ecdec42291c1388b3a7453ea96ce
> Reviewed-on: https://chromium-review.googlesource.com/950775
> Commit-Queue: Jakob Gruber <jgruber@chromium.org>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Reviewed-by: Yang Guo <yangguo@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#51960}

TBR=yangguo@chromium.org,mstarzinger@chromium.org,jgruber@chromium.org

Change-Id: I58dd4bf9a99d37416855b48807150e1dd9ecd9e8
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:6666
Reviewed-on: https://chromium-review.googlesource.com/964363
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51962}
This commit is contained in:
Jakob Gruber 2018-03-15 14:25:03 +00:00 committed by Commit Bot
parent ef99ff6ed4
commit fda0d684c3
39 changed files with 157 additions and 412 deletions

View File

@ -73,8 +73,7 @@ Address RelocInfo::target_address() {
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsOffHeapTarget(rmode_));
rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
if (Assembler::IsMovW(Memory::int32_at(pc_))) {
return reinterpret_cast<Address>(pc_);
} else {
@ -152,11 +151,6 @@ void RelocInfo::set_target_runtime_entry(Address target,
set_target_address(target, write_barrier_mode, icache_flush_mode);
}
Address RelocInfo::target_off_heap_target() {
DCHECK(IsOffHeapTarget(rmode_));
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::WipeOut() {
DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
@ -181,8 +175,6 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
visitor->VisitInternalReference(host(), this);
} else if (RelocInfo::IsRuntimeEntry(mode)) {
visitor->VisitRuntimeEntry(host(), this);
} else if (RelocInfo::IsOffHeapTarget(mode)) {
visitor->VisitOffHeapTarget(host(), this);
}
}

View File

@ -1717,7 +1717,7 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
void MacroAssembler::JumpToInstructionStream(Address entry) {
mov(kOffHeapTrampolineRegister,
Operand(reinterpret_cast<int32_t>(entry), RelocInfo::OFF_HEAP_TARGET));
Operand(reinterpret_cast<int32_t>(entry), RelocInfo::NONE));
Jump(kOffHeapTrampolineRegister);
}

View File

@ -613,8 +613,7 @@ Address RelocInfo::target_address() {
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsOffHeapTarget(rmode_));
rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
return Assembler::target_pointer_address_at(pc_);
}
@ -683,11 +682,6 @@ void RelocInfo::set_target_runtime_entry(Address target,
}
}
Address RelocInfo::target_off_heap_target() {
DCHECK(IsOffHeapTarget(rmode_));
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::WipeOut() {
DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
@ -712,8 +706,6 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
visitor->VisitInternalReference(host(), this);
} else if (RelocInfo::IsRuntimeEntry(mode)) {
visitor->VisitRuntimeEntry(host(), this);
} else if (RelocInfo::IsOffHeapTarget(mode)) {
visitor->VisitOffHeapTarget(host(), this);
}
}

View File

@ -1760,8 +1760,7 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
}
void MacroAssembler::JumpToInstructionStream(Address entry) {
Mov(kOffHeapTrampolineRegister,
Operand(reinterpret_cast<uint64_t>(entry), RelocInfo::OFF_HEAP_TARGET));
Mov(kOffHeapTrampolineRegister, reinterpret_cast<uint64_t>(entry));
Br(kOffHeapTrampolineRegister);
}

View File

@ -38,7 +38,6 @@
#include "src/code-stubs.h"
#include "src/deoptimizer.h"
#include "src/disassembler.h"
#include "src/instruction-stream.h"
#include "src/isolate.h"
#include "src/ostreams.h"
#include "src/simulator.h" // For flushing instruction cache.
@ -521,8 +520,6 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
return "internal reference";
case INTERNAL_REFERENCE_ENCODED:
return "encoded internal reference";
case OFF_HEAP_TARGET:
return "off heap target";
case DEOPT_SCRIPT_OFFSET:
return "deopt script offset";
case DEOPT_INLINING_ID:
@ -624,12 +621,6 @@ void RelocInfo::Verify(Isolate* isolate) {
CHECK(target <= code->instruction_end());
break;
}
case OFF_HEAP_TARGET: {
Address addr = target_off_heap_target();
CHECK_NOT_NULL(addr);
CHECK_NOT_NULL(InstructionStream::TryLookupCode(isolate, addr));
break;
}
case RUNTIME_ENTRY:
case COMMENT:
case EXTERNAL_REFERENCE:

View File

@ -379,9 +379,6 @@ class RelocInfo {
// Encoded internal reference, used only on MIPS, MIPS64 and PPC.
INTERNAL_REFERENCE_ENCODED,
// An off-heap instruction stream target. See http://goo.gl/Z2HUiM.
OFF_HEAP_TARGET,
// Marks constant and veneer pools. Only used on ARM and ARM64.
// They use a custom noncompact encoding.
CONST_POOL,
@ -458,9 +455,6 @@ class RelocInfo {
static inline bool IsInternalReferenceEncoded(Mode mode) {
return mode == INTERNAL_REFERENCE_ENCODED;
}
static inline bool IsOffHeapTarget(Mode mode) {
return mode == OFF_HEAP_TARGET;
}
static inline bool IsNone(Mode mode) { return mode == NONE; }
static inline bool IsWasmContextReference(Mode mode) {
return mode == WASM_CONTEXT_REFERENCE;
@ -535,7 +529,6 @@ class RelocInfo {
Address target,
WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
INLINE(Address target_off_heap_target());
INLINE(Cell* target_cell());
INLINE(Handle<Cell> target_cell_handle());
INLINE(void set_target_cell(

View File

@ -202,7 +202,8 @@ bool Builtins::IsBuiltin(Code* code) {
// static
bool Builtins::IsOffHeapBuiltin(Code* code) {
#ifdef V8_EMBEDDED_BUILTINS
return Builtins::IsBuiltinId(code->builtin_index()) &&
return FLAG_stress_off_heap_code &&
Builtins::IsBuiltinId(code->builtin_index()) &&
Builtins::IsOffHeapSafe(code->builtin_index());
#else
return false;
@ -212,12 +213,6 @@ bool Builtins::IsOffHeapBuiltin(Code* code) {
// static
bool Builtins::IsLazy(int index) {
DCHECK(IsBuiltinId(index));
#ifdef V8_EMBEDDED_BUILTINS
// We don't want to lazy-deserialize off-heap builtins.
if (Builtins::IsOffHeapSafe(index)) return false;
#endif
// There are a couple of reasons that builtins can require eager-loading,
// i.e. deserialization at isolate creation instead of on-demand. For
// instance:
@ -649,7 +644,7 @@ bool Builtins::IsIsolateIndependent(int index) {
// static
bool Builtins::IsOffHeapSafe(int index) {
#if !defined(V8_EMBEDDED_BUILTINS) || !defined(V8_USE_SNAPSHOT)
#ifndef V8_EMBEDDED_BUILTINS
return false;
#else
DCHECK(IsBuiltinId(index));
@ -669,32 +664,6 @@ bool Builtins::IsTooShortForOffHeapTrampoline(int index) {
}
}
#ifdef V8_EMBEDDED_BUILTINS
// static
Handle<Code> Builtins::GenerateOffHeapTrampolineFor(Isolate* isolate,
Address off_heap_entry) {
DCHECK(isolate->serializer_enabled());
DCHECK_NOT_NULL(isolate->embedded_blob());
DCHECK_NE(0, isolate->embedded_blob_size());
constexpr size_t buffer_size = 256; // Enough to fit the single jmp.
byte buffer[buffer_size]; // NOLINT(runtime/arrays)
// Generate replacement code that simply tail-calls the off-heap code.
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
DCHECK(!masm.has_frame());
{
FrameScope scope(&masm, StackFrame::NONE);
masm.JumpToInstructionStream(off_heap_entry);
}
CodeDesc desc;
masm.GetCode(isolate, &desc);
return isolate->factory()->NewCode(desc, Code::BUILTIN, masm.CodeObject());
}
#endif // V8_EMBEDDED_BUILTINS
// static
Builtins::Kind Builtins::KindOf(int index) {
DCHECK(IsBuiltinId(index));

View File

@ -72,7 +72,7 @@ class Builtins {
Handle<Code> NewFunctionContext(ScopeType scope_type);
Handle<Code> JSConstructStubGeneric();
// Used by BuiltinDeserializer and CreateOffHeapTrampolines in isolate.cc.
// Used by BuiltinDeserializer.
void set_builtin(int index, HeapObject* builtin);
Code* builtin(int index) {
@ -160,14 +160,6 @@ class Builtins {
private:
Builtins();
#ifdef V8_EMBEDDED_BUILTINS
// Creates a trampoline code object that jumps to the given off-heap entry.
// The result should not be used directly, but only from the related Factory
// function.
static Handle<Code> GenerateOffHeapTrampolineFor(Isolate* isolate,
Address off_heap_entry);
#endif
static void Generate_CallFunction(MacroAssembler* masm,
ConvertReceiverMode mode);
@ -206,7 +198,6 @@ class Builtins {
Object* builtins_[builtin_count];
bool initialized_;
friend class Factory; // For GenerateOffHeapTrampolineFor.
friend class Isolate;
friend class SetupIsolateDelegate;

View File

@ -1856,36 +1856,6 @@ Handle<Code> Factory::NewCodeForDeserialization(uint32_t size) {
Code);
}
#ifdef V8_EMBEDDED_BUILTINS
Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
Address off_heap_entry) {
DCHECK(isolate()->serializer_enabled());
DCHECK_NOT_NULL(isolate()->embedded_blob());
DCHECK_NE(0, isolate()->embedded_blob_size());
DCHECK(Builtins::IsOffHeapBuiltin(*code));
Handle<Code> result =
Builtins::GenerateOffHeapTrampolineFor(isolate(), off_heap_entry);
// The trampoline code object must inherit specific flags from the original
// builtin (e.g. the safepoint-table offset). We set them manually here.
const int stack_slots = code->has_safepoint_info() ? code->stack_slots() : 0;
result->initialize_flags(code->kind(), code->has_unwinding_info(),
code->is_turbofanned(), stack_slots);
result->set_builtin_index(code->builtin_index());
result->set_has_tagged_params(code->has_tagged_params());
result->set_handler_table_offset(code->handler_table_offset());
result->code_data_container()->set_kind_specific_flags(
code->code_data_container()->kind_specific_flags());
if (code->has_safepoint_info()) {
result->set_safepoint_table_offset(code->safepoint_table_offset());
}
return result;
}
#endif
Handle<Code> Factory::CopyCode(Handle<Code> code) {
Handle<CodeDataContainer> data_container =
NewCodeDataContainer(code->code_data_container()->kind_specific_flags());

View File

@ -716,13 +716,6 @@ class V8_EXPORT_PRIVATE Factory final {
// given {size} argument specifies the size of the entire code object.
Handle<Code> NewCodeForDeserialization(uint32_t size);
#ifdef V8_EMBEDDED_BUILTINS
// Allocates a new code object and initializes it as the trampoline to the
// given off-heap entry point.
Handle<Code> NewOffHeapTrampolineFor(Handle<Code> code,
Address off_heap_entry);
#endif
Handle<Code> CopyCode(Handle<Code> code);
Handle<BytecodeArray> CopyBytecodeArray(Handle<BytecodeArray>);

View File

@ -6830,7 +6830,9 @@ bool Heap::GcSafeCodeContains(HeapObject* code, Address addr) {
Map* map = GcSafeMapOfCodeSpaceObject(code);
DCHECK(map == code->GetHeap()->code_map());
#ifdef V8_EMBEDDED_BUILTINS
if (InstructionStream::TryLookupCode(isolate(), addr) == code) return true;
if (FLAG_stress_off_heap_code) {
if (InstructionStream::TryLookupCode(isolate(), addr) == code) return true;
}
#endif
Address start = code->address();
Address end = code->address() + code->SizeFromMap(map);
@ -6839,8 +6841,10 @@ bool Heap::GcSafeCodeContains(HeapObject* code, Address addr) {
Code* Heap::GcSafeFindCodeForInnerPointer(Address inner_pointer) {
#ifdef V8_EMBEDDED_BUILTINS
Code* code = InstructionStream::TryLookupCode(isolate(), inner_pointer);
if (code != nullptr) return code;
if (FLAG_stress_off_heap_code) {
Code* code = InstructionStream::TryLookupCode(isolate(), inner_pointer);
if (code != nullptr) return code;
}
#endif
// Check if the inner pointer points into a large object chunk.

View File

@ -72,8 +72,7 @@ Address RelocInfo::target_address() {
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsOffHeapTarget(rmode_));
rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
return reinterpret_cast<Address>(pc_);
}
@ -145,11 +144,6 @@ void RelocInfo::set_target_runtime_entry(Address target,
}
}
Address RelocInfo::target_off_heap_target() {
DCHECK(IsOffHeapTarget(rmode_));
return Memory::Address_at(pc_);
}
void RelocInfo::WipeOut() {
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_)) {
@ -177,8 +171,6 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
visitor->VisitInternalReference(host(), this);
} else if (IsRuntimeEntry(mode)) {
visitor->VisitRuntimeEntry(host(), this);
} else if (RelocInfo::IsOffHeapTarget(mode)) {
visitor->VisitOffHeapTarget(host(), this);
}
}

View File

@ -848,7 +848,7 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
}
void MacroAssembler::JumpToInstructionStream(Address entry) {
mov(kOffHeapTrampolineRegister, Immediate(entry, RelocInfo::OFF_HEAP_TARGET));
mov(kOffHeapTrampolineRegister, Immediate(entry, RelocInfo::NONE));
jmp(kOffHeapTrampolineRegister);
}

View File

@ -24,6 +24,8 @@ bool InstructionStream::PcIsOffHeap(Isolate* isolate, Address pc) {
// static
Code* InstructionStream::TryLookupCode(Isolate* isolate, Address address) {
#ifdef V8_EMBEDDED_BUILTINS
DCHECK(FLAG_stress_off_heap_code);
if (!PcIsOffHeap(isolate, address)) return nullptr;
EmbeddedData d = EmbeddedData::FromBlob(isolate->embedded_blob(),
@ -50,35 +52,5 @@ Code* InstructionStream::TryLookupCode(Isolate* isolate, Address address) {
#endif
}
#ifdef V8_EMBEDDED_BUILTINS
// static
void InstructionStream::CreateOffHeapInstructionStream(Isolate* isolate,
uint8_t** data,
uint32_t* size) {
EmbeddedData d = EmbeddedData::FromIsolate(isolate);
const uint32_t page_size = static_cast<uint32_t>(AllocatePageSize());
const uint32_t allocated_size = RoundUp(d.size(), page_size);
uint8_t* allocated_bytes = static_cast<uint8_t*>(
AllocatePages(GetRandomMmapAddr(), allocated_size, page_size,
PageAllocator::kReadWrite));
CHECK_NOT_NULL(allocated_bytes);
std::memcpy(allocated_bytes, d.data(), d.size());
CHECK(SetPermissions(allocated_bytes, allocated_size,
PageAllocator::kReadExecute));
*data = allocated_bytes;
*size = allocated_size;
}
// static
void InstructionStream::FreeOffHeapInstructionStream(uint8_t* data,
uint32_t size) {
CHECK(FreePages(data, size));
}
#endif // V8_EMBEDDED_BUILTINS
} // namespace internal
} // namespace v8

View File

@ -23,16 +23,6 @@ class InstructionStream final : public AllStatic {
// Returns the corresponding Code object if it exists, and nullptr otherwise.
static Code* TryLookupCode(Isolate* isolate, Address address);
#ifdef V8_EMBEDDED_BUILTINS
// During snapshot creation, we first create an executable off-heap area
// 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);
#endif
};
} // namespace internal

View File

@ -70,8 +70,11 @@ base::Atomic32 ThreadId::highest_thread_id_ = 0;
extern const uint8_t* DefaultEmbeddedBlob();
extern uint32_t DefaultEmbeddedBlobSize();
const uint8_t* Isolate::embedded_blob() const { return embedded_blob_; }
uint32_t Isolate::embedded_blob_size() const { return embedded_blob_size_; }
const uint8_t* Isolate::embedded_blob() const { return DefaultEmbeddedBlob(); }
uint32_t Isolate::embedded_blob_size() const {
return DefaultEmbeddedBlobSize();
}
#endif
int ThreadId::AllocateThreadId() {
@ -2648,14 +2651,6 @@ void Isolate::Deinit() {
heap_.TearDown();
logger_->TearDown();
#ifdef V8_EMBEDDED_BUILTINS
if (DefaultEmbeddedBlob() == nullptr && embedded_blob() != nullptr) {
// We own the embedded blob. Free it.
uint8_t* data = const_cast<uint8_t*>(embedded_blob_);
InstructionStream::FreeOffHeapInstructionStream(data, embedded_blob_size_);
}
#endif
delete interpreter_;
interpreter_ = nullptr;
@ -2823,14 +2818,70 @@ void PrintBuiltinSizes(Isolate* isolate) {
}
#ifdef V8_EMBEDDED_BUILTINS
void CreateOffHeapTrampolines(Isolate* isolate) {
DCHECK(isolate->serializer_enabled());
void ChangeToOffHeapTrampoline(Isolate* isolate, Handle<Code> code,
const uint8_t* entry) {
DCHECK(Builtins::IsOffHeapSafe(code->builtin_index()));
HandleScope scope(isolate);
constexpr size_t buffer_size = 256; // Enough to fit the single jmp.
byte buffer[buffer_size]; // NOLINT(runtime/arrays)
// Generate replacement code that simply tail-calls the off-heap code.
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
DCHECK(!masm.has_frame());
{
FrameScope scope(&masm, StackFrame::NONE);
masm.JumpToInstructionStream(
reinterpret_cast<Address>(const_cast<uint8_t*>(entry)));
}
CodeDesc desc;
masm.GetCode(isolate, &desc);
// Hack in an empty reloc info to satisfy the GC.
DCHECK_EQ(0, desc.reloc_size);
Handle<ByteArray> reloc_info =
isolate->factory()->NewByteArray(desc.reloc_size, TENURED);
code->set_relocation_info(*reloc_info);
// Overwrites the original code.
CHECK_LE(desc.instr_size, code->instruction_size());
CHECK_IMPLIES(code->has_safepoint_info(),
desc.instr_size <= code->safepoint_table_offset());
code->CopyFrom(desc);
// TODO(jgruber): CopyFrom isn't intended to overwrite existing code, and
// doesn't update things like instruction_size. The result is a code object in
// which the first instructions are overwritten while the rest remain intact
// (but are never executed). That's fine for our current purposes, just
// manually zero the trailing part.
int code_instruction_size = code->instruction_size();
DCHECK_LE(desc.instr_size, code_instruction_size);
byte* trailing_instruction_start =
code->instruction_start() + desc.instr_size;
if (code->has_safepoint_info()) {
CHECK_LE(code->safepoint_table_offset(), code->instruction_size());
code_instruction_size = code->safepoint_table_offset();
CHECK_LE(desc.instr_size, code_instruction_size);
}
size_t trailing_instruction_size = code_instruction_size - desc.instr_size;
std::memset(trailing_instruction_start, 0, trailing_instruction_size);
}
void CreateOnHeapTrampolines(Isolate* isolate) {
DCHECK(FLAG_stress_off_heap_code);
DCHECK(!isolate->serializer_enabled());
DCHECK_NOT_NULL(isolate->embedded_blob());
DCHECK_NE(0, isolate->embedded_blob_size());
HandleScope scope(isolate);
Builtins* builtins = isolate->builtins();
// Lazy deserialization would defeat our off-heap stress test (we'd
// deserialize later without moving off-heap), so force eager
// deserialization.
Snapshot::EnsureAllBuiltinsAreDeserialized(isolate);
EmbeddedData d = EmbeddedData::FromBlob(isolate->embedded_blob(),
isolate->embedded_blob_size());
@ -2839,49 +2890,22 @@ void CreateOffHeapTrampolines(Isolate* isolate) {
if (!Builtins::IsOffHeapSafe(i)) continue;
const uint8_t* instruction_start = d.InstructionStartOfBuiltin(i);
Handle<Code> trampoline = isolate->factory()->NewOffHeapTrampolineFor(
builtins->builtin_handle(i), const_cast<Address>(instruction_start));
// Note that references to the old, on-heap code objects may still exist on
// the heap. This is fine for the sake of serialization, as serialization
// will replace all of them with a builtin reference which is later
// deserialized to point to the object within the builtins table.
//
// From this point onwards, some builtin code objects may be unreachable and
// thus collected by the GC.
builtins->set_builtin(i, *trampoline);
// TODO(jgruber,v8:6666): Create fresh trampolines instead of rewriting
// existing ones. This could happen prior to serialization or
// post-deserialization.
Handle<Code> code(builtins->builtin(i));
ChangeToOffHeapTrampoline(isolate, code, instruction_start);
if (isolate->logger()->is_logging_code_events() ||
isolate->is_profiling()) {
isolate->logger()->LogCodeObject(*trampoline);
isolate->logger()->LogCodeObject(*code);
}
}
}
#endif // V8_EMBEDDED_BUILTINS
} // namespace
#ifdef V8_EMBEDDED_BUILTINS
void Isolate::PrepareEmbeddedBlobForSerialization() {
// When preparing the embedded blob, ensure it doesn't exist yet.
DCHECK_NULL(embedded_blob());
DCHECK_NULL(DefaultEmbeddedBlob());
DCHECK(serializer_enabled());
// The isolate takes ownership of this pointer into an executable mmap'd
// area. We muck around with const-casts because the standard use-case in
// shipping builds is for embedded_blob_ to point into a read-only
// .text-embedded section.
uint8_t* data;
uint32_t size;
InstructionStream::CreateOffHeapInstructionStream(this, &data, &size);
embedded_blob_ = const_cast<const uint8_t*>(data);
embedded_blob_size_ = size;
CreateOffHeapTrampolines(this);
}
#endif // V8_EMBEDDED_BUILTINS
bool Isolate::Init(StartupDeserializer* des) {
TRACE_ISOLATE(init);
@ -2935,11 +2959,6 @@ bool Isolate::Init(StartupDeserializer* des) {
compiler_dispatcher_ =
new CompilerDispatcher(this, V8::GetCurrentPlatform(), FLAG_stack_size);
#ifdef V8_EMBEDDED_BUILTINS
embedded_blob_ = DefaultEmbeddedBlob();
embedded_blob_size_ = DefaultEmbeddedBlobSize();
#endif
// Enable logging before setting up the heap
logger_->SetUp(this);
@ -3047,6 +3066,14 @@ bool Isolate::Init(StartupDeserializer* des) {
if (FLAG_print_builtin_size) PrintBuiltinSizes(this);
#ifdef V8_EMBEDDED_BUILTINS
if (FLAG_stress_off_heap_code && !serializer_enabled() &&
embedded_blob() != nullptr) {
// Create the on-heap trampolines that jump into embedded code.
CreateOnHeapTrampolines(this);
}
#endif
// Finish initialization of ThreadLocal after deserialization is done.
clear_pending_exception();
clear_pending_message();

View File

@ -1247,11 +1247,6 @@ class Isolate {
}
#ifdef V8_EMBEDDED_BUILTINS
// Called only prior to serialization.
// This function copies off-heap-safe builtins off the heap, creates off-heap
// trampolines, and sets up this isolate's embedded blob.
void PrepareEmbeddedBlobForSerialization();
BuiltinsConstantsTableBuilder* builtins_constants_table_builder() const {
return builtins_constants_table_builder_;
}
@ -1633,9 +1628,6 @@ class Isolate {
// Used during builtins compilation to build the builtins constants table,
// which is stored on the root list prior to serialization.
BuiltinsConstantsTableBuilder* builtins_constants_table_builder_ = nullptr;
const uint8_t* embedded_blob_ = nullptr;
uint32_t embedded_blob_size_ = 0;
#endif
v8::ArrayBuffer::Allocator* array_buffer_allocator_;

View File

@ -82,8 +82,7 @@ Address RelocInfo::target_address() {
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsOffHeapTarget(rmode_));
rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
// Read the address of the word containing the target_address in an
// instruction stream.
// The only architecture-independent user of this function is the serializer.
@ -255,11 +254,6 @@ void RelocInfo::set_target_runtime_entry(Address target,
set_target_address(target, write_barrier_mode, icache_flush_mode);
}
Address RelocInfo::target_off_heap_target() {
DCHECK(IsOffHeapTarget(rmode_));
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::WipeOut() {
DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
@ -287,8 +281,6 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
visitor->VisitInternalReference(host(), this);
} else if (RelocInfo::IsRuntimeEntry(mode)) {
visitor->VisitRuntimeEntry(host(), this);
} else if (RelocInfo::IsOffHeapTarget(mode)) {
visitor->VisitOffHeapTarget(host(), this);
}
}

View File

@ -4550,7 +4550,7 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
void MacroAssembler::JumpToInstructionStream(Address entry) {
li(kOffHeapTrampolineRegister,
Operand(reinterpret_cast<int32_t>(entry), RelocInfo::OFF_HEAP_TARGET));
Operand(reinterpret_cast<int32_t>(entry), RelocInfo::NONE));
Jump(kOffHeapTrampolineRegister);
}

View File

@ -80,9 +80,10 @@ Address RelocInfo::target_address() {
}
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsOffHeapTarget(rmode_));
DCHECK(IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) ||
rmode_ == EMBEDDED_OBJECT ||
rmode_ == EXTERNAL_REFERENCE);
// Read the address of the word containing the target_address in an
// instruction stream.
// The only architecture-independent user of this function is the serializer.
@ -221,11 +222,6 @@ void RelocInfo::set_target_runtime_entry(Address target,
set_target_address(target, write_barrier_mode, icache_flush_mode);
}
Address RelocInfo::target_off_heap_target() {
DCHECK(IsOffHeapTarget(rmode_));
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::WipeOut() {
DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
@ -253,8 +249,6 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
visitor->VisitInternalReference(host(), this);
} else if (RelocInfo::IsRuntimeEntry(mode)) {
visitor->VisitRuntimeEntry(host(), this);
} else if (RelocInfo::IsOffHeapTarget(mode)) {
visitor->VisitOffHeapTarget(host(), this);
}
}

View File

@ -4849,7 +4849,7 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
void MacroAssembler::JumpToInstructionStream(Address entry) {
li(kOffHeapTrampolineRegister,
Operand(reinterpret_cast<uint64_t>(entry), RelocInfo::OFF_HEAP_TARGET));
Operand(reinterpret_cast<uint64_t>(entry), RelocInfo::NONE));
Jump(kOffHeapTrampolineRegister);
}

View File

@ -414,7 +414,6 @@ class Code::BodyDescriptor final : public BodyDescriptorBase {
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
// GC does not visit data/code in the header and in the body directly.

View File

@ -13970,7 +13970,6 @@ SafepointEntry Code::GetSafepointEntry(Address pc) {
int Code::OffHeapInstructionSize() {
DCHECK(Builtins::IsOffHeapBuiltin(this));
Isolate* isolate = GetIsolate();
if (isolate->embedded_blob() == nullptr) return instruction_size();
EmbeddedData d = EmbeddedData::FromBlob(isolate->embedded_blob(),
isolate->embedded_blob_size());
return d.InstructionSizeOfBuiltin(builtin_index());
@ -13979,7 +13978,6 @@ int Code::OffHeapInstructionSize() {
Address Code::OffHeapInstructionStart() {
DCHECK(Builtins::IsOffHeapBuiltin(this));
Isolate* isolate = GetIsolate();
if (isolate->embedded_blob() == nullptr) return instruction_start();
EmbeddedData d = EmbeddedData::FromBlob(isolate->embedded_blob(),
isolate->embedded_blob_size());
return reinterpret_cast<Address>(
@ -13989,7 +13987,6 @@ Address Code::OffHeapInstructionStart() {
Address Code::OffHeapInstructionEnd() {
DCHECK(Builtins::IsOffHeapBuiltin(this));
Isolate* isolate = GetIsolate();
if (isolate->embedded_blob() == nullptr) return instruction_end();
EmbeddedData d = EmbeddedData::FromBlob(isolate->embedded_blob(),
isolate->embedded_blob_size());
return reinterpret_cast<Address>(
@ -14141,7 +14138,6 @@ bool Code::IsProcessIndependent() {
all_real_modes_mask & ~RelocInfo::ModeMask(RelocInfo::COMMENT) &
~RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) &
~RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) &
~RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) &
~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
~RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
STATIC_ASSERT(RelocInfo::LAST_REAL_RELOC_MODE == RelocInfo::VENEER_POOL);

View File

@ -91,8 +91,7 @@ Address RelocInfo::target_address() {
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsOffHeapTarget(rmode_));
rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
if (FLAG_enable_embedded_constant_pool &&
Assembler::IsConstantPoolLoadStart(pc_)) {
@ -207,11 +206,6 @@ void RelocInfo::set_target_runtime_entry(Address target,
set_target_address(target, write_barrier_mode, icache_flush_mode);
}
Address RelocInfo::target_off_heap_target() {
DCHECK(IsOffHeapTarget(rmode_));
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::WipeOut() {
DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
@ -243,8 +237,6 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
visitor->VisitInternalReference(host(), this);
} else if (IsRuntimeEntry(mode)) {
visitor->VisitRuntimeEntry(host(), this);
} else if (RelocInfo::IsOffHeapTarget(mode)) {
visitor->VisitOffHeapTarget(host(), this);
}
}

View File

@ -1617,7 +1617,7 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
void MacroAssembler::JumpToInstructionStream(Address entry) {
mov(kOffHeapTrampolineRegister,
Operand(reinterpret_cast<intptr_t>(entry), RelocInfo::OFF_HEAP_TARGET));
Operand(reinterpret_cast<intptr_t>(entry), RelocInfo::NONE));
Jump(kOffHeapTrampolineRegister);
}

View File

@ -98,8 +98,7 @@ Address RelocInfo::target_address() {
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsOffHeapTarget(rmode_));
rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
// Read the address of the word containing the target_address in an
// instruction stream.
@ -180,11 +179,6 @@ Address RelocInfo::target_runtime_entry(Assembler* origin) {
return target_address();
}
Address RelocInfo::target_off_heap_target() {
DCHECK(IsOffHeapTarget(rmode_));
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::set_target_runtime_entry(Address target,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
@ -223,8 +217,6 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
visitor->VisitInternalReference(host(), this);
} else if (IsRuntimeEntry(mode)) {
visitor->VisitRuntimeEntry(host(), this);
} else if (RelocInfo::IsOffHeapTarget(mode)) {
visitor->VisitOffHeapTarget(host(), this);
}
}

View File

@ -1524,8 +1524,7 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
}
void MacroAssembler::JumpToInstructionStream(Address entry) {
mov(kOffHeapTrampolineRegister,
Operand(reinterpret_cast<intptr_t>(entry), RelocInfo::OFF_HEAP_TARGET));
mov(kOffHeapTrampolineRegister, Operand(reinterpret_cast<intptr_t>(entry)));
Jump(kOffHeapTrampolineRegister);
}

View File

@ -10,7 +10,6 @@
#include "src/objects/string.h"
#include "src/snapshot/builtin-deserializer-allocator.h"
#include "src/snapshot/natives.h"
#include "src/snapshot/snapshot.h"
namespace v8 {
namespace internal {
@ -492,28 +491,6 @@ bool Deserializer<AllocatorT>::ReadData(Object** current, Object** limit,
break;
}
case kOffHeapTarget: {
#ifdef V8_EMBEDDED_BUILTINS
int skip = source_.GetInt();
int builtin_index = source_.GetInt();
DCHECK(Builtins::IsBuiltinId(builtin_index));
current = reinterpret_cast<Object**>(
reinterpret_cast<Address>(current) + skip);
EmbeddedData d = EmbeddedData::FromBlob(isolate->embedded_blob(),
isolate->embedded_blob_size());
const uint8_t* address = d.InstructionStartOfBuiltin(builtin_index);
Object* o = reinterpret_cast<Object*>(const_cast<uint8_t*>(address));
UnalignedCopy(current, &o);
current++;
#else
UNREACHABLE();
#endif
break;
}
case kNop:
break;

View File

@ -16,7 +16,6 @@
#include "src/snapshot/snapshot.h"
#include "src/snapshot/startup-serializer.h"
namespace {
class SnapshotWriter {
public:
SnapshotWriter()
@ -306,56 +305,6 @@ v8::StartupData CreateSnapshotDataBlob(v8::SnapshotCreator* snapshot_creator,
return result;
}
v8::StartupData WarmUpSnapshotDataBlob(v8::SnapshotCreator* snapshot_creator,
const char* warmup_source) {
CHECK_NOT_NULL(warmup_source);
// Use following steps to create a warmed up snapshot blob from a cold one:
// - Create a new isolate from the cold snapshot.
// - Create a new context to run the warmup script. This will trigger
// compilation of executed functions.
// - Create a new context. This context will be unpolluted.
// - Serialize the isolate and the second context into a new snapshot blob.
v8::StartupData result = {nullptr, 0};
v8::base::ElapsedTimer timer;
timer.Start();
{
v8::Isolate* isolate = snapshot_creator->GetIsolate();
{
v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) {
return result;
}
}
{
v8::HandleScope handle_scope(isolate);
isolate->ContextDisposedNotification(false);
v8::Local<v8::Context> context = v8::Context::New(isolate);
snapshot_creator->SetDefaultContext(context);
}
result = snapshot_creator->CreateBlob(
v8::SnapshotCreator::FunctionCodeHandling::kKeep);
}
if (i::FLAG_profile_deserialization) {
i::PrintF("Warming up snapshot took %0.3f ms\n",
timer.Elapsed().InMillisecondsF());
}
timer.Stop();
return result;
}
#ifdef V8_EMBEDDED_BUILTINS
void WriteEmbeddedFile(v8::SnapshotCreator* creator, SnapshotWriter* writer) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(creator->GetIsolate());
isolate->PrepareEmbeddedBlobForSerialization();
i::EmbeddedData embedded_blob = i::EmbeddedData::FromBlob(
isolate->embedded_blob(), isolate->embedded_blob_size());
writer->WriteEmbedded(&embedded_blob);
}
#endif // V8_EMBEDDED_BUILTINS
} // namespace
int main(int argc, char** argv) {
// Make mksnapshot runs predictable to create reproducible snapshots.
i::FLAG_predictable = true;
@ -384,33 +333,31 @@ int main(int argc, char** argv) {
if (i::FLAG_embedded_src) writer.SetEmbeddedFile(i::FLAG_embedded_src);
#endif
std::unique_ptr<char> embed_script(
GetExtraCode(argc >= 2 ? argv[1] : nullptr, "embedding"));
std::unique_ptr<char> warmup_script(
GetExtraCode(argc >= 3 ? argv[2] : nullptr, "warm up"));
v8::StartupData blob;
{
char* embed_script =
GetExtraCode(argc >= 2 ? argv[1] : nullptr, "embedding");
v8::SnapshotCreator snapshot_creator;
blob = CreateSnapshotDataBlob(&snapshot_creator, embed_script);
#ifdef V8_EMBEDDED_BUILTINS
// This process is a bit tricky since we might go on to make a second
// snapshot if a warmup script is passed. In that case, create the first
// snapshot without off-heap trampolines and only move code off-heap for
// the warmed-up snapshot.
if (!warmup_script) WriteEmbeddedFile(&snapshot_creator, &writer);
i::Isolate* isolate =
reinterpret_cast<i::Isolate*>(snapshot_creator.GetIsolate());
i::EmbeddedData embedded_blob = i::Snapshot::CreateEmbeddedBlob(isolate);
writer.WriteEmbedded(&embedded_blob);
delete[] embedded_blob.data();
#endif
blob = CreateSnapshotDataBlob(&snapshot_creator, embed_script.get());
delete[] embed_script;
}
char* warmup_script =
GetExtraCode(argc >= 3 ? argv[2] : nullptr, "warm up");
if (warmup_script) {
CHECK(blob.raw_size > 0 && blob.data != nullptr);
v8::StartupData cold = blob;
v8::SnapshotCreator snapshot_creator(nullptr, &cold);
#ifdef V8_EMBEDDED_BUILTINS
WriteEmbeddedFile(&snapshot_creator, &writer);
#endif
blob = WarmUpSnapshotDataBlob(&snapshot_creator, warmup_script.get());
blob = v8::V8::WarmUpSnapshotDataBlob(cold, warmup_script);
delete[] cold.data;
delete[] warmup_script;
}
CHECK(blob.data);

View File

@ -132,6 +132,7 @@ class SerializerDeserializer : public RootVisitor {
V(0x7c) \
V(0x7d) \
V(0x7e) \
V(0x7f) \
V(0xf0) \
V(0xf1) \
V(0xf2) \
@ -239,9 +240,6 @@ class SerializerDeserializer : public RootVisitor {
// Used to encode external referenced provided through the API.
static const int kApiReference = 0x37;
// Encodes an off-heap instruction stream target.
static const int kOffHeapTarget = 0x7f;
// 8 hot (recently seen or back-referenced) objects with optional skip.
static const int kNumberOfHotObjects = 8;
STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);

View File

@ -10,7 +10,6 @@
#include "src/objects/map.h"
#include "src/snapshot/builtin-serializer-allocator.h"
#include "src/snapshot/natives.h"
#include "src/snapshot/snapshot.h"
namespace v8 {
namespace internal {
@ -831,29 +830,6 @@ void Serializer<AllocatorT>::ObjectSerializer::VisitRuntimeEntry(
bytes_processed_so_far_ += rinfo->target_address_size();
}
template <class AllocatorT>
void Serializer<AllocatorT>::ObjectSerializer::VisitOffHeapTarget(
Code* host, RelocInfo* rinfo) {
#ifdef V8_EMBEDDED_BUILTINS
{
STATIC_ASSERT(EmbeddedData::kTableSize == Builtins::builtin_count);
CHECK(Builtins::IsOffHeapBuiltin(host));
Address addr = rinfo->target_off_heap_target();
CHECK_NOT_NULL(addr);
CHECK_NOT_NULL(
InstructionStream::TryLookupCode(serializer_->isolate(), addr));
}
int skip = SkipTo(rinfo->target_address_address());
sink_->Put(kOffHeapTarget, "OffHeapTarget");
sink_->PutInt(skip, "SkipB4OffHeapTarget");
sink_->PutInt(host->builtin_index(), "builtin index");
bytes_processed_so_far_ += kPointerSize;
#else
UNREACHABLE();
#endif
}
template <class AllocatorT>
void Serializer<AllocatorT>::ObjectSerializer::VisitCodeTarget(
Code* host, RelocInfo* rinfo) {

View File

@ -305,7 +305,6 @@ class Serializer<AllocatorT>::ObjectSerializer : public ObjectVisitor {
void VisitInternalReference(Code* host, RelocInfo* rinfo) override;
void VisitCodeTarget(Code* host, RelocInfo* target) override;
void VisitRuntimeEntry(Code* host, RelocInfo* reloc) override;
void VisitOffHeapTarget(Code* host, RelocInfo* target) override;
private:
void SerializePrologue(AllocationSpace space, int size, Map* map);

View File

@ -399,8 +399,6 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
}
EmbeddedData EmbeddedData::FromBlob(const uint8_t* data, uint32_t size) {
DCHECK_NOT_NULL(data);
DCHECK_LT(0, size);
return {data, size};
}
@ -418,6 +416,12 @@ uint32_t EmbeddedData::InstructionSizeOfBuiltin(int i) const {
const uint32_t* lengths = Lengths();
return lengths[i];
}
// static
EmbeddedData Snapshot::CreateEmbeddedBlob(Isolate* isolate) {
DisallowHeapAllocation no_gc;
return EmbeddedData::FromIsolate(isolate);
}
#endif
uint32_t Snapshot::ExtractNumContexts(const v8::StartupData* data) {

View File

@ -177,6 +177,10 @@ class Snapshot : public AllStatic {
const std::vector<SnapshotData*>& context_snapshots,
bool can_be_rehashed);
#ifdef V8_EMBEDDED_BUILTINS
static EmbeddedData CreateEmbeddedBlob(Isolate* isolate);
#endif
#ifdef DEBUG
static bool SnapshotIsValid(const v8::StartupData* snapshot_blob);
#endif // DEBUG

View File

@ -119,9 +119,6 @@ class ObjectVisitor BASE_EMBEDDED {
// Visits an (encoded) internal reference.
virtual void VisitInternalReference(Code* host, RelocInfo* rinfo) {}
// Visits an off-heap target in the instruction stream.
virtual void VisitOffHeapTarget(Code* host, RelocInfo* rinfo) {}
};
} // namespace internal

View File

@ -303,8 +303,7 @@ Address RelocInfo::target_address() {
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsOffHeapTarget(rmode_));
rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
return reinterpret_cast<Address>(pc_);
}
@ -384,11 +383,6 @@ void RelocInfo::set_target_runtime_entry(Address target,
}
}
Address RelocInfo::target_off_heap_target() {
DCHECK(IsOffHeapTarget(rmode_));
return Memory::Address_at(pc_);
}
void RelocInfo::WipeOut() {
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_)) {
@ -416,8 +410,6 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
visitor->VisitInternalReference(host(), this);
} else if (RelocInfo::IsRuntimeEntry(mode)) {
visitor->VisitRuntimeEntry(host(), this);
} else if (RelocInfo::IsOffHeapTarget(mode)) {
visitor->VisitOffHeapTarget(host(), this);
}
}

View File

@ -1367,7 +1367,7 @@ void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
}
void MacroAssembler::JumpToInstructionStream(Address entry) {
Move(kOffHeapTrampolineRegister, entry, RelocInfo::OFF_HEAP_TARGET);
Move(kOffHeapTrampolineRegister, entry, RelocInfo::NONE);
jmp(kOffHeapTrampolineRegister);
}

View File

@ -53,7 +53,6 @@ UNINITIALIZED_TEST(VerifyBuiltinsIsolateIndependence) {
all_real_modes_mask & ~RelocInfo::ModeMask(RelocInfo::COMMENT) &
~RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) &
~RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) &
~RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) &
~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
~RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
STATIC_ASSERT(RelocInfo::LAST_REAL_RELOC_MODE == RelocInfo::VENEER_POOL);

View File

@ -3324,5 +3324,26 @@ TEST(SerializationMemoryStats) {
delete[] blob.data;
}
TEST(BuiltinsHaveBuiltinIdForLazyDeserialization) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
CHECK(Builtins::IsLazy(Builtins::kRegExpPrototypeExec));
CHECK_EQ(Builtins::kRegExpPrototypeExec,
isolate->regexp_exec_function()
->shared()
->lazy_deserialization_builtin_id());
CHECK(Builtins::IsLazy(Builtins::kAsyncIteratorValueUnwrap));
CHECK_EQ(Builtins::kAsyncIteratorValueUnwrap,
isolate->async_iterator_value_unwrap_shared_fun()
->lazy_deserialization_builtin_id());
CHECK(!Builtins::IsLazy(Builtins::kIllegal));
CHECK(!isolate->opaque_reference_function()
->shared()
->HasLazyDeserializationBuiltinId());
}
} // namespace internal
} // namespace v8