[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:
jgruber 2018-02-23 14:34:08 +01:00 committed by Commit Bot
parent f8569ff38a
commit 97adad01a3
5 changed files with 81 additions and 8 deletions

View File

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

View File

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

View File

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

View File

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

View File

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