Commit 49b112e1 authored by bmeurer's avatar bmeurer Committed by Commit bot

Revert of Rebase GDBJIT interface solely on JITCodeEvent (patchset #2 id:20001...

Revert of Rebase GDBJIT interface solely on JITCodeEvent (patchset #2 id:20001 of https://codereview.chromium.org/957673004/)

Reason for revert:
Doesn't compile

Original issue's description:
> Rebase GDBJIT interface solely on JITCodeEvent
>
> R=mstarzinger@chromium.org
> BUG=
>
> Committed: https://chromium.googlesource.com/v8/v8/+/8989d828e86bc7edae5e25687bcb60c0e301dffb

TBR=mstarzinger@chromium.org,wingo@igalia.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=

Review URL: https://codereview.chromium.org/954833004

Cr-Commit-Position: refs/heads/master@{#26848}
parent 8989d828
......@@ -719,6 +719,10 @@ static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
CodeCreateEvent(log_tag, *code, *shared, info, script_name,
line_num, column_num));
}
GDBJIT(AddCode(Handle<String>(shared->DebugName()),
Handle<Script>(info->script()), Handle<Code>(info->code()),
info));
}
......@@ -1179,6 +1183,7 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
PROFILE(isolate, CodeCreateEvent(
log_tag, *info->code(), *result, info, *script_name));
GDBJIT(AddCode(script_name, script, info->code(), info));
// Hint to the runtime system used when allocating space for initial
// property space by setting the expected number of properties for
......
......@@ -752,14 +752,6 @@ DEFINE_NEG_IMPLICATION(predictable, concurrent_recompilation)
DEFINE_NEG_IMPLICATION(predictable, concurrent_osr)
DEFINE_NEG_IMPLICATION(predictable, concurrent_sweeping)
// mark-compact.cc
DEFINE_BOOL(force_marking_deque_overflows, false,
"force overflows of marking deque by reducing it's size "
"to 64 words")
DEFINE_BOOL(stress_compaction, false,
"stress the GC compactor to flush out bugs (implies "
"--force_marking_deque_overflows)")
//
// Dev shell flags
......@@ -777,24 +769,21 @@ DEFINE_ARGS(js_arguments,
//
// GDB JIT integration flags.
//
#undef FLAG
#ifdef ENABLE_GDB_JIT_INTERFACE
#define FLAG FLAG_FULL
#else
#define FLAG FLAG_READONLY
#endif
DEFINE_BOOL(gdbjit, false, "enable GDBJIT interface")
DEFINE_BOOL(gdbjit, false, "enable GDBJIT interface (disables compacting GC)")
DEFINE_BOOL(gdbjit_full, false, "enable GDBJIT interface for all code objects")
DEFINE_BOOL(gdbjit_dump, false, "dump elf objects with debug info to disk")
DEFINE_STRING(gdbjit_dump_filter, "",
"dump only objects containing this substring")
#ifdef ENABLE_GDB_JIT_INTERFACE
DEFINE_IMPLICATION(gdbjit_full, gdbjit)
DEFINE_IMPLICATION(gdbjit_dump, gdbjit)
#endif
DEFINE_NEG_IMPLICATION(gdbjit, compact_code_space)
// mark-compact.cc
DEFINE_BOOL(force_marking_deque_overflows, false,
"force overflows of marking deque by reducing it's size "
"to 64 words")
DEFINE_BOOL(stress_compaction, false,
"stress the GC compactor to flush out bugs (implies "
"--force_marking_deque_overflows)")
//
// Debug only flags
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef ENABLE_GDB_JIT_INTERFACE
#include "src/v8.h"
#include "src/base/bits.h"
......@@ -14,14 +15,11 @@
#include "src/global-handles.h"
#include "src/messages.h"
#include "src/natives.h"
#include "src/objects.h"
#include "src/ostreams.h"
#include "src/scopes.h"
namespace v8 {
namespace internal {
namespace GDBJITInterface {
#ifdef ENABLE_GDB_JIT_INTERFACE
#ifdef __APPLE__
#define __MACH_O
......@@ -935,9 +933,15 @@ class CodeDescription BASE_EMBEDDED {
};
#endif
CodeDescription(const char* name, Code* code, SharedFunctionInfo* shared,
LineInfo* lineinfo)
: name_(name), code_(code), shared_info_(shared), lineinfo_(lineinfo) {}
CodeDescription(const char* name, Code* code, Handle<Script> script,
LineInfo* lineinfo, GDBJITInterface::CodeTag tag,
CompilationInfo* info)
: name_(name),
code_(code),
script_(script),
lineinfo_(lineinfo),
tag_(tag),
info_(info) {}
const char* name() const {
return name_;
......@@ -945,16 +949,16 @@ class CodeDescription BASE_EMBEDDED {
LineInfo* lineinfo() const { return lineinfo_; }
bool is_function() const {
Code::Kind kind = code_->kind();
return kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION;
GDBJITInterface::CodeTag tag() const {
return tag_;
}
bool has_scope_info() const { return shared_info_ != NULL; }
CompilationInfo* info() const {
return info_;
}
ScopeInfo* scope_info() const {
DCHECK(has_scope_info());
return shared_info_->scope_info();
bool IsInfoAvailable() const {
return info_ != NULL;
}
uintptr_t CodeStart() const {
......@@ -969,15 +973,11 @@ class CodeDescription BASE_EMBEDDED {
return CodeEnd() - CodeStart();
}
bool has_script() {
return shared_info_ != NULL && shared_info_->script()->IsScript();
}
Script* script() { return Script::cast(shared_info_->script()); }
bool IsLineInfoAvailable() {
return has_script() && script()->source()->IsString() &&
script()->HasValidSource() && script()->name()->IsString() &&
return !script_.is_null() &&
script_->source()->IsString() &&
script_->HasValidSource() &&
script_->name()->IsString() &&
lineinfo_ != NULL;
}
......@@ -994,17 +994,21 @@ class CodeDescription BASE_EMBEDDED {
#endif
SmartArrayPointer<char> GetFilename() {
return String::cast(script()->name())->ToCString();
return String::cast(script_->name())->ToCString();
}
int GetScriptLineNumber(int pos) { return script()->GetLineNumber(pos) + 1; }
int GetScriptLineNumber(int pos) {
return script_->GetLineNumber(pos) + 1;
}
private:
const char* name_;
Code* code_;
SharedFunctionInfo* shared_info_;
Handle<Script> script_;
LineInfo* lineinfo_;
GDBJITInterface::CodeTag tag_;
CompilationInfo* info_;
#if V8_TARGET_ARCH_X64
uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
#endif
......@@ -1091,8 +1095,8 @@ class DebugInfoSection : public DebugSection {
w->Write<uint8_t>(kPointerSize);
w->WriteString("v8value");
if (desc_->has_scope_info()) {
ScopeInfo* scope = desc_->scope_info();
if (desc_->IsInfoAvailable()) {
Scope* scope = desc_->info()->scope();
w->WriteULEB128(2);
w->WriteString(desc_->name());
w->Write<intptr_t>(desc_->CodeStart());
......@@ -1114,8 +1118,8 @@ class DebugInfoSection : public DebugSection {
#endif
fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
int params = scope->ParameterCount();
int slots = scope->StackLocalCount();
int params = scope->num_parameters();
int slots = scope->num_stack_slots();
int context_slots = scope->ContextLocalCount();
// The real slot ID is internal_slots + context_slot_id.
int internal_slots = Context::MIN_CONTEXT_SLOTS;
......@@ -1125,7 +1129,7 @@ class DebugInfoSection : public DebugSection {
for (int param = 0; param < params; ++param) {
w->WriteULEB128(current_abbreviation++);
w->WriteString(
scope->ParameterName(param)->ToCString(DISALLOW_NULLS).get());
scope->parameter(param)->name()->ToCString(DISALLOW_NULLS).get());
w->Write<uint32_t>(ty_offset);
Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
uintptr_t block_start = w->position();
......@@ -1170,10 +1174,13 @@ class DebugInfoSection : public DebugSection {
w->WriteString(builder.Finalize());
}
ZoneList<Variable*> stack_locals(locals, scope->zone());
ZoneList<Variable*> context_locals(context_slots, scope->zone());
scope->CollectStackAndContextLocals(&stack_locals, &context_locals);
for (int local = 0; local < locals; ++local) {
w->WriteULEB128(current_abbreviation++);
w->WriteString(
scope->StackLocalName(local)->ToCString(DISALLOW_NULLS).get());
stack_locals[local]->name()->ToCString(DISALLOW_NULLS).get());
w->Write<uint32_t>(ty_offset);
Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
uintptr_t block_start = w->position();
......@@ -1295,7 +1302,7 @@ class DebugAbbrevSection : public DebugSection {
bool WriteBodyInternal(Writer* w) {
int current_abbreviation = 1;
bool extra_info = desc_->has_scope_info();
bool extra_info = desc_->IsInfoAvailable();
DCHECK(desc_->IsLineInfoAvailable());
w->WriteULEB128(current_abbreviation++);
w->WriteULEB128(DW_TAG_COMPILE_UNIT);
......@@ -1312,9 +1319,9 @@ class DebugAbbrevSection : public DebugSection {
w->WriteULEB128(0);
if (extra_info) {
ScopeInfo* scope = desc_->scope_info();
int params = scope->ParameterCount();
int slots = scope->StackLocalCount();
Scope* scope = desc_->info()->scope();
int params = scope->num_parameters();
int slots = scope->num_stack_slots();
int context_slots = scope->ContextLocalCount();
// The real slot ID is internal_slots + context_slot_id.
int internal_slots = Context::MIN_CONTEXT_SLOTS;
......@@ -1861,7 +1868,27 @@ static void DestroyCodeEntry(JITCodeEntry* entry) {
}
static void RegisterCodeEntry(JITCodeEntry* entry) {
static void RegisterCodeEntry(JITCodeEntry* entry,
bool dump_if_enabled,
const char* name_hint) {
#if defined(DEBUG) && !V8_OS_WIN
static int file_num = 0;
if (FLAG_gdbjit_dump && dump_if_enabled) {
static const int kMaxFileNameSize = 64;
static const char* kElfFilePrefix = "/tmp/elfdump";
static const char* kObjFileExt = ".o";
char file_name[64];
SNPrintF(Vector<char>(file_name, kMaxFileNameSize),
"%s%s%d%s",
kElfFilePrefix,
(name_hint != NULL) ? name_hint : "",
file_num++,
kObjFileExt);
WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
}
#endif
entry->next_ = __jit_debug_descriptor.first_entry_;
if (entry->next_ != NULL) entry->next_->prev_ = entry;
__jit_debug_descriptor.first_entry_ =
......@@ -1928,67 +1955,69 @@ static JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) {
}
struct AddressRange {
Address start;
Address end;
};
static bool SameCodeObjects(void* key1, void* key2) {
return key1 == key2;
}
class JITCodeEntry;
struct SplayTreeConfig {
typedef AddressRange Key;
typedef JITCodeEntry* Value;
static const AddressRange kNoKey;
static Value NoValue() { return NULL; }
static int Compare(const AddressRange& a, const AddressRange& b) {
// ptrdiff_t probably doesn't fit in an int.
if (a.start < b.start) return -1;
if (a.start == b.start) return 0;
return 1;
static HashMap* GetEntries() {
static HashMap* entries = NULL;
if (entries == NULL) {
entries = new HashMap(&SameCodeObjects);
}
};
return entries;
}
const AddressRange SplayTreeConfig::kNoKey = {0, 0};
typedef SplayTree<SplayTreeConfig> CodeMap;
static CodeMap* GetCodeMap() {
static CodeMap* code_map = NULL;
if (code_map == NULL) code_map = new CodeMap();
return code_map;
static uint32_t HashForCodeObject(Code* code) {
static const uintptr_t kGoldenRatio = 2654435761u;
uintptr_t hash = reinterpret_cast<uintptr_t>(code->address());
return static_cast<uint32_t>((hash >> kCodeAlignmentBits) * kGoldenRatio);
}
static uint32_t HashCodeAddress(Address addr) {
static const intptr_t kGoldenRatio = 2654435761;
uintptr_t offset = OffsetFrom(addr);
return static_cast<uint32_t>((offset >> kCodeAlignmentBits) * kGoldenRatio);
static const intptr_t kLineInfoTag = 0x1;
static bool IsLineInfoTagged(void* ptr) {
return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag);
}
static HashMap* GetLineMap() {
static HashMap* line_map = NULL;
if (line_map == NULL) line_map = new HashMap(&HashMap::PointersMatch);
return line_map;
static void* TagLineInfo(LineInfo* ptr) {
return reinterpret_cast<void*>(
reinterpret_cast<intptr_t>(ptr) | kLineInfoTag);
}
static void PutLineInfo(Address addr, LineInfo* info) {
HashMap* line_map = GetLineMap();
HashMap::Entry* e = line_map->Lookup(addr, HashCodeAddress(addr), true);
if (e->value != NULL) delete static_cast<LineInfo*>(e->value);
e->value = info;
static LineInfo* UntagLineInfo(void* ptr) {
return reinterpret_cast<LineInfo*>(reinterpret_cast<intptr_t>(ptr) &
~kLineInfoTag);
}
static LineInfo* GetLineInfo(Address addr) {
void* value = GetLineMap()->Remove(addr, HashCodeAddress(addr));
return static_cast<LineInfo*>(value);
void GDBJITInterface::AddCode(Handle<Name> name,
Handle<Script> script,
Handle<Code> code,
CompilationInfo* info) {
if (!FLAG_gdbjit) return;
Script::InitLineEnds(script);
if (!name.is_null() && name->IsString()) {
SmartArrayPointer<char> name_cstring =
Handle<String>::cast(name)->ToCString(DISALLOW_NULLS);
AddCode(name_cstring.get(), *code, GDBJITInterface::FUNCTION, *script,
info);
} else {
AddCode("", *code, GDBJITInterface::FUNCTION, *script, info);
}
}
static void AddUnwindInfo(CodeDescription* desc) {
#if V8_TARGET_ARCH_X64
if (desc->is_function()) {
if (desc->tag() == GDBJITInterface::FUNCTION) {
// To avoid propagating unwinding information through
// compilation pipeline we use an approximation.
// For most use cases this should not affect usability.
......@@ -2026,83 +2055,39 @@ static void AddUnwindInfo(CodeDescription* desc) {
static base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
// Remove entries from the splay tree that intersect the given address range,
// and deregister them from GDB.
static void RemoveJITCodeEntries(CodeMap* map, const AddressRange& range) {
DCHECK(range.start < range.end);
CodeMap::Locator cur;
if (map->FindGreatestLessThan(range, &cur) || map->FindLeast(&cur)) {
// Skip entries that are entirely less than the range of interest.
while (cur.key().end <= range.start) {
// CodeMap::FindLeastGreaterThan succeeds for entries whose key is greater
// than _or equal to_ the given key, so we have to advance our key to get
// the next one.
AddressRange new_key;
new_key.start = cur.key().end;
new_key.end = 0;
if (!map->FindLeastGreaterThan(new_key, &cur)) return;
}
// Evict intersecting ranges.
while (cur.key().start < range.end) {
AddressRange old_range = cur.key();
JITCodeEntry* old_entry = cur.value();
UnregisterCodeEntry(old_entry);
DestroyCodeEntry(old_entry);
CHECK(map->Remove(old_range));
if (!map->FindLeastGreaterThan(old_range, &cur)) return;
}
}
}
// Insert the entry into the splay tree and register it with GDB.
static void AddJITCodeEntry(CodeMap* map, const AddressRange& range,
JITCodeEntry* entry, bool dump_if_enabled,
const char* name_hint) {
#if defined(DEBUG) && !V8_OS_WIN
static int file_num = 0;
if (FLAG_gdbjit_dump && dump_if_enabled) {
static const int kMaxFileNameSize = 64;
char file_name[64];
SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "/tmp/elfdump%s%d.o",
(name_hint != NULL) ? name_hint : "", file_num++);
WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
}
#endif
CodeMap::Locator cur;
CHECK(map->Insert(range, &cur));
cur.set_value(entry);
RegisterCodeEntry(entry);
}
static void AddCode(const char* name, Code* code, SharedFunctionInfo* shared,
LineInfo* lineinfo) {
void GDBJITInterface::AddCode(const char* name,
Code* code,
GDBJITInterface::CodeTag tag,
Script* script,
CompilationInfo* info) {
base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
DisallowHeapAllocation no_gc;
CodeMap* code_map = GetCodeMap();
AddressRange range;
range.start = code->address();
range.end = code->address() + code->CodeSize();
RemoveJITCodeEntries(code_map, range);
HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
if (e->value != NULL && !IsLineInfoTagged(e->value)) return;
CodeDescription code_desc(name, code, shared, lineinfo);
LineInfo* lineinfo = UntagLineInfo(e->value);
CodeDescription code_desc(name,
code,
script != NULL ? Handle<Script>(script)
: Handle<Script>(),
lineinfo,
tag,
info);
if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
delete lineinfo;
GetEntries()->Remove(code, HashForCodeObject(code));
return;
}
AddUnwindInfo(&code_desc);
Isolate* isolate = code->GetIsolate();
JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
DCHECK(!IsLineInfoTagged(entry));
delete lineinfo;
e->value = entry;
const char* name_hint = NULL;
bool should_dump = false;
......@@ -2115,35 +2100,82 @@ static void AddCode(const char* name, Code* code, SharedFunctionInfo* shared,
should_dump = (name_hint != NULL);
}
}
AddJITCodeEntry(code_map, range, entry, should_dump, name_hint);
RegisterCodeEntry(entry, should_dump, name_hint);
}
void EventHandler(const v8::JitCodeEvent* event) {
void GDBJITInterface::RemoveCode(Code* code) {
if (!FLAG_gdbjit) return;
base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
HashMap::Entry* e = GetEntries()->Lookup(code,
HashForCodeObject(code),
false);
if (e == NULL) return;
if (IsLineInfoTagged(e->value)) {
delete UntagLineInfo(e->value);
} else {
JITCodeEntry* entry = static_cast<JITCodeEntry*>(e->value);
UnregisterCodeEntry(entry);
DestroyCodeEntry(entry);
}
e->value = NULL;
GetEntries()->Remove(code, HashForCodeObject(code));
}
void GDBJITInterface::RemoveCodeRange(Address start, Address end) {
HashMap* entries = GetEntries();
Zone zone;
ZoneList<Code*> dead_codes(1, &zone);
for (HashMap::Entry* e = entries->Start(); e != NULL; e = entries->Next(e)) {
Code* code = reinterpret_cast<Code*>(e->key);
if (code->address() >= start && code->address() < end) {
dead_codes.Add(code, &zone);
}
}
for (int i = 0; i < dead_codes.length(); i++) {
RemoveCode(dead_codes.at(i));
}
}
static void RegisterDetailedLineInfo(Code* code, LineInfo* line_info) {
base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
DCHECK(!IsLineInfoTagged(line_info));
HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
DCHECK(e->value == NULL);
e->value = TagLineInfo(line_info);
}
void GDBJITInterface::EventHandler(const v8::JitCodeEvent* event) {
if (!FLAG_gdbjit) return;
switch (event->type) {
case v8::JitCodeEvent::CODE_ADDED: {
Address addr = reinterpret_cast<Address>(event->code_start);
Code* code = Code::GetCodeFromTargetAddress(addr);
LineInfo* lineinfo = GetLineInfo(addr);
Code* code = Code::GetCodeFromTargetAddress(
reinterpret_cast<Address>(event->code_start));
if (code->kind() == Code::OPTIMIZED_FUNCTION ||
code->kind() == Code::FUNCTION) {
break;
}
EmbeddedVector<char, 256> buffer;
StringBuilder builder(buffer.start(), buffer.length());
builder.AddSubstring(event->name.str, static_cast<int>(event->name.len));
// It's called UnboundScript in the API but it's a SharedFunctionInfo.
SharedFunctionInfo* shared =
event->script.IsEmpty() ? NULL : *Utils::OpenHandle(*event->script);
AddCode(builder.Finalize(), code, shared, lineinfo);
AddCode(builder.Finalize(), code, NON_FUNCTION, NULL, NULL);
break;
}
case v8::JitCodeEvent::CODE_MOVED:
// Enabling the GDB JIT interface should disable code compaction.
UNREACHABLE();
break;
case v8::JitCodeEvent::CODE_REMOVED:
// Do nothing. Instead, adding code causes eviction of any entry whose
// address range intersects the address range of the added code.
case v8::JitCodeEvent::CODE_REMOVED: {
Code* code = Code::GetCodeFromTargetAddress(
reinterpret_cast<Address>(event->code_start));
RemoveCode(code);
break;
}
case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
......@@ -2159,12 +2191,14 @@ void EventHandler(const v8::JitCodeEvent* event) {
}
case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
PutLineInfo(reinterpret_cast<Address>(event->code_start), line_info);
Code* code = Code::GetCodeFromTargetAddress(
reinterpret_cast<Address>(event->code_start));
RegisterDetailedLineInfo(code, line_info);
break;
}
}
}
} } // namespace v8::internal
#endif
} // namespace GDBJITInterface
} // namespace internal
} // namespace v8
......@@ -5,35 +5,50 @@
#ifndef V8_GDB_JIT_H_
#define V8_GDB_JIT_H_
#include "src/v8.h"
#include "src/allocation.h"
//
// GDB has two ways of interacting with JIT code. With the "JIT compilation
// interface", V8 can tell GDB when it emits JIT code. Unfortunately to do so,
// it has to create platform-native object files, possibly with platform-native
// debugging information. Currently only ELF and Mach-O are supported, which
// limits this interface to Linux and Mac OS. This JIT compilation interface
// was introduced in GDB 7.0. V8 support can be enabled with the --gdbjit flag.
//
// The other way that GDB can know about V8 code is via the "custom JIT reader"
// interface, in which a GDB extension parses V8's private data to determine the
// function, file, and line of a JIT frame, and how to unwind those frames.
// This interface was introduced in GDB 7.6. This interface still relies on V8
// to register its code via the JIT compilation interface, but doesn't require
// that V8 create ELF images. Support will be added for this interface in the
// future.
// Basic implementation of GDB JIT Interface client.
// GBD JIT Interface is supported in GDB 7.0 and above.
// Currently on x64 and ia32 architectures and Linux OS are supported.
//
#ifdef ENABLE_GDB_JIT_INTERFACE
#include "src/v8.h"
#include "src/factory.h"
namespace v8 {
namespace internal {
namespace GDBJITInterface {
#ifdef ENABLE_GDB_JIT_INTERFACE
// JitCodeEventHandler that creates ELF/Mach-O objects and registers them with
// GDB.
void EventHandler(const v8::JitCodeEvent* event);
class CompilationInfo;
class GDBJITInterface: public AllStatic {
public:
enum CodeTag { NON_FUNCTION, FUNCTION };
// Main entry point into GDB JIT realized as a JitCodeEventHandler.
static void EventHandler(const v8::JitCodeEvent* event);
static void AddCode(Handle<Name> name,
Handle<Script> script,
Handle<Code> code,
CompilationInfo* info);
static void RemoveCodeRange(Address start, Address end);
private:
static void AddCode(const char* name, Code* code, CodeTag tag, Script* script,
CompilationInfo* info);
static void RemoveCode(Code* code);
};
#define GDBJIT(action) GDBJITInterface::action
} } // namespace v8::internal
#else
#define GDBJIT(action) ((void) 0)
#endif
} // namespace GDBJITInterface
} // namespace internal
} // namespace v8
#endif
......@@ -262,6 +262,11 @@ bool MarkCompactCollector::StartCompaction(CompactionMode mode) {
if (!compacting_) {
DCHECK(evacuation_candidates_.length() == 0);
#ifdef ENABLE_GDB_JIT_INTERFACE
// If GDBJIT interface is active disable compaction.
if (FLAG_gdbjit) return false;
#endif
CollectEvacuationCandidates(heap()->old_pointer_space());
CollectEvacuationCandidates(heap()->old_data_space());
......@@ -3218,6 +3223,11 @@ static int Sweep(PagedSpace* space, FreeList* free_list, Page* p,
}
freed_bytes = Free<parallelism>(space, free_list, free_start, size);
max_freed_bytes = Max(freed_bytes, max_freed_bytes);
#ifdef ENABLE_GDB_JIT_INTERFACE
if (FLAG_gdbjit && space->identity() == CODE_SPACE) {
GDBJITInterface::RemoveCodeRange(free_start, free_end);
}
#endif
}
HeapObject* live_object = HeapObject::FromAddress(free_end);
DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object)));
......@@ -3247,6 +3257,11 @@ static int Sweep(PagedSpace* space, FreeList* free_list, Page* p,
}
freed_bytes = Free<parallelism>(space, free_list, free_start, size);
max_freed_bytes = Max(freed_bytes, max_freed_bytes);
#ifdef ENABLE_GDB_JIT_INTERFACE
if (FLAG_gdbjit && space->identity() == CODE_SPACE) {
GDBJITInterface::RemoveCodeRange(free_start, p->area_end());
}
#endif
}
p->ResetLiveBytes();
......
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