Commit 0ad8033b authored by jgruber's avatar jgruber Committed by Commit Bot

[code] Add Code::Instruction{Start,End,Size} helpers

These helpers support off-heap code objects, for which they return
start, end, and size of the off-heap instruction stream.

Bug: v8:6666
Change-Id: Ib5e819d976eee3073b0354b8d8ce324b691f1b15
Reviewed-on: https://chromium-review.googlesource.com/937281
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51572}
parent d6a88d05
......@@ -199,6 +199,17 @@ bool Builtins::IsBuiltin(Code* code) {
return Builtins::IsBuiltinId(code->builtin_index());
}
// static
bool Builtins::IsOffHeapBuiltin(Code* code) {
#ifdef V8_EMBEDDED_BUILTINS
return FLAG_stress_off_heap_code &&
Builtins::IsBuiltinId(code->builtin_index()) &&
Builtins::IsOffHeapSafe(code->builtin_index());
#else
return false;
#endif
}
// static
bool Builtins::IsLazy(int index) {
DCHECK(IsBuiltinId(index));
......
......@@ -113,6 +113,9 @@ class Builtins {
// necessarily mean that its kind is Code::BUILTIN.
static bool IsBuiltin(Code* code);
// True, iff the given code object is a builtin with off-heap code.
static bool IsOffHeapBuiltin(Code* code);
// Returns true iff the given builtin can be lazy-loaded from the snapshot.
// This is true in general for most builtins with the exception of a few
// special cases such as CompileLazy and DeserializeLazy.
......
......@@ -13,7 +13,6 @@
#include "src/disasm.h"
#include "src/frames-inl.h"
#include "src/global-handles.h"
#include "src/instruction-stream.h"
#include "src/interpreter/interpreter.h"
#include "src/macro-assembler.h"
#include "src/objects/debug-objects-inl.h"
......@@ -958,9 +957,8 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
(!is_topmost || (bailout_type_ == LAZY)) && !goto_catch_handler
? builtins->builtin(Builtins::kInterpreterEnterBytecodeAdvance)
: builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
// TODO(jgruber,v8:6666): Update logic once builtin is off-heap-safe.
DCHECK(!Builtins::IsOffHeapSafe(dispatch_builtin->builtin_index()));
output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry()));
output_frame->SetPc(
reinterpret_cast<intptr_t>(dispatch_builtin->InstructionStart()));
// Update constant pool.
if (FLAG_enable_embedded_constant_pool) {
......@@ -984,7 +982,7 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
// Set the continuation for the topmost frame.
Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
output_frame->SetContinuation(
reinterpret_cast<intptr_t>(continuation->entry()));
reinterpret_cast<intptr_t>(continuation->InstructionStart()));
}
}
......@@ -1117,17 +1115,8 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(
Builtins* builtins = isolate_->builtins();
Code* adaptor_trampoline =
builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
Address adaptor_trampoline_entry = adaptor_trampoline->instruction_start();
#ifdef V8_EMBEDDED_BUILTINS
if (FLAG_stress_off_heap_code) {
DCHECK(Builtins::IsOffHeapSafe(Builtins::kArgumentsAdaptorTrampoline));
InstructionStream* stream = InstructionStream::TryLookupInstructionStream(
isolate(), adaptor_trampoline);
adaptor_trampoline_entry = stream->bytes();
}
#endif // V8_EMBEDDED_BUILTINS
intptr_t pc_value = reinterpret_cast<intptr_t>(
adaptor_trampoline_entry +
adaptor_trampoline->InstructionStart() +
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
output_frame->SetPc(pc_value);
if (FLAG_enable_embedded_constant_pool) {
......@@ -1147,11 +1136,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
CHECK(!is_topmost || bailout_type_ == LAZY);
int input_index = 0;
// TODO(jgruber,v8:6666): Update logic once builtin is off-heap-safe.
DCHECK(!Builtins::IsOffHeapSafe(
Builtins::kJSConstructStubGenericRestrictedReturn));
DCHECK(!Builtins::IsOffHeapSafe(
Builtins::kJSConstructStubGenericUnrestrictedReturn));
Builtins* builtins = isolate_->builtins();
Code* construct_stub = builtins->builtin(
FLAG_harmony_restrict_constructor_return
......@@ -1321,7 +1305,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
// Compute this frame's PC.
DCHECK(bailout_id.IsValidForConstructStub());
Address start = construct_stub->instruction_start();
Address start = construct_stub->InstructionStart();
int pc_offset =
bailout_id == BailoutId::ConstructStubCreate()
? isolate_->heap()->construct_stub_create_deopt_pc_offset()->value()
......@@ -1356,7 +1340,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
DCHECK_EQ(LAZY, bailout_type_);
Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
output_frame->SetContinuation(
reinterpret_cast<intptr_t>(continuation->entry()));
reinterpret_cast<intptr_t>(continuation->InstructionStart()));
}
}
......@@ -1705,15 +1689,13 @@ void Deoptimizer::DoComputeBuiltinContinuation(
Builtins::kContinueToCodeStubBuiltinWithResult)
: isolate()->builtins()->builtin(
Builtins::kContinueToCodeStubBuiltin));
// TODO(jgruber,v8:6666): Update logic once builtin is off-heap-safe.
DCHECK(!Builtins::IsOffHeapSafe(continue_to_builtin->builtin_index()));
output_frame->SetPc(
reinterpret_cast<intptr_t>(continue_to_builtin->instruction_start()));
reinterpret_cast<intptr_t>(continue_to_builtin->InstructionStart()));
Code* continuation =
isolate()->builtins()->builtin(Builtins::kNotifyDeoptimized);
output_frame->SetContinuation(
reinterpret_cast<intptr_t>(continuation->entry()));
reinterpret_cast<intptr_t>(continuation->InstructionStart()));
}
void Deoptimizer::MaterializeHeapObjects() {
......@@ -2307,7 +2289,7 @@ DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
CHECK(code->instruction_start() <= pc && pc <= code->instruction_end());
CHECK(code->InstructionStart() <= pc && pc <= code->InstructionEnd());
SourcePosition last_position = SourcePosition::Unknown();
DeoptimizeReason last_reason = DeoptimizeReason::kUnknown;
int last_deopt_id = kNoDeoptimizationId;
......
......@@ -11,7 +11,6 @@
#include "src/deoptimizer.h"
#include "src/frames-inl.h"
#include "src/ic/ic-stats.h"
#include "src/instruction-stream.h"
#include "src/register-configuration.h"
#include "src/safepoint-table.h"
#include "src/string-stream.h"
......@@ -171,10 +170,6 @@ bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
namespace {
bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
// TODO(jgruber,v8:6666): Update logic once builtin is off-heap-safe.
DCHECK(!Builtins::IsOffHeapSafe(Builtins::kInterpreterEntryTrampoline));
DCHECK(!Builtins::IsOffHeapSafe(Builtins::kInterpreterEnterBytecodeAdvance));
DCHECK(!Builtins::IsOffHeapSafe(Builtins::kInterpreterEnterBytecodeDispatch));
Code* interpreter_entry_trampoline =
isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
Code* interpreter_bytecode_advance =
......@@ -182,12 +177,12 @@ bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
Code* interpreter_bytecode_dispatch =
isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
return (pc >= interpreter_entry_trampoline->instruction_start() &&
pc < interpreter_entry_trampoline->instruction_end()) ||
(pc >= interpreter_bytecode_advance->instruction_start() &&
pc < interpreter_bytecode_advance->instruction_end()) ||
(pc >= interpreter_bytecode_dispatch->instruction_start() &&
pc < interpreter_bytecode_dispatch->instruction_end());
return (pc >= interpreter_entry_trampoline->InstructionStart() &&
pc < interpreter_entry_trampoline->InstructionEnd()) ||
(pc >= interpreter_bytecode_advance->InstructionStart() &&
pc < interpreter_bytecode_advance->InstructionEnd()) ||
(pc >= interpreter_bytecode_dispatch->InstructionStart() &&
pc < interpreter_bytecode_dispatch->InstructionEnd());
}
DISABLE_ASAN Address ReadMemoryAt(Address address) {
......@@ -395,20 +390,8 @@ Code* GetContainingCode(Isolate* isolate, Address pc) {
Code* StackFrame::LookupCode() const {
Code* result = GetContainingCode(isolate(), pc());
#ifdef DEBUG
Address start = result->instruction_start();
Address end = result->instruction_end();
if (FLAG_stress_off_heap_code) {
InstructionStream* stream =
InstructionStream::TryLookupInstructionStream(isolate(), result);
if (stream != nullptr) {
start = stream->bytes();
end = start + stream->byte_length();
}
}
DCHECK_GE(pc(), start);
DCHECK_LT(pc(), end);
#endif
DCHECK_GE(pc(), result->InstructionStart());
DCHECK_LT(pc(), result->InstructionEnd());
return result;
}
......@@ -416,12 +399,12 @@ void StackFrame::IteratePc(RootVisitor* v, Address* pc_address,
Address* constant_pool_address, Code* holder) {
Address pc = *pc_address;
DCHECK(holder->GetHeap()->GcSafeCodeContains(holder, pc));
unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
unsigned pc_offset = static_cast<unsigned>(pc - holder->InstructionStart());
Object* code = holder;
v->VisitRootPointer(Root::kTop, nullptr, &code);
if (code == holder) return;
holder = reinterpret_cast<Code*>(code);
pc = holder->instruction_start() + pc_offset;
pc = holder->InstructionStart() + pc_offset;
*pc_address = pc;
if (FLAG_enable_embedded_constant_pool && constant_pool_address) {
*constant_pool_address = holder->constant_pool();
......@@ -1000,7 +983,7 @@ int StubFrame::LookupExceptionHandlerInTable(int* stack_slots) {
DCHECK(code->is_turbofanned());
DCHECK_EQ(code->kind(), Code::BUILTIN);
HandlerTable* table = HandlerTable::cast(code->handler_table());
int pc_offset = static_cast<int>(pc() - code->entry());
int pc_offset = static_cast<int>(pc() - code->InstructionStart());
*stack_slots = code->stack_slots();
return table->LookupReturn(pc_offset);
}
......@@ -1065,7 +1048,7 @@ void JavaScriptFrame::GetFunctions(
void JavaScriptFrame::Summarize(std::vector<FrameSummary>* functions) const {
DCHECK(functions->empty());
Code* code = LookupCode();
int offset = static_cast<int>(pc() - code->instruction_start());
int offset = static_cast<int>(pc() - code->InstructionStart());
AbstractCode* abstract_code = AbstractCode::cast(code);
FrameSummary::JavaScriptFrameSummary summary(isolate(), receiver(),
function(), abstract_code,
......@@ -1151,7 +1134,7 @@ void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
code_offset = iframe->GetBytecodeOffset();
} else {
Code* code = frame->unchecked_code();
code_offset = static_cast<int>(frame->pc() - code->instruction_start());
code_offset = static_cast<int>(frame->pc() - code->InstructionStart());
}
PrintFunctionAndOffset(function, function->abstract_code(), code_offset,
file, print_line_number);
......@@ -1209,7 +1192,7 @@ void JavaScriptFrame::CollectTopFrameForICStats(Isolate* isolate) {
code_offset = iframe->GetBytecodeOffset();
} else {
Code* code = frame->unchecked_code();
code_offset = static_cast<int>(frame->pc() - code->instruction_start());
code_offset = static_cast<int>(frame->pc() - code->InstructionStart());
}
CollectFunctionAndOffsetForICStats(function, function->abstract_code(),
code_offset);
......@@ -1522,7 +1505,7 @@ int OptimizedFrame::LookupExceptionHandlerInTable(
DCHECK_NULL(prediction);
Code* code = LookupCode();
HandlerTable* table = HandlerTable::cast(code->handler_table());
int pc_offset = static_cast<int>(pc() - code->entry());
int pc_offset = static_cast<int>(pc() - code->InstructionStart());
if (stack_slots) *stack_slots = code->stack_slots();
// When the return pc has been replaced by a trampoline there won't be
......
......@@ -14,8 +14,7 @@ namespace internal {
InstructionStream::InstructionStream(Code* code)
: builtin_index_(code->builtin_index()) {
DCHECK(Builtins::IsBuiltinId(builtin_index_));
DCHECK(Builtins::IsOffHeapSafe(builtin_index_));
DCHECK(Builtins::IsOffHeapBuiltin(code));
const size_t page_size = AllocatePageSize();
byte_length_ =
RoundUp(static_cast<size_t>(code->instruction_size()), page_size);
......
......@@ -1267,7 +1267,7 @@ Object* Isolate::UnwindAndFindHandler() {
// Gather information from the handler.
Code* code = frame->LookupCode();
return FoundHandler(
nullptr, code->instruction_start(),
nullptr, code->InstructionStart(),
Smi::ToInt(code->handler_table()->get(0)), code->constant_pool(),
handler->address() + StackHandlerConstants::kSize, 0);
}
......@@ -1336,7 +1336,7 @@ Object* Isolate::UnwindAndFindHandler() {
set_deoptimizer_lazy_throw(true);
}
return FoundHandler(nullptr, code->instruction_start(), offset,
return FoundHandler(nullptr, code->InstructionStart(), offset,
code->constant_pool(), return_sp, frame->fp());
}
......@@ -1360,7 +1360,7 @@ Object* Isolate::UnwindAndFindHandler() {
StandardFrameConstants::kFixedFrameSizeAboveFp -
stack_slots * kPointerSize;
return FoundHandler(nullptr, code->instruction_start(), offset,
return FoundHandler(nullptr, code->InstructionStart(), offset,
code->constant_pool(), return_sp, frame->fp());
}
......@@ -1393,7 +1393,7 @@ Object* Isolate::UnwindAndFindHandler() {
Code* code =
builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
return FoundHandler(context, code->instruction_start(), 0,
return FoundHandler(context, code->InstructionStart(), 0,
code->constant_pool(), return_sp, frame->fp());
}
......@@ -2925,8 +2925,6 @@ void MoveBuiltinsOffHeap(Isolate* isolate) {
HandleScope scope(isolate);
Builtins* builtins = isolate->builtins();
// TODO(jgruber): Support stack iteration with off-heap on-stack builtins.
// Lazy deserialization would defeat our off-heap stress test (we'd
// deserialize later without moving off-heap), so force eager
// deserialization.
......
......@@ -14029,6 +14029,26 @@ SafepointEntry Code::GetSafepointEntry(Address pc) {
return table.FindEntry(pc);
}
int Code::OffHeapInstructionSize() {
DCHECK(Builtins::IsOffHeapBuiltin(this));
InstructionStream* stream =
InstructionStream::TryLookupInstructionStream(GetIsolate(), this);
return static_cast<int>(stream->byte_length());
}
Address Code::OffHeapInstructionStart() {
DCHECK(Builtins::IsOffHeapBuiltin(this));
InstructionStream* stream =
InstructionStream::TryLookupInstructionStream(GetIsolate(), this);
return stream->bytes();
}
Address Code::OffHeapInstructionEnd() {
DCHECK(Builtins::IsOffHeapBuiltin(this));
InstructionStream* stream =
InstructionStream::TryLookupInstructionStream(GetIsolate(), this);
return stream->bytes() + stream->byte_length();
}
namespace {
template <typename Code>
......
......@@ -204,14 +204,35 @@ void Code::set_next_code_link(Object* value) {
code_data_container()->set_next_code_link(value);
}
int Code::InstructionSize() {
#ifdef V8_EMBEDDED_BUILTINS
if (Builtins::IsOffHeapBuiltin(this)) return OffHeapInstructionSize();
#endif
return instruction_size();
}
byte* Code::instruction_start() const {
return const_cast<byte*>(FIELD_ADDR_CONST(this, kHeaderSize));
}
Address Code::InstructionStart() {
#ifdef V8_EMBEDDED_BUILTINS
if (Builtins::IsOffHeapBuiltin(this)) return OffHeapInstructionStart();
#endif
return instruction_start();
}
byte* Code::instruction_end() const {
return instruction_start() + instruction_size();
}
Address Code::InstructionEnd() {
#ifdef V8_EMBEDDED_BUILTINS
if (Builtins::IsOffHeapBuiltin(this)) return OffHeapInstructionEnd();
#endif
return instruction_end();
}
int Code::GetUnwindingInfoSizeOffset() const {
DCHECK(has_unwinding_info());
return RoundUp(kHeaderSize + instruction_size(), kInt64Size);
......
......@@ -138,10 +138,19 @@ class Code : public HeapObject {
void* current_pc = nullptr); // NOLINT
#endif
// [instruction_size]: Size of the native instructions
// [instruction_size]: Size of the native instructions, including embedded
// data such as the safepoints table.
inline int instruction_size() const;
inline void set_instruction_size(int value);
// Returns the size of the native instructions, including embedded
// data such as the safepoints table. For off-heap code objects
// this may 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();
int OffHeapInstructionSize();
// [relocation_info]: Code relocation information
DECL_ACCESSORS(relocation_info, ByteArray)
void InvalidateEmbeddedObjects();
......@@ -297,9 +306,21 @@ class Code : public HeapObject {
// Returns the address of the first instruction.
inline byte* instruction_start() const;
// 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();
Address OffHeapInstructionStart();
// Returns the address right after the last instruction.
inline byte* instruction_end() const;
// 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();
Address OffHeapInstructionEnd();
// Returns the size of the instructions, padding, relocation and unwinding
// information.
inline int body_size() const;
......
......@@ -8,7 +8,6 @@
#include "src/deoptimizer.h"
#include "src/disasm.h"
#include "src/frames-inl.h"
#include "src/instruction-stream.h"
#include "src/macro-assembler.h"
#include "src/ostreams.h"
......@@ -52,18 +51,8 @@ SafepointTable::SafepointTable(Address instruction_start,
}
SafepointTable::SafepointTable(Code* code)
: SafepointTable(code->instruction_start(), code->safepoint_table_offset(),
code->stack_slots(), true) {
#ifdef V8_EMBEDDED_BUILTINS
if (FLAG_stress_off_heap_code && Builtins::IsBuiltin(code) &&
Builtins::IsOffHeapSafe(code->builtin_index())) {
InstructionStream* stream =
InstructionStream::TryLookupInstructionStream(code->GetIsolate(), code);
DCHECK_NOT_NULL(stream);
instruction_start_ = static_cast<Address>(stream->bytes());
}
#endif
}
: SafepointTable(code->InstructionStart(), code->safepoint_table_offset(),
code->stack_slots(), true) {}
unsigned SafepointTable::find_return_pc(unsigned pc_offset) {
for (unsigned i = 0; i < length(); i++) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment