[heap] Support off-heap code in address-to-code lookups
Off-heap code may have pc values that are not within [instruction_start, instruction_end]. Handle these kinds of objects in heap Code lookup functions. Bug: v8:6666 Change-Id: Ib7a58f962ef6311c48234e506a35485fd5966814 Reviewed-on: https://chromium-review.googlesource.com/934184 Commit-Queue: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Cr-Commit-Position: refs/heads/master@{#51518}
This commit is contained in:
parent
f8569ff38a
commit
97adad01a3
@ -11,6 +11,7 @@
|
||||
#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"
|
||||
@ -394,8 +395,20 @@ Code* GetContainingCode(Isolate* isolate, Address pc) {
|
||||
|
||||
Code* StackFrame::LookupCode() const {
|
||||
Code* result = GetContainingCode(isolate(), pc());
|
||||
DCHECK_GE(pc(), result->instruction_start());
|
||||
DCHECK_LT(pc(), result->instruction_end());
|
||||
#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
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "src/heap/stress-marking-observer.h"
|
||||
#include "src/heap/stress-scavenge-observer.h"
|
||||
#include "src/heap/sweeper.h"
|
||||
#include "src/instruction-stream.h"
|
||||
#include "src/interpreter/interpreter.h"
|
||||
#include "src/objects/data-handler.h"
|
||||
#include "src/objects/shared-function-info.h"
|
||||
@ -6720,12 +6721,24 @@ Code* GcSafeCastToCode(Heap* heap, HeapObject* object, Address inner_pointer) {
|
||||
bool Heap::GcSafeCodeContains(HeapObject* code, Address addr) {
|
||||
Map* map = GcSafeMapOfCodeSpaceObject(code);
|
||||
DCHECK(map == code->GetHeap()->code_map());
|
||||
#ifdef V8_EMBEDDED_BUILTINS
|
||||
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);
|
||||
return start <= addr && addr < end;
|
||||
}
|
||||
|
||||
Code* Heap::GcSafeFindCodeForInnerPointer(Address inner_pointer) {
|
||||
#ifdef V8_EMBEDDED_BUILTINS
|
||||
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.
|
||||
LargePage* large_page = lo_space()->FindPage(inner_pointer);
|
||||
if (large_page != nullptr) {
|
||||
|
@ -12,8 +12,10 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
InstructionStream::InstructionStream(Code* code) {
|
||||
DCHECK(Builtins::IsIsolateIndependent(code->builtin_index()));
|
||||
InstructionStream::InstructionStream(Code* code)
|
||||
: builtin_index_(code->builtin_index()) {
|
||||
DCHECK(Builtins::IsBuiltinId(builtin_index_));
|
||||
DCHECK(Builtins::IsOffHeapSafe(builtin_index_));
|
||||
const size_t page_size = AllocatePageSize();
|
||||
byte_length_ =
|
||||
RoundUp(static_cast<size_t>(code->instruction_size()), page_size);
|
||||
@ -30,5 +32,36 @@ InstructionStream::~InstructionStream() {
|
||||
CHECK(FreePages(bytes_, byte_length_));
|
||||
}
|
||||
|
||||
// static
|
||||
Code* InstructionStream::TryLookupCode(Isolate* isolate, Address address) {
|
||||
DCHECK(FLAG_stress_off_heap_code);
|
||||
// TODO(jgruber,v8:6666): Replace with binary search through range checks
|
||||
// once off-heap code is mapped into a contiguous memory space.
|
||||
for (const InstructionStream* stream : isolate->off_heap_code_) {
|
||||
if (stream->Contains(address)) {
|
||||
return isolate->builtins()->builtin(stream->builtin_index());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
InstructionStream* InstructionStream::TryLookupInstructionStream(
|
||||
Isolate* isolate, Code* code) {
|
||||
DCHECK(FLAG_stress_off_heap_code);
|
||||
// TODO(jgruber,v8:6666): Replace with binary search through range checks
|
||||
// once off-heap code is mapped into a contiguous memory space.
|
||||
const int builtin_index = code->builtin_index();
|
||||
DCHECK(Builtins::IsBuiltinId(builtin_index));
|
||||
for (InstructionStream* stream : isolate->off_heap_code_) {
|
||||
if (stream->builtin_index() == builtin_index) return stream;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool InstructionStream::Contains(Address address) const {
|
||||
return bytes_ <= address && address < bytes_ + byte_length_;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -6,11 +6,13 @@
|
||||
#define V8_INSTRUCTION_STREAM_H_
|
||||
|
||||
#include "src/base/macros.h"
|
||||
#include "src/globals.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class Code;
|
||||
class Isolate;
|
||||
|
||||
// Wraps an mmap'ed off-heap instruction stream. This class will likely become
|
||||
// unneeded once --stress-off-heap-code is removed.
|
||||
@ -19,12 +21,23 @@ class InstructionStream final {
|
||||
explicit InstructionStream(Code* code);
|
||||
~InstructionStream();
|
||||
|
||||
// Returns the corresponding Code object if it exists, and nullptr otherwise.
|
||||
static Code* TryLookupCode(Isolate* isolate, Address address);
|
||||
|
||||
// Returns the corresponding stream if it exists, and nullptr otherwise.
|
||||
static InstructionStream* TryLookupInstructionStream(Isolate* isolate,
|
||||
Code* code);
|
||||
|
||||
bool Contains(Address address) const;
|
||||
|
||||
int builtin_index() const { return builtin_index_; }
|
||||
size_t byte_length() const { return byte_length_; }
|
||||
uint8_t* bytes() const { return bytes_; }
|
||||
|
||||
private:
|
||||
size_t byte_length_;
|
||||
uint8_t* bytes_;
|
||||
int builtin_index_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(InstructionStream)
|
||||
};
|
||||
|
@ -1621,7 +1621,7 @@ class Isolate {
|
||||
// Stores off-heap instruction streams. Only used if --stress-off-heap-code
|
||||
// is enabled.
|
||||
// TODO(jgruber,v8:6666): Remove once isolate-independent builtins are
|
||||
// implemented.
|
||||
// implemented. Also remove friend class below.
|
||||
std::vector<InstructionStream*> off_heap_code_;
|
||||
|
||||
#ifdef V8_EMBEDDED_BUILTINS
|
||||
@ -1658,17 +1658,18 @@ class Isolate {
|
||||
friend class ExecutionAccess;
|
||||
friend class HandleScopeImplementer;
|
||||
friend class heap::HeapTester;
|
||||
friend class InstructionStream;
|
||||
friend class OptimizingCompileDispatcher;
|
||||
friend class SweeperThread;
|
||||
friend class ThreadManager;
|
||||
friend class Simulator;
|
||||
friend class StackGuard;
|
||||
friend class SweeperThread;
|
||||
friend class TestIsolate;
|
||||
friend class ThreadId;
|
||||
friend class ThreadManager;
|
||||
friend class v8::Isolate;
|
||||
friend class v8::Locker;
|
||||
friend class v8::Unlocker;
|
||||
friend class v8::SnapshotCreator;
|
||||
friend class v8::Unlocker;
|
||||
friend v8::StartupData v8::V8::CreateSnapshotDataBlob(const char*);
|
||||
friend v8::StartupData v8::V8::WarmUpSnapshotDataBlob(v8::StartupData,
|
||||
const char*);
|
||||
|
Loading…
Reference in New Issue
Block a user