[code] Remove the is_off_heap_trampoline bit
.. which no longer makes sense in today's code base. This was originally introduced to distinguish Code objects containing the actual instruction stream (= all non-builtin Code objects) from Code objects only containing a trampoline with a `jmp` to the .text section (= where instruction streams for embedded builtins are located). Today, trampoline code no longer exists; rename the predicate to `has_instruction_stream`, where has_instruction_stream == !is_off_heap_trampoline Bug: v8:13654 Fixed: v8:13698 Change-Id: I78be1cee2e045c1944486b8a54a03eb9d1ce0c27 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4205921 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Commit-Queue: Jakob Linke <jgruber@chromium.org> Auto-Submit: Jakob Linke <jgruber@chromium.org> Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> Cr-Commit-Position: refs/heads/main@{#85579}
This commit is contained in:
parent
df83719d4f
commit
ac99619606
@ -313,7 +313,7 @@ void Builtins::InitializeIsolateDataTables(Isolate* isolate) {
|
||||
// The entry table.
|
||||
for (Builtin i = Builtins::kFirst; i <= Builtins::kLast; ++i) {
|
||||
DCHECK(Builtins::IsBuiltinId(isolate->builtins()->code(i).builtin_id()));
|
||||
DCHECK(isolate->builtins()->code(i).is_off_heap_trampoline());
|
||||
DCHECK(!isolate->builtins()->code(i).has_instruction_stream());
|
||||
isolate_data->builtin_entry_table()[ToInt(i)] =
|
||||
embedded_data.InstructionStartOfBuiltin(i);
|
||||
}
|
||||
|
@ -2293,7 +2293,7 @@ unsigned InstructionStreamRef::GetInlinedBytecodeSize() const {
|
||||
|
||||
unsigned CodeRef::GetInlinedBytecodeSize() const {
|
||||
Code code = *object();
|
||||
if (code.is_off_heap_trampoline()) {
|
||||
if (!code.has_instruction_stream()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1095,12 +1095,6 @@ void Code::CodeVerify(Isolate* isolate) {
|
||||
InstructionStream istream = instruction_stream();
|
||||
CHECK_EQ(istream.kind(), kind());
|
||||
CHECK_EQ(istream.builtin_id(), builtin_id());
|
||||
// When v8_flags.interpreted_frames_native_stack is enabled each
|
||||
// interpreted function gets its own copy of the
|
||||
// InterpreterEntryTrampoline. Thus, there could be InstructionStream'ful
|
||||
// builtins.
|
||||
CHECK_IMPLIES(isolate->embedded_blob_code() && is_off_heap_trampoline(),
|
||||
builtin_id() == Builtin::kInterpreterEntryTrampoline);
|
||||
CHECK_EQ(istream.code(kAcquireLoad), *this);
|
||||
|
||||
// Ensure the cached code entry point corresponds to the InstructionStream
|
||||
|
@ -1810,13 +1810,12 @@ void Code::CodePrint(std::ostream& os) {
|
||||
if (is_builtin()) {
|
||||
os << "\n - builtin: " << Builtins::name(builtin_id());
|
||||
}
|
||||
os << "\n - is_off_heap_trampoline: " << is_off_heap_trampoline();
|
||||
os << "\n - instruction_stream: " << Brief(raw_instruction_stream());
|
||||
os << "\n - code_entry_point: "
|
||||
<< reinterpret_cast<void*>(code_entry_point());
|
||||
os << "\n - kind_specific_flags: " << kind_specific_flags(kRelaxedLoad);
|
||||
os << "\n";
|
||||
if (!is_off_heap_trampoline()) {
|
||||
if (has_instruction_stream()) {
|
||||
instruction_stream().Print(os);
|
||||
}
|
||||
}
|
||||
|
@ -582,7 +582,7 @@ Code StackFrame::LookupCode() const {
|
||||
void StackFrame::IteratePc(RootVisitor* v, Address* pc_address,
|
||||
Address* constant_pool_address,
|
||||
GcSafeCode holder) const {
|
||||
if (holder.is_off_heap_trampoline()) {
|
||||
if (!holder.has_instruction_stream()) {
|
||||
// The embedded builtins are immovable so there's no need to update PCs on
|
||||
// the stack. Just visit the Code object.
|
||||
Object code = holder.UnsafeCastToCode();
|
||||
@ -590,9 +590,6 @@ void StackFrame::IteratePc(RootVisitor* v, Address* pc_address,
|
||||
return;
|
||||
}
|
||||
|
||||
// .. because we access e.g. raw_instruction_start() below.
|
||||
DCHECK(!holder.is_off_heap_trampoline());
|
||||
|
||||
InstructionStream unsafe_istream = InstructionStream::unchecked_cast(
|
||||
holder.UnsafeCastToCode().raw_instruction_stream());
|
||||
|
||||
|
@ -460,18 +460,9 @@ size_t Isolate::HashIsolateForEmbeddedBlob() {
|
||||
Code::kUnalignedSize);
|
||||
constexpr int kStartOffset = Code::kFlagsOffset;
|
||||
|
||||
// |is_off_heap_trampoline| is false during builtins compilation (since
|
||||
// the builtins are not trampolines yet) but it's true for off-heap
|
||||
// builtin trampolines. The rest of the data fields should be the same.
|
||||
// So we temporarily set |is_off_heap_trampoline| to true during hash
|
||||
// computation.
|
||||
bool is_off_heap_trampoline_sav = code.is_off_heap_trampoline();
|
||||
code.set_is_off_heap_trampoline_for_hash(true);
|
||||
|
||||
for (int j = kStartOffset; j < Code::kUnalignedSize; j++) {
|
||||
hash = base::hash_combine(hash, size_t{code_ptr[j]});
|
||||
}
|
||||
code.set_is_off_heap_trampoline_for_hash(is_off_heap_trampoline_sav);
|
||||
}
|
||||
|
||||
// The builtins constants table is also tightly tied to embedded builtins.
|
||||
|
@ -117,9 +117,7 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
|
||||
code = factory->NewCode(0, AllocationType::kOld);
|
||||
}
|
||||
|
||||
static constexpr bool kIsNotOffHeapTrampoline = false;
|
||||
code->initialize_flags(kind_, builtin_, is_turbofanned_,
|
||||
kIsNotOffHeapTrampoline);
|
||||
code->initialize_flags(kind_, builtin_, is_turbofanned_);
|
||||
code->set_kind_specific_flags(kind_specific_flags_, kRelaxedStore);
|
||||
|
||||
// Basic block profiling data for builtins is stored in the JS heap rather
|
||||
@ -160,8 +158,7 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
|
||||
raw_istream.set_raw_instruction_size(code_desc_.instruction_size());
|
||||
raw_istream.set_raw_metadata_size(code_desc_.metadata_size());
|
||||
raw_istream.set_relocation_info(*reloc_info);
|
||||
raw_istream.initialize_flags(kind_, is_turbofanned_, stack_slots_,
|
||||
kIsNotOffHeapTrampoline);
|
||||
raw_istream.initialize_flags(kind_, is_turbofanned_, stack_slots_);
|
||||
raw_istream.set_builtin_id(builtin_);
|
||||
// This might impact direct concurrent reads from TF if we are resetting
|
||||
// this field. We currently assume it's immutable thus a relaxed read (after
|
||||
@ -2489,10 +2486,8 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
|
||||
const int no_flags = 0;
|
||||
Handle<Code> off_heap_trampoline = NewCode(no_flags, AllocationType::kOld);
|
||||
|
||||
const bool set_is_off_heap_trampoline = true;
|
||||
off_heap_trampoline->initialize_flags(code->kind(), code->builtin_id(),
|
||||
code->is_turbofanned(),
|
||||
set_is_off_heap_trampoline);
|
||||
code->is_turbofanned());
|
||||
off_heap_trampoline->set_kind_specific_flags(
|
||||
code->kind_specific_flags(kRelaxedLoad), kRelaxedStore);
|
||||
off_heap_trampoline->set_code_entry_point(isolate(),
|
||||
|
@ -1104,7 +1104,7 @@ class MarkCompactCollector::RootMarkingVisitor final : public RootVisitor {
|
||||
if (!IsCodeSpaceObject(value)) {
|
||||
// The slot might contain a Code object representing an
|
||||
// embedded builtin, which doesn't require additional processing.
|
||||
DCHECK(Code::cast(value).is_off_heap_trampoline());
|
||||
DCHECK(!Code::cast(value).has_instruction_stream());
|
||||
} else {
|
||||
InstructionStream code = InstructionStream::cast(value);
|
||||
if (code.kind() != CodeKind::BASELINE) {
|
||||
@ -2688,8 +2688,7 @@ void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor,
|
||||
if (it.frame()->is_unoptimized()) return;
|
||||
if (it.frame()->is_optimized()) {
|
||||
GcSafeCode lookup_result = it.frame()->GcSafeLookupCode();
|
||||
// Builtins can't deoptimize.
|
||||
if (lookup_result.is_off_heap_trampoline()) return;
|
||||
if (!lookup_result.has_instruction_stream()) return;
|
||||
InstructionStream istream = InstructionStream::unchecked_cast(
|
||||
lookup_result.raw_instruction_stream());
|
||||
DCHECK_NE(istream, Smi::zero());
|
||||
|
@ -119,7 +119,7 @@ Code Interpreter::GetBytecodeHandler(Bytecode bytecode,
|
||||
|
||||
void Interpreter::SetBytecodeHandler(Bytecode bytecode,
|
||||
OperandScale operand_scale, Code handler) {
|
||||
DCHECK(handler.is_off_heap_trampoline());
|
||||
DCHECK(!handler.has_instruction_stream());
|
||||
DCHECK(handler.kind() == CodeKind::BYTECODE_HANDLER);
|
||||
size_t index = GetDispatchTableIndex(bytecode, operand_scale);
|
||||
dispatch_table_[index] = handler.InstructionStart();
|
||||
@ -342,8 +342,7 @@ void Interpreter::Initialize() {
|
||||
// initialized.
|
||||
Handle<Code> code = BUILTIN_CODE(isolate_, InterpreterEntryTrampoline);
|
||||
DCHECK(builtins->is_initialized());
|
||||
DCHECK(code->is_off_heap_trampoline() ||
|
||||
isolate_->heap()->IsImmovable(FromCode(*code)));
|
||||
DCHECK(!code->has_instruction_stream());
|
||||
interpreter_entry_trampoline_instruction_start_ = code->InstructionStart();
|
||||
|
||||
// Initialize the dispatch table.
|
||||
|
@ -129,7 +129,7 @@ const char* ComputeMarker(SharedFunctionInfo shared, AbstractCode code) {
|
||||
// We record interpreter trampoline builtin copies as having the
|
||||
// "interpreted" marker.
|
||||
if (v8_flags.interpreted_frames_native_stack && kind == CodeKind::BUILTIN &&
|
||||
!code.is_off_heap_trampoline(cage_base)) {
|
||||
code.has_instruction_stream(cage_base)) {
|
||||
DCHECK_EQ(code.builtin_id(cage_base), Builtin::kInterpreterEntryTrampoline);
|
||||
kind = CodeKind::INTERPRETED_FUNCTION;
|
||||
}
|
||||
@ -2326,7 +2326,7 @@ void ExistingCodeLogger::LogCodeObject(AbstractCode object) {
|
||||
tag = CodeTag::kBytecodeHandler;
|
||||
break;
|
||||
case CodeKind::BUILTIN:
|
||||
if (!abstract_code->is_off_heap_trampoline(cage_base)) {
|
||||
if (abstract_code->has_instruction_stream(cage_base)) {
|
||||
DCHECK_EQ(abstract_code->builtin_id(cage_base),
|
||||
Builtin::kInterpreterEntryTrampoline);
|
||||
// We treat interpreter trampoline builtin copies as
|
||||
|
@ -63,7 +63,7 @@ GCSAFE_CODE_FWD_ACCESSOR(CodeKind, kind)
|
||||
GCSAFE_CODE_FWD_ACCESSOR(bool, is_interpreter_trampoline_builtin)
|
||||
GCSAFE_CODE_FWD_ACCESSOR(bool, is_baseline_trampoline_builtin)
|
||||
GCSAFE_CODE_FWD_ACCESSOR(bool, is_baseline_leave_frame_builtin)
|
||||
GCSAFE_CODE_FWD_ACCESSOR(bool, is_off_heap_trampoline)
|
||||
GCSAFE_CODE_FWD_ACCESSOR(bool, has_instruction_stream)
|
||||
GCSAFE_CODE_FWD_ACCESSOR(bool, is_maglevved)
|
||||
GCSAFE_CODE_FWD_ACCESSOR(bool, is_turbofanned)
|
||||
GCSAFE_CODE_FWD_ACCESSOR(bool, has_tagged_outgoing_params)
|
||||
@ -100,7 +100,7 @@ ByteArray AbstractCode::SourcePositionTableInternal(
|
||||
Map map_object = map(cage_base);
|
||||
if (InstanceTypeChecker::IsCode(map_object)) {
|
||||
Code code = GetCode();
|
||||
if (code.is_off_heap_trampoline()) {
|
||||
if (!code.has_instruction_stream()) {
|
||||
return GetReadOnlyRoots().empty_byte_array();
|
||||
}
|
||||
return code.source_position_table(cage_base);
|
||||
@ -125,9 +125,9 @@ int AbstractCode::SizeIncludingMetadata(PtrComprCageBase cage_base) {
|
||||
Map map_object = map(cage_base);
|
||||
if (InstanceTypeChecker::IsCode(map_object)) {
|
||||
Code code = GetCode();
|
||||
return code.is_off_heap_trampoline()
|
||||
? 0
|
||||
: FromCode(code).SizeIncludingMetadata(cage_base);
|
||||
return code.has_instruction_stream()
|
||||
? FromCode(code).SizeIncludingMetadata(cage_base)
|
||||
: 0;
|
||||
} else {
|
||||
DCHECK(InstanceTypeChecker::IsBytecodeArray(map_object));
|
||||
return GetBytecodeArray().SizeIncludingMetadata();
|
||||
@ -187,14 +187,9 @@ Builtin AbstractCode::builtin_id(PtrComprCageBase cage_base) {
|
||||
}
|
||||
}
|
||||
|
||||
bool AbstractCode::is_off_heap_trampoline(PtrComprCageBase cage_base) {
|
||||
Map map_object = map(cage_base);
|
||||
if (InstanceTypeChecker::IsCode(map_object)) {
|
||||
return GetCode().is_off_heap_trampoline();
|
||||
} else {
|
||||
DCHECK(InstanceTypeChecker::IsBytecodeArray(map_object));
|
||||
return false;
|
||||
}
|
||||
bool AbstractCode::has_instruction_stream(PtrComprCageBase cage_base) {
|
||||
DCHECK(InstanceTypeChecker::IsCode(map(cage_base)));
|
||||
return GetCode().has_instruction_stream();
|
||||
}
|
||||
|
||||
HandlerTable::CatchPrediction AbstractCode::GetBuiltinCatchPrediction(
|
||||
@ -364,7 +359,7 @@ inline MaybeHandle<Code> ToCode(MaybeHandle<InstructionStream> maybe_code,
|
||||
}
|
||||
|
||||
inline InstructionStream FromCode(Code code) {
|
||||
DCHECK(!code.is_off_heap_trampoline());
|
||||
DCHECK(code.has_instruction_stream());
|
||||
// Compute the InstructionStream object pointer from the code entry point.
|
||||
Address ptr =
|
||||
code.code_entry_point() - InstructionStream::kHeaderSize + kHeapObjectTag;
|
||||
@ -373,7 +368,7 @@ inline InstructionStream FromCode(Code code) {
|
||||
|
||||
inline InstructionStream FromCode(Code code, PtrComprCageBase code_cage_base,
|
||||
RelaxedLoadTag tag) {
|
||||
DCHECK(!code.is_off_heap_trampoline());
|
||||
DCHECK(code.has_instruction_stream());
|
||||
// Since the code entry point field is not aligned we can't load it atomically
|
||||
// and use for InstructionStream object pointer calculation. So, we load and
|
||||
// decompress the code field.
|
||||
@ -415,7 +410,7 @@ void InstructionStream::clear_padding() {
|
||||
|
||||
ByteArray Code::SourcePositionTable(PtrComprCageBase cage_base,
|
||||
SharedFunctionInfo sfi) const {
|
||||
if (is_off_heap_trampoline()) {
|
||||
if (!has_instruction_stream()) {
|
||||
return GetReadOnlyRoots().empty_byte_array();
|
||||
}
|
||||
return instruction_stream().SourcePositionTable(cage_base, sfi);
|
||||
@ -443,71 +438,66 @@ int InstructionStream::raw_body_size() const {
|
||||
return raw_instruction_size() + raw_metadata_size();
|
||||
}
|
||||
|
||||
// TODO(jgruber): Remove this.
|
||||
int InstructionStream::InstructionSize() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapInstructionSize(*this, builtin_id())
|
||||
: raw_instruction_size();
|
||||
return raw_instruction_size();
|
||||
}
|
||||
|
||||
int Code::InstructionSize() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapInstructionSize(*this, builtin_id())
|
||||
: instruction_stream().raw_instruction_size();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().raw_instruction_size()
|
||||
: i::OffHeapInstructionSize(*this, builtin_id());
|
||||
}
|
||||
|
||||
Address InstructionStream::raw_instruction_start() const {
|
||||
return field_address(kHeaderSize);
|
||||
}
|
||||
|
||||
// TODO(jgruber): Remove this.
|
||||
Address InstructionStream::InstructionStart() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? i::OffHeapInstructionStart(*this, builtin_id())
|
||||
: raw_instruction_start();
|
||||
return raw_instruction_start();
|
||||
}
|
||||
|
||||
Address InstructionStream::raw_instruction_end() const {
|
||||
return raw_instruction_start() + raw_instruction_size();
|
||||
}
|
||||
|
||||
// TODO(jgruber): Remove this.
|
||||
Address InstructionStream::InstructionEnd() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? i::OffHeapInstructionEnd(*this, builtin_id())
|
||||
: raw_instruction_end();
|
||||
return raw_instruction_end();
|
||||
}
|
||||
|
||||
Address Code::InstructionEnd() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? i::OffHeapInstructionEnd(*this, builtin_id())
|
||||
: instruction_stream().raw_instruction_end();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().raw_instruction_end()
|
||||
: i::OffHeapInstructionEnd(*this, builtin_id());
|
||||
}
|
||||
|
||||
Address InstructionStream::raw_metadata_start() const {
|
||||
return raw_instruction_start() + raw_instruction_size();
|
||||
}
|
||||
|
||||
// TODO(jgruber): Remove this.
|
||||
Address InstructionStream::InstructionStart(Isolate* isolate,
|
||||
Address pc) const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapInstructionStart(isolate, pc)
|
||||
: raw_instruction_start();
|
||||
return raw_instruction_start();
|
||||
}
|
||||
|
||||
Address Code::InstructionStart(Isolate* isolate, Address pc) const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapInstructionStart(isolate, pc)
|
||||
: raw_instruction_start();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? raw_instruction_start()
|
||||
: OffHeapInstructionStart(isolate, pc);
|
||||
}
|
||||
|
||||
// TODO(jgruber): Remove this.
|
||||
Address InstructionStream::InstructionEnd(Isolate* isolate, Address pc) const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapInstructionEnd(isolate, pc)
|
||||
: raw_instruction_end();
|
||||
return raw_instruction_end();
|
||||
}
|
||||
|
||||
Address Code::InstructionEnd(Isolate* isolate, Address pc) const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapInstructionEnd(isolate, pc)
|
||||
: raw_instruction_end();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? raw_instruction_end()
|
||||
: OffHeapInstructionEnd(isolate, pc);
|
||||
}
|
||||
|
||||
int InstructionStream::GetOffsetFromInstructionStart(Isolate* isolate,
|
||||
@ -529,11 +519,8 @@ Address InstructionStream::raw_metadata_end() const {
|
||||
return raw_metadata_start() + raw_metadata_size();
|
||||
}
|
||||
|
||||
int InstructionStream::MetadataSize() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapMetadataSize(*this, builtin_id())
|
||||
: raw_metadata_size();
|
||||
}
|
||||
// TODO(jgruber): Remove this.
|
||||
int InstructionStream::MetadataSize() const { return raw_metadata_size(); }
|
||||
|
||||
DEF_GETTER(InstructionStream, SizeIncludingMetadata, int) {
|
||||
int size = CodeSize();
|
||||
@ -548,10 +535,9 @@ Address InstructionStream::raw_safepoint_table_address() const {
|
||||
return raw_metadata_start() + safepoint_table_offset();
|
||||
}
|
||||
|
||||
// TODO(jgruber): Remove this.
|
||||
Address InstructionStream::SafepointTableAddress() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapSafepointTableAddress(*this, builtin_id())
|
||||
: raw_safepoint_table_address();
|
||||
return raw_safepoint_table_address();
|
||||
}
|
||||
|
||||
int InstructionStream::safepoint_table_size() const {
|
||||
@ -564,24 +550,24 @@ bool InstructionStream::has_safepoint_table() const {
|
||||
}
|
||||
|
||||
Address Code::SafepointTableAddress() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapSafepointTableAddress(*this, builtin_id())
|
||||
: instruction_stream().raw_safepoint_table_address();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().raw_safepoint_table_address()
|
||||
: OffHeapSafepointTableAddress(*this, builtin_id());
|
||||
}
|
||||
|
||||
Address GcSafeCode::SafepointTableAddress() const {
|
||||
Code unsafe_this = UnsafeCastToCode();
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapSafepointTableAddress(unsafe_this, builtin_id())
|
||||
: InstructionStream::unchecked_cast(
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? InstructionStream::unchecked_cast(
|
||||
unsafe_this.raw_instruction_stream(kRelaxedLoad))
|
||||
.raw_safepoint_table_address();
|
||||
.raw_safepoint_table_address()
|
||||
: OffHeapSafepointTableAddress(unsafe_this, builtin_id());
|
||||
}
|
||||
|
||||
int Code::safepoint_table_size() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapSafepointTableSize(*this, builtin_id())
|
||||
: instruction_stream().safepoint_table_size();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().safepoint_table_size()
|
||||
: OffHeapSafepointTableSize(*this, builtin_id());
|
||||
}
|
||||
|
||||
bool Code::has_safepoint_table() const { return safepoint_table_size() > 0; }
|
||||
@ -590,10 +576,9 @@ Address InstructionStream::raw_handler_table_address() const {
|
||||
return raw_metadata_start() + handler_table_offset();
|
||||
}
|
||||
|
||||
// TODO(jgruber): Remove this.
|
||||
Address InstructionStream::HandlerTableAddress() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapHandlerTableAddress(*this, builtin_id())
|
||||
: raw_handler_table_address();
|
||||
return raw_handler_table_address();
|
||||
}
|
||||
|
||||
int InstructionStream::handler_table_size() const {
|
||||
@ -606,15 +591,15 @@ bool InstructionStream::has_handler_table() const {
|
||||
}
|
||||
|
||||
Address Code::HandlerTableAddress() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapHandlerTableAddress(*this, builtin_id())
|
||||
: instruction_stream().raw_handler_table_address();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().raw_handler_table_address()
|
||||
: OffHeapHandlerTableAddress(*this, builtin_id());
|
||||
}
|
||||
|
||||
int Code::handler_table_size() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapHandlerTableSize(*this, builtin_id())
|
||||
: instruction_stream().handler_table_size();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().handler_table_size()
|
||||
: OffHeapHandlerTableSize(*this, builtin_id());
|
||||
}
|
||||
|
||||
bool Code::has_handler_table() const { return handler_table_size() > 0; }
|
||||
@ -634,9 +619,9 @@ bool InstructionStream::has_constant_pool() const {
|
||||
}
|
||||
|
||||
int Code::constant_pool_size() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapConstantPoolSize(*this, builtin_id())
|
||||
: instruction_stream().constant_pool_size();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().constant_pool_size()
|
||||
: OffHeapConstantPoolSize(*this, builtin_id());
|
||||
}
|
||||
|
||||
bool Code::has_constant_pool() const { return constant_pool_size() > 0; }
|
||||
@ -660,39 +645,34 @@ int InstructionStream::relocation_size() const {
|
||||
}
|
||||
|
||||
byte* Code::relocation_start() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? nullptr // Off heap trampolines do not have reloc info.
|
||||
: instruction_stream().relocation_start();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().relocation_start()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
byte* Code::relocation_end() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? nullptr // Off heap trampolines do not have reloc info.
|
||||
: instruction_stream().relocation_end();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().relocation_end()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
int Code::relocation_size() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? 0 // Off heap trampolines do not have reloc info.
|
||||
: instruction_stream().relocation_size();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().relocation_size()
|
||||
: 0;
|
||||
}
|
||||
|
||||
Address InstructionStream::entry() const { return raw_instruction_start(); }
|
||||
|
||||
bool InstructionStream::contains(Isolate* isolate, Address inner_pointer) {
|
||||
if (is_off_heap_trampoline() &&
|
||||
OffHeapBuiltinContains(isolate, inner_pointer)) {
|
||||
return true;
|
||||
}
|
||||
return (address() <= inner_pointer) &&
|
||||
(inner_pointer < address() + CodeSize());
|
||||
}
|
||||
|
||||
bool Code::contains(Isolate* isolate, Address inner_pointer) {
|
||||
if (is_off_heap_trampoline()) {
|
||||
return OffHeapBuiltinContains(isolate, inner_pointer);
|
||||
}
|
||||
return instruction_stream().contains(isolate, inner_pointer);
|
||||
return has_instruction_stream()
|
||||
? instruction_stream().contains(isolate, inner_pointer)
|
||||
: OffHeapBuiltinContains(isolate, inner_pointer);
|
||||
}
|
||||
|
||||
// static
|
||||
@ -778,14 +758,12 @@ uintptr_t InstructionStream::GetBaselinePCForNextExecutedBytecode(
|
||||
}
|
||||
|
||||
void InstructionStream::initialize_flags(CodeKind kind, bool is_turbofanned,
|
||||
int stack_slots,
|
||||
bool is_off_heap_trampoline) {
|
||||
int stack_slots) {
|
||||
CHECK(0 <= stack_slots && stack_slots < StackSlotsField::kMax);
|
||||
DCHECK(!CodeKindIsInterpretedJSFunction(kind));
|
||||
uint32_t flags = KindField::encode(kind) |
|
||||
IsTurbofannedField::encode(is_turbofanned) |
|
||||
StackSlotsField::encode(stack_slots) |
|
||||
IsOffHeapTrampoline::encode(is_off_heap_trampoline);
|
||||
StackSlotsField::encode(stack_slots);
|
||||
static_assert(FIELD_SIZE(kFlagsOffset) == kInt32Size);
|
||||
RELAXED_WRITE_UINT32_FIELD(*this, kFlagsOffset, flags);
|
||||
DCHECK_IMPLIES(stack_slots != 0, uses_safepoint_table());
|
||||
@ -912,8 +890,6 @@ inline void InstructionStream::set_is_promise_rejection(bool value) {
|
||||
container.set_is_promise_rejection(value);
|
||||
}
|
||||
|
||||
inline bool InstructionStream::is_off_heap_trampoline() const { return false; }
|
||||
|
||||
inline HandlerTable::CatchPrediction
|
||||
InstructionStream::GetBuiltinCatchPrediction() const {
|
||||
if (is_promise_rejection()) return HandlerTable::PROMISE;
|
||||
@ -977,18 +953,18 @@ int InstructionStream::stack_slots() const {
|
||||
}
|
||||
|
||||
int Code::stack_slots() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapStackSlots(*this, builtin_id())
|
||||
: instruction_stream().stack_slots();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().stack_slots()
|
||||
: OffHeapStackSlots(*this, builtin_id());
|
||||
}
|
||||
|
||||
int GcSafeCode::stack_slots() const {
|
||||
Code unsafe_this = UnsafeCastToCode();
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapStackSlots(unsafe_this, builtin_id())
|
||||
: InstructionStream::unchecked_cast(
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? InstructionStream::unchecked_cast(
|
||||
unsafe_this.raw_instruction_stream(kRelaxedLoad))
|
||||
.stack_slots();
|
||||
.stack_slots()
|
||||
: OffHeapStackSlots(unsafe_this, builtin_id());
|
||||
}
|
||||
|
||||
bool Code::marked_for_deoptimization() const {
|
||||
@ -1064,27 +1040,22 @@ Address InstructionStream::raw_constant_pool() const {
|
||||
|
||||
Address InstructionStream::constant_pool() const {
|
||||
if (!has_constant_pool()) return kNullAddress;
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapConstantPoolAddress(*this, builtin_id())
|
||||
: raw_constant_pool();
|
||||
return raw_constant_pool();
|
||||
}
|
||||
|
||||
Address Code::constant_pool() const {
|
||||
if (!has_constant_pool()) return kNullAddress;
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapConstantPoolAddress(*this, builtin_id())
|
||||
: instruction_stream().raw_constant_pool();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().raw_constant_pool()
|
||||
: OffHeapConstantPoolAddress(*this, builtin_id());
|
||||
}
|
||||
|
||||
Address InstructionStream::raw_code_comments() const {
|
||||
return raw_metadata_start() + code_comments_offset();
|
||||
}
|
||||
|
||||
Address InstructionStream::code_comments() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapCodeCommentsAddress(*this, builtin_id())
|
||||
: raw_code_comments();
|
||||
}
|
||||
// TODO(jgruber): Remove this.
|
||||
Address InstructionStream::code_comments() const { return raw_code_comments(); }
|
||||
|
||||
int InstructionStream::code_comments_size() const {
|
||||
DCHECK_GE(unwinding_info_offset() - code_comments_offset(), 0);
|
||||
@ -1096,15 +1067,15 @@ bool InstructionStream::has_code_comments() const {
|
||||
}
|
||||
|
||||
Address Code::code_comments() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapCodeCommentsAddress(*this, builtin_id())
|
||||
: instruction_stream().code_comments();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().code_comments()
|
||||
: OffHeapCodeCommentsAddress(*this, builtin_id());
|
||||
}
|
||||
|
||||
int Code::code_comments_size() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapCodeCommentsSize(*this, builtin_id())
|
||||
: instruction_stream().code_comments_size();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().code_comments_size()
|
||||
: OffHeapCodeCommentsSize(*this, builtin_id());
|
||||
}
|
||||
|
||||
bool Code::has_code_comments() const { return code_comments_size() > 0; }
|
||||
@ -1113,16 +1084,14 @@ Address InstructionStream::raw_unwinding_info_start() const {
|
||||
return raw_metadata_start() + unwinding_info_offset();
|
||||
}
|
||||
|
||||
// TODO(jgruber): Remove this.
|
||||
Address InstructionStream::unwinding_info_start() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapUnwindingInfoAddress(*this, builtin_id())
|
||||
: raw_unwinding_info_start();
|
||||
return raw_unwinding_info_start();
|
||||
}
|
||||
|
||||
// TODO(jgruber): Remove this.
|
||||
Address InstructionStream::unwinding_info_end() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapMetadataEnd(*this, builtin_id())
|
||||
: raw_metadata_end();
|
||||
return raw_metadata_end();
|
||||
}
|
||||
|
||||
int InstructionStream::unwinding_info_size() const {
|
||||
@ -1135,21 +1104,21 @@ bool InstructionStream::has_unwinding_info() const {
|
||||
}
|
||||
|
||||
Address Code::unwinding_info_start() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapUnwindingInfoAddress(*this, builtin_id())
|
||||
: instruction_stream().raw_unwinding_info_start();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().raw_unwinding_info_start()
|
||||
: OffHeapUnwindingInfoAddress(*this, builtin_id());
|
||||
}
|
||||
|
||||
Address Code::unwinding_info_end() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapMetadataEnd(*this, builtin_id())
|
||||
: instruction_stream().raw_metadata_end();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().raw_metadata_end()
|
||||
: OffHeapMetadataEnd(*this, builtin_id());
|
||||
}
|
||||
|
||||
int Code::unwinding_info_size() const {
|
||||
return V8_UNLIKELY(is_off_heap_trampoline())
|
||||
? OffHeapUnwindingInfoSize(*this, builtin_id())
|
||||
: instruction_stream().unwinding_info_size();
|
||||
return V8_LIKELY(has_instruction_stream())
|
||||
? instruction_stream().unwinding_info_size()
|
||||
: OffHeapUnwindingInfoSize(*this, builtin_id());
|
||||
|
||||
DCHECK_GE(unwinding_info_end(), unwinding_info_start());
|
||||
return static_cast<int>(unwinding_info_end() - unwinding_info_start());
|
||||
@ -1232,6 +1201,14 @@ void Code::set_raw_instruction_stream(Object value, WriteBarrierMode mode) {
|
||||
CONDITIONAL_WRITE_BARRIER(*this, kInstructionStreamOffset, value, mode);
|
||||
}
|
||||
|
||||
bool Code::has_instruction_stream() const {
|
||||
return raw_instruction_stream() != Smi::zero();
|
||||
}
|
||||
|
||||
bool Code::has_instruction_stream(RelaxedLoadTag tag) const {
|
||||
return raw_instruction_stream(tag) != Smi::zero();
|
||||
}
|
||||
|
||||
PtrComprCageBase Code::code_cage_base() const {
|
||||
#ifdef V8_EXTERNAL_CODE_SPACE
|
||||
Isolate* isolate = GetIsolateFromWritableObject(*this);
|
||||
@ -1246,7 +1223,7 @@ InstructionStream Code::instruction_stream() const {
|
||||
return Code::instruction_stream(cage_base);
|
||||
}
|
||||
InstructionStream Code::instruction_stream(PtrComprCageBase cage_base) const {
|
||||
DCHECK(!is_off_heap_trampoline());
|
||||
DCHECK(has_instruction_stream());
|
||||
return ExternalCodeField<InstructionStream>::load(cage_base, *this);
|
||||
}
|
||||
|
||||
@ -1257,7 +1234,7 @@ InstructionStream Code::instruction_stream(RelaxedLoadTag tag) const {
|
||||
|
||||
InstructionStream Code::instruction_stream(PtrComprCageBase cage_base,
|
||||
RelaxedLoadTag tag) const {
|
||||
DCHECK(!is_off_heap_trampoline());
|
||||
DCHECK(has_instruction_stream());
|
||||
return ExternalCodeField<InstructionStream>::Relaxed_Load(cage_base, *this);
|
||||
}
|
||||
|
||||
@ -1268,7 +1245,7 @@ Object Code::raw_instruction_stream(RelaxedLoadTag tag) const {
|
||||
|
||||
Object Code::raw_instruction_stream(PtrComprCageBase cage_base,
|
||||
RelaxedLoadTag tag) const {
|
||||
DCHECK(!is_off_heap_trampoline());
|
||||
DCHECK(has_instruction_stream());
|
||||
return ExternalCodeField<HeapObject>::Relaxed_Load(cage_base, *this);
|
||||
}
|
||||
|
||||
@ -1293,7 +1270,7 @@ void Code::SetInstructionStreamAndEntryPoint(Isolate* isolate_for_sandbox,
|
||||
|
||||
void Code::SetEntryPointForOffHeapBuiltin(Isolate* isolate_for_sandbox,
|
||||
Address entry) {
|
||||
DCHECK(is_off_heap_trampoline());
|
||||
DCHECK(!has_instruction_stream());
|
||||
set_code_entry_point(isolate_for_sandbox, entry);
|
||||
}
|
||||
|
||||
@ -1307,7 +1284,7 @@ Address Code::InstructionStart() const { return code_entry_point(); }
|
||||
|
||||
Address Code::raw_instruction_start() const { return code_entry_point(); }
|
||||
Address Code::raw_instruction_end() const {
|
||||
DCHECK(!is_off_heap_trampoline());
|
||||
DCHECK(has_instruction_stream());
|
||||
return InstructionStream::unchecked_cast(raw_instruction_stream())
|
||||
.raw_instruction_end();
|
||||
}
|
||||
@ -1334,10 +1311,9 @@ static_assert(static_cast<int>(Builtin::kNoBuiltinId) == -1);
|
||||
static_assert(Builtins::kBuiltinCount < std::numeric_limits<int16_t>::max());
|
||||
|
||||
void Code::initialize_flags(CodeKind kind, Builtin builtin_id,
|
||||
bool is_turbofanned, bool is_off_heap_trampoline) {
|
||||
uint16_t value = KindField::encode(kind) |
|
||||
IsTurbofannedField::encode(is_turbofanned) |
|
||||
IsOffHeapTrampoline::encode(is_off_heap_trampoline);
|
||||
bool is_turbofanned) {
|
||||
uint16_t value =
|
||||
KindField::encode(kind) | IsTurbofannedField::encode(is_turbofanned);
|
||||
set_flags(value, kRelaxedStore);
|
||||
|
||||
WriteField<int16_t>(kBuiltinIdOffset, static_cast<int16_t>(builtin_id));
|
||||
@ -1356,16 +1332,6 @@ Builtin Code::builtin_id() const {
|
||||
|
||||
bool Code::is_builtin() const { return builtin_id() != Builtin::kNoBuiltinId; }
|
||||
|
||||
bool Code::is_off_heap_trampoline() const {
|
||||
return IsOffHeapTrampoline::decode(flags(kRelaxedLoad));
|
||||
}
|
||||
|
||||
void Code::set_is_off_heap_trampoline_for_hash(bool value) {
|
||||
uint16_t flags_value = flags(kRelaxedLoad);
|
||||
flags_value = IsOffHeapTrampoline::update(flags_value, value);
|
||||
set_flags(flags_value, kRelaxedStore);
|
||||
}
|
||||
|
||||
bool Code::is_optimized_code() const {
|
||||
return CodeKindIsOptimizedJSFunction(kind());
|
||||
}
|
||||
@ -1390,12 +1356,12 @@ inline bool Code::is_baseline_leave_frame_builtin() const {
|
||||
#define DEF_PRIMITIVE_FORWARDING_CDC_GETTER(name, type) \
|
||||
type Code::name() const { return FromCode(*this).name(); }
|
||||
|
||||
#define DEF_FORWARDING_CDC_GETTER(name, type, result_if_off_heap) \
|
||||
DEF_GETTER(Code, name, type) { \
|
||||
if (is_off_heap_trampoline()) { \
|
||||
return GetReadOnlyRoots().result_if_off_heap(); \
|
||||
} \
|
||||
return FromCode(*this).name(cage_base); \
|
||||
#define DEF_FORWARDING_CDC_GETTER(name, type, result_if_no_instruction_stream) \
|
||||
DEF_GETTER(Code, name, type) { \
|
||||
if (!has_instruction_stream()) { \
|
||||
return GetReadOnlyRoots().result_if_no_instruction_stream(); \
|
||||
} \
|
||||
return FromCode(*this).name(cage_base); \
|
||||
}
|
||||
|
||||
DEF_FORWARDING_CDC_GETTER(deoptimization_data, FixedArray, empty_fixed_array)
|
||||
|
@ -237,41 +237,20 @@ MaglevSafepointEntry Code::GetMaglevSafepointEntry(Isolate* isolate,
|
||||
return table.FindEntry(pc);
|
||||
}
|
||||
|
||||
Address InstructionStream::OffHeapInstructionStart(Isolate* isolate,
|
||||
Address pc) const {
|
||||
DCHECK(is_off_heap_trampoline());
|
||||
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
|
||||
return d.InstructionStartOfBuiltin(builtin_id());
|
||||
}
|
||||
|
||||
Address Code::OffHeapInstructionStart(Isolate* isolate, Address pc) const {
|
||||
DCHECK(is_off_heap_trampoline());
|
||||
DCHECK(!has_instruction_stream());
|
||||
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
|
||||
return d.InstructionStartOfBuiltin(builtin_id());
|
||||
}
|
||||
|
||||
Address InstructionStream::OffHeapInstructionEnd(Isolate* isolate,
|
||||
Address pc) const {
|
||||
DCHECK(is_off_heap_trampoline());
|
||||
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
|
||||
return d.InstructionEndOf(builtin_id());
|
||||
}
|
||||
|
||||
Address Code::OffHeapInstructionEnd(Isolate* isolate, Address pc) const {
|
||||
DCHECK(is_off_heap_trampoline());
|
||||
DCHECK(!has_instruction_stream());
|
||||
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
|
||||
return d.InstructionEndOf(builtin_id());
|
||||
}
|
||||
|
||||
bool InstructionStream::OffHeapBuiltinContains(Isolate* isolate,
|
||||
Address pc) const {
|
||||
DCHECK(is_off_heap_trampoline());
|
||||
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
|
||||
return d.BuiltinContains(builtin_id(), pc);
|
||||
}
|
||||
|
||||
bool Code::OffHeapBuiltinContains(Isolate* isolate, Address pc) const {
|
||||
DCHECK(is_off_heap_trampoline());
|
||||
DCHECK(!has_instruction_stream());
|
||||
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
|
||||
return d.BuiltinContains(builtin_id(), pc);
|
||||
}
|
||||
@ -556,16 +535,6 @@ void Disassemble(const char* name, std::ostream& os, Isolate* isolate,
|
||||
<< "\n";
|
||||
os << "address = " << reinterpret_cast<void*>(code.ptr()) << "\n\n";
|
||||
|
||||
if (code.IsInstructionStream() && code.is_off_heap_trampoline()) {
|
||||
InstructionStream trampoline_code = InstructionStream::cast(code);
|
||||
int trampoline_size = trampoline_code.raw_instruction_size();
|
||||
os << "Trampoline (size = " << trampoline_size << ")\n";
|
||||
DisassembleCodeRange(isolate, os, trampoline_code,
|
||||
trampoline_code.raw_instruction_start(),
|
||||
trampoline_size, current_pc);
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
{
|
||||
int code_size = code.InstructionSize();
|
||||
os << "Instructions (size = " << code_size << ")\n";
|
||||
|
@ -73,6 +73,17 @@ class Code : public HeapObject {
|
||||
DECL_ACCESSORS(raw_instruction_stream, Object)
|
||||
DECL_RELAXED_GETTER(raw_instruction_stream, Object)
|
||||
|
||||
// Whether this Code object has an associated InstructionStream (embedded
|
||||
// builtins don't).
|
||||
//
|
||||
// Note there's a short amount of time during CodeBuilder::BuildInternal in
|
||||
// which the Code object has been allocated and initialized, but the
|
||||
// InstructionStream doesn't exist yet - in this situation,
|
||||
// has_instruction_stream is `false` but will change to `true` once
|
||||
// InstructionStream has also been initialized.
|
||||
inline bool has_instruction_stream() const;
|
||||
inline bool has_instruction_stream(RelaxedLoadTag) const;
|
||||
|
||||
// When V8_EXTERNAL_CODE_SPACE is enabled, InstructionStream objects are
|
||||
// allocated in a separate pointer compression cage instead of the cage where
|
||||
// all the other objects are allocated. This helper method returns code cage
|
||||
@ -98,8 +109,7 @@ class Code : public HeapObject {
|
||||
// Initializes internal flags field which stores cached values of some
|
||||
// properties of the respective InstructionStream object.
|
||||
inline void initialize_flags(CodeKind kind, Builtin builtin_id,
|
||||
bool is_turbofanned,
|
||||
bool is_off_heap_trampoline);
|
||||
bool is_turbofanned);
|
||||
|
||||
// Alias for code_entry_point to make it API compatible with
|
||||
// InstructionStream.
|
||||
@ -154,14 +164,6 @@ class Code : public HeapObject {
|
||||
// TurboFan optimizing compiler.
|
||||
inline bool is_turbofanned() const;
|
||||
|
||||
// [is_off_heap_trampoline]: For kind BUILTIN tells whether this is a
|
||||
// trampoline to an off-heap builtin.
|
||||
//
|
||||
// This is identical to is_builtin, *except* when
|
||||
// FLAG_interpreter_frames_native_stack is enabled where we may have physical
|
||||
// (non-trampoline) InterpreterEntryTrampoline copies on the heap.
|
||||
inline bool is_off_heap_trampoline() const;
|
||||
|
||||
// [uses_safepoint_table]: Whether this InstructionStream object uses
|
||||
// safepoint tables (note the table may still be empty, see
|
||||
// has_safepoint_table).
|
||||
@ -284,15 +286,14 @@ class Code : public HeapObject {
|
||||
class BodyDescriptor;
|
||||
|
||||
// Flags layout.
|
||||
#define FLAGS_BIT_FIELDS(V, _) \
|
||||
V(KindField, CodeKind, 4, _) \
|
||||
V(IsTurbofannedField, bool, 1, _) \
|
||||
V(IsOffHeapTrampoline, bool, 1, _)
|
||||
#define FLAGS_BIT_FIELDS(V, _) \
|
||||
V(KindField, CodeKind, 4, _) \
|
||||
V(IsTurbofannedField, bool, 1, _)
|
||||
/* The other 10 bits are still free. */
|
||||
|
||||
DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
|
||||
#undef FLAGS_BIT_FIELDS
|
||||
static_assert(FLAGS_BIT_FIELDS_Ranges::kBitsCount == 6);
|
||||
static_assert(FLAGS_BIT_FIELDS_Ranges::kBitsCount == 5);
|
||||
static_assert(FLAGS_BIT_FIELDS_Ranges::kBitsCount <=
|
||||
FIELD_SIZE(Code::kFlagsOffset) * kBitsPerByte);
|
||||
|
||||
@ -303,7 +304,6 @@ class Code : public HeapObject {
|
||||
// Contains cached values of some flags of the from the respective
|
||||
// InstructionStream object.
|
||||
DECL_RELAXED_UINT16_ACCESSORS(flags)
|
||||
inline void set_is_off_heap_trampoline_for_hash(bool value);
|
||||
|
||||
template <typename IsolateT>
|
||||
friend class Deserializer;
|
||||
@ -350,7 +350,7 @@ class GcSafeCode : public HeapObject {
|
||||
inline bool is_interpreter_trampoline_builtin() const;
|
||||
inline bool is_baseline_trampoline_builtin() const;
|
||||
inline bool is_baseline_leave_frame_builtin() const;
|
||||
inline bool is_off_heap_trampoline() const;
|
||||
inline bool has_instruction_stream() const;
|
||||
inline bool is_maglevved() const;
|
||||
inline bool is_turbofanned() const;
|
||||
inline bool has_tagged_outgoing_params() const;
|
||||
@ -461,14 +461,7 @@ class InstructionStream : public HeapObject {
|
||||
// raw_instruction_start/end() values.
|
||||
// TODO(11527): remove these versions once the full solution is ready.
|
||||
inline Address InstructionStart(Isolate* isolate, Address pc) const;
|
||||
V8_EXPORT_PRIVATE Address OffHeapInstructionStart(Isolate* isolate,
|
||||
Address pc) const;
|
||||
inline Address InstructionEnd(Isolate* isolate, Address pc) const;
|
||||
V8_EXPORT_PRIVATE Address OffHeapInstructionEnd(Isolate* isolate,
|
||||
Address pc) const;
|
||||
|
||||
V8_EXPORT_PRIVATE bool OffHeapBuiltinContains(Isolate* isolate,
|
||||
Address pc) const;
|
||||
|
||||
// Computes offset of the |pc| from the instruction start. The |pc| must
|
||||
// belong to this code.
|
||||
@ -641,10 +634,6 @@ class InstructionStream : public HeapObject {
|
||||
// Use GetBuiltinCatchPrediction to access this.
|
||||
inline void set_is_promise_rejection(bool flag);
|
||||
|
||||
// [is_off_heap_trampoline]: For kind BUILTIN tells whether
|
||||
// this is a trampoline to an off-heap builtin.
|
||||
inline bool is_off_heap_trampoline() const;
|
||||
|
||||
// The entire code object including its header is copied verbatim to the
|
||||
// snapshot so that it can be written in one, fast, memcpy during
|
||||
// deserialization. The deserializer will overwrite some pointers, rather
|
||||
@ -669,7 +658,7 @@ class InstructionStream : public HeapObject {
|
||||
// Initialize the flags field. Similar to clear_padding above this ensure that
|
||||
// the snapshot content is deterministic.
|
||||
inline void initialize_flags(CodeKind kind, bool is_turbofanned,
|
||||
int stack_slots, bool is_off_heap_trampoline);
|
||||
int stack_slots);
|
||||
|
||||
// Convert a target address into a code object.
|
||||
static inline InstructionStream GetCodeFromTargetAddress(Address address);
|
||||
@ -833,15 +822,14 @@ class InstructionStream : public HeapObject {
|
||||
class BodyDescriptor;
|
||||
|
||||
// Flags layout. base::BitField<type, shift, size>.
|
||||
#define CODE_FLAGS_BIT_FIELDS(V, _) \
|
||||
V(KindField, CodeKind, 4, _) \
|
||||
V(IsTurbofannedField, bool, 1, _) \
|
||||
V(StackSlotsField, int, 24, _) \
|
||||
V(IsOffHeapTrampoline, bool, 1, _)
|
||||
#define CODE_FLAGS_BIT_FIELDS(V, _) \
|
||||
V(KindField, CodeKind, 4, _) \
|
||||
V(IsTurbofannedField, bool, 1, _) \
|
||||
V(StackSlotsField, int, 24, _)
|
||||
DEFINE_BIT_FIELDS(CODE_FLAGS_BIT_FIELDS)
|
||||
#undef CODE_FLAGS_BIT_FIELDS
|
||||
static_assert(kCodeKindCount <= KindField::kNumValues);
|
||||
static_assert(CODE_FLAGS_BIT_FIELDS_Ranges::kBitsCount == 30);
|
||||
static_assert(CODE_FLAGS_BIT_FIELDS_Ranges::kBitsCount == 29);
|
||||
static_assert(CODE_FLAGS_BIT_FIELDS_Ranges::kBitsCount <=
|
||||
FIELD_SIZE(kFlagsOffset) * kBitsPerByte);
|
||||
|
||||
@ -951,21 +939,8 @@ class AbstractCode : public HeapObject {
|
||||
int SourcePosition(PtrComprCageBase cage_base, int offset);
|
||||
int SourceStatementPosition(PtrComprCageBase cage_base, int offset);
|
||||
|
||||
// Returns the address of the first instruction. For off-heap code objects
|
||||
// this differs from instruction_start (which would point to the off-heap
|
||||
// trampoline instead).
|
||||
inline Address InstructionStart(PtrComprCageBase cage_base);
|
||||
|
||||
// Returns the address right after the last instruction. For off-heap code
|
||||
// objects this differs from instruction_end (which would point to the
|
||||
// off-heap trampoline instead).
|
||||
inline Address InstructionEnd(PtrComprCageBase cage_base);
|
||||
|
||||
// Returns the size of the native instructions, including embedded
|
||||
// data such as the safepoints table. For off-heap code objects
|
||||
// this may differ from instruction_size in that this will return the size of
|
||||
// the off-heap instruction stream rather than the on-heap trampoline located
|
||||
// at instruction_start.
|
||||
inline int InstructionSize(PtrComprCageBase cage_base);
|
||||
|
||||
// Return the source position table for interpreter code.
|
||||
@ -985,10 +960,7 @@ class AbstractCode : public HeapObject {
|
||||
|
||||
inline Builtin builtin_id(PtrComprCageBase cage_base);
|
||||
|
||||
// This is identical to is_builtin, *except* when
|
||||
// FLAG_interpreter_frames_native_stack is enabled where we may have physical
|
||||
// (non-trampoline) InterpreterEntryTrampoline copies on the heap.
|
||||
inline bool is_off_heap_trampoline(PtrComprCageBase cage_base);
|
||||
inline bool has_instruction_stream(PtrComprCageBase cage_base);
|
||||
|
||||
inline HandlerTable::CatchPrediction GetBuiltinCatchPrediction(
|
||||
PtrComprCageBase cage_base);
|
||||
|
@ -1501,10 +1501,8 @@ void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
|
||||
HeapEntry* entry, SharedFunctionInfo shared) {
|
||||
std::unique_ptr<char[]> name = shared.DebugNameCStr();
|
||||
Code code = shared.GetCode();
|
||||
// Don't try to get the InstructionStream object from InstructionStream-less
|
||||
// embedded builtin.
|
||||
HeapObject maybe_code_obj =
|
||||
code.is_off_heap_trampoline() ? HeapObject::cast(code) : FromCode(code);
|
||||
code.has_instruction_stream() ? FromCode(code) : HeapObject::cast(code);
|
||||
if (name[0] != '\0') {
|
||||
TagObject(maybe_code_obj,
|
||||
names_->GetFormatted("(code for %s)", name.get()));
|
||||
@ -1577,7 +1575,7 @@ void V8HeapExplorer::ExtractWeakCellReferences(HeapEntry* entry,
|
||||
|
||||
void V8HeapExplorer::TagBuiltinCodeObject(Code code, const char* name) {
|
||||
TagObject(code, names_->GetFormatted("(%s builtin handle)", name));
|
||||
if (!code.is_off_heap_trampoline()) {
|
||||
if (code.has_instruction_stream()) {
|
||||
TagObject(FromCode(code), names_->GetFormatted("(%s builtin)", name));
|
||||
}
|
||||
}
|
||||
@ -2075,7 +2073,7 @@ class RootsReferencesExtractor : public RootVisitor {
|
||||
// When external code space is enabled, the slot might contain a
|
||||
// Code object representing an embedded builtin, which
|
||||
// doesn't require additional processing.
|
||||
DCHECK(Code::cast(value).is_off_heap_trampoline());
|
||||
DCHECK(!Code::cast(value).has_instruction_stream());
|
||||
} else {
|
||||
InstructionStream code = InstructionStream::cast(value);
|
||||
if (code.kind() != CodeKind::BASELINE) {
|
||||
|
@ -499,7 +499,7 @@ void Deserializer<IsolateT>::PostProcessNewObject(Handle<Map> map,
|
||||
} else if (InstanceTypeChecker::IsCode(instance_type)) {
|
||||
auto code = Code::cast(raw_obj);
|
||||
code.init_code_entry_point(main_thread_isolate(), kNullAddress);
|
||||
if (code.is_off_heap_trampoline()) {
|
||||
if (!code.has_instruction_stream()) {
|
||||
Address entry = OffHeapInstructionStart(code, code.builtin_id());
|
||||
code.SetEntryPointForOffHeapBuiltin(main_thread_isolate(), entry);
|
||||
} else {
|
||||
|
@ -270,9 +270,6 @@ void EmbeddedFileWriter::PrepareBuiltinSourcePositionMap(Builtins* builtins) {
|
||||
++builtin) {
|
||||
// Retrieve the SourcePositionTable and copy it.
|
||||
InstructionStream code = FromCode(builtins->code(builtin));
|
||||
// Verify that the code object is still the "real code" and not a
|
||||
// trampoline (which wouldn't have source positions).
|
||||
DCHECK(!code.is_off_heap_trampoline());
|
||||
ByteArray source_position_table = code.source_position_table();
|
||||
std::vector<unsigned char> data(source_position_table.GetDataStartAddress(),
|
||||
source_position_table.GetDataEndAddress());
|
||||
|
@ -91,7 +91,6 @@ bool IsUnexpectedCodeObject(Isolate* isolate, HeapObject obj) {
|
||||
InstructionStream code = InstructionStream::cast(obj);
|
||||
if (code.kind() == CodeKind::REGEXP) return false;
|
||||
if (!code.is_builtin()) return true;
|
||||
if (code.is_off_heap_trampoline()) return false;
|
||||
|
||||
// An on-heap builtin.
|
||||
return true;
|
||||
|
@ -1425,7 +1425,7 @@ void TierUpNowForTesting(Isolate* isolate, WasmInstanceObject instance,
|
||||
namespace {
|
||||
|
||||
void RecordStats(Code code, Counters* counters) {
|
||||
if (code.is_off_heap_trampoline()) return;
|
||||
if (!code.has_instruction_stream()) return;
|
||||
InstructionStream instruction_stream = FromCode(code);
|
||||
counters->wasm_generated_code_size()->Increment(
|
||||
instruction_stream.raw_body_size());
|
||||
|
@ -899,7 +899,6 @@ WasmCode* NativeModule::AddCodeForTesting(Handle<InstructionStream> code) {
|
||||
source_pos_table->copy_out(0, source_pos.begin(),
|
||||
source_pos_table->length());
|
||||
}
|
||||
CHECK(!code->is_off_heap_trampoline());
|
||||
static_assert(InstructionStream::kOnHeapBodyIsContiguous);
|
||||
base::Vector<const byte> instructions(
|
||||
reinterpret_cast<byte*>(code->raw_body_start()),
|
||||
|
Loading…
Reference in New Issue
Block a user