5 #ifdef ENABLE_GDB_JIT_INTERFACE
28 typedef MachO DebugObject;
29 typedef MachOSection DebugSection;
34 typedef ELF DebugObject;
35 typedef ELFSection DebugSection;
40 explicit Writer(DebugObject* debug_object)
41 : debug_object_(debug_object),
44 buffer_(reinterpret_cast<
byte*>(malloc(capacity_))) {
58 Slot(Writer* w,
uintptr_t offset) : w_(w), offset_(offset) { }
61 return w_->RawSlotAt<
T>(offset_);
64 void set(
const T& value) {
65 *w_->RawSlotAt<
T>(offset_) = value;
69 return Slot<T>(w_, offset_ +
sizeof(
T) *
i);
78 void Write(
const T& val) {
79 Ensure(position_ +
sizeof(
T));
80 *RawSlotAt<T>(position_) = val;
81 position_ +=
sizeof(
T);
86 Ensure(offset +
sizeof(
T));
87 return Slot<T>(
this, offset);
91 Slot<T> CreateSlotHere() {
92 return CreateSlotsHere<T>(1);
96 Slot<T> CreateSlotsHere(
uint32_t count) {
98 position_ +=
sizeof(
T) * count;
100 return SlotAt<T>(slot_position);
104 if (capacity_ < pos) {
105 while (capacity_ < pos) capacity_ *= 2;
106 buffer_ =
reinterpret_cast<byte*
>(realloc(buffer_, capacity_));
110 DebugObject* debug_object() {
return debug_object_; }
112 byte* buffer() {
return buffer_; }
116 if (delta == 0)
return;
118 Ensure(position_ += padding);
119 DCHECK((position_ % align) == 0);
124 uint8_t
byte = value & 0x7F;
126 if (value != 0)
byte |= 0x80;
127 Write<uint8_t>(
byte);
128 }
while (value != 0);
131 void WriteSLEB128(intptr_t value) {
134 int8_t
byte = value & 0x7F;
135 bool byte_sign =
byte & 0x40;
138 if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) {
148 void WriteString(
const char* str) {
155 template<
typename T>
friend class Slot;
159 DCHECK(offset < capacity_ && offset +
sizeof(
T) <= capacity_);
160 return reinterpret_cast<T*
>(&buffer_[offset]);
163 DebugObject* debug_object_;
169 class ELFStringTable;
171 template<
typename THeader>
172 class DebugSectionBase :
public ZoneObject {
174 virtual ~DebugSectionBase() { }
176 virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) {
178 if (WriteBodyInternal(writer)) {
180 header->offset = start;
181 #if defined(__MACH_O)
184 header->size = end - start;
188 virtual bool WriteBodyInternal(Writer* writer) {
192 typedef THeader Header;
196 struct MachOSectionHeader {
199 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
216 class MachOSection :
public DebugSectionBase<MachOSectionHeader> {
220 S_ATTR_COALESCED = 0xbu,
221 S_ATTR_SOME_INSTRUCTIONS = 0x400u,
222 S_ATTR_DEBUG = 0x02000000u,
223 S_ATTR_PURE_INSTRUCTIONS = 0x80000000u
226 MachOSection(
const char*
name,
const char* segment,
uint32_t align,
228 : name_(
name), segment_(segment), align_(align), flags_(
flags) {
235 virtual ~MachOSection() { }
237 virtual void PopulateHeader(Writer::Slot<Header> header) {
241 header->align = align_;
244 header->flags = flags_;
245 header->reserved1 = 0;
246 header->reserved2 = 0;
247 memset(header->sectname, 0,
sizeof(header->sectname));
248 memset(header->segname, 0,
sizeof(header->segname));
249 DCHECK(strlen(name_) <
sizeof(header->sectname));
250 DCHECK(strlen(segment_) <
sizeof(header->segname));
251 strncpy(header->sectname, name_,
sizeof(header->sectname));
252 strncpy(header->segname, segment_,
sizeof(header->segname));
257 const char* segment_;
263 struct ELFSectionHeader {
278 class ELFSection :
public DebugSectionBase<ELFSectionHeader> {
293 TYPE_LOPROC = 0x70000000,
294 TYPE_X86_64_UNWIND = 0x70000001,
295 TYPE_HIPROC = 0x7fffffff,
296 TYPE_LOUSER = 0x80000000,
297 TYPE_HIUSER = 0xffffffff
306 enum SpecialIndexes {
307 INDEX_ABSOLUTE = 0xfff1
311 : name_(
name), type_(type), align_(align) { }
313 virtual ~ELFSection() { }
315 void PopulateHeader(Writer::Slot<Header> header, ELFStringTable* strtab);
317 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
319 if (WriteBodyInternal(w)) {
321 header->offset = start;
322 header->size = end - start;
326 virtual bool WriteBodyInternal(Writer* w) {
330 uint16_t index()
const {
return index_; }
331 void set_index(
uint16_t index) { index_ = index; }
334 virtual void PopulateHeader(Writer::Slot<Header> header) {
341 header->entry_size = 0;
353 #if defined(__MACH_O)
354 class MachOTextSection :
public MachOSection {
359 : MachOSection(
"__text",
362 MachOSection::S_REGULAR |
363 MachOSection::S_ATTR_SOME_INSTRUCTIONS |
364 MachOSection::S_ATTR_PURE_INSTRUCTIONS),
369 virtual void PopulateHeader(Writer::Slot<Header> header) {
370 MachOSection::PopulateHeader(header);
371 header->addr = addr_;
372 header->size = size_;
383 class FullHeaderELFSection :
public ELFSection {
385 FullHeaderELFSection(
const char*
name,
392 : ELFSection(
name, type, align),
399 virtual void PopulateHeader(Writer::Slot<Header> header) {
400 ELFSection::PopulateHeader(header);
401 header->address = addr_;
402 header->offset = offset_;
403 header->size = size_;
404 header->flags = flags_;
415 class ELFStringTable :
public ELFSection {
417 explicit ELFStringTable(
const char*
name)
418 : ELFSection(
name, TYPE_STRTAB, 1), writer_(
NULL), offset_(0), size_(0) {
422 if (*str ==
'\0')
return 0;
429 void AttachWriter(Writer* w) {
431 offset_ = writer_->position();
437 void DetachWriter() {
441 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
443 header->offset = offset_;
444 header->size = size_;
448 void WriteString(
const char* str) {
451 writer_->Write(*str);
464 void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
465 ELFStringTable* strtab) {
466 header->name = strtab->Add(name_);
467 header->type = type_;
468 header->alignment = align_;
469 PopulateHeader(header);
474 #if defined(__MACH_O)
477 explicit MachO(Zone* zone) : zone_(zone), sections_(6, zone) { }
479 uint32_t AddSection(MachOSection* section) {
480 sections_.Add(section, zone_);
481 return sections_.length() - 1;
485 Writer::Slot<MachOHeader> header = WriteHeader(w);
486 uintptr_t load_command_start = w->position();
487 Writer::Slot<MachOSegmentCommand> cmd = WriteSegmentCommand(w,
490 WriteSections(w, cmd, header, load_command_start);
502 #if V8_TARGET_ARCH_X64
507 struct MachOSegmentCommand {
511 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
528 enum MachOLoadCommandCmd {
529 LC_SEGMENT_32 = 0x00000001u,
530 LC_SEGMENT_64 = 0x00000019u
534 Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
535 DCHECK(w->position() == 0);
536 Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
537 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
538 header->magic = 0xFEEDFACEu;
540 header->cpusubtype = 3;
541 #elif V8_TARGET_ARCH_X64
542 header->magic = 0xFEEDFACFu;
543 header->cputype = 7 | 0x01000000;
544 header->cpusubtype = 3;
545 header->reserved = 0;
547 #error Unsupported target architecture.
549 header->filetype = 0x1;
551 header->sizeofcmds = 0;
557 Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w,
560 Writer::Slot<MachOSegmentCommand> cmd =
561 w->CreateSlotHere<MachOSegmentCommand>();
562 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
563 cmd->cmd = LC_SEGMENT_32;
565 cmd->cmd = LC_SEGMENT_64;
567 cmd->vmaddr = code_start;
568 cmd->vmsize = code_size;
574 cmd->nsects = sections_.length();
575 memset(cmd->segname, 0, 16);
576 cmd->cmdsize =
sizeof(MachOSegmentCommand) +
sizeof(MachOSection::Header) *
582 void WriteSections(Writer* w,
583 Writer::Slot<MachOSegmentCommand> cmd,
584 Writer::Slot<MachOHeader> header,
586 Writer::Slot<MachOSection::Header> headers =
587 w->CreateSlotsHere<MachOSection::Header>(sections_.length());
588 cmd->fileoff = w->position();
589 header->sizeofcmds = w->position() - load_command_start;
590 for (
int section = 0; section < sections_.length(); ++section) {
591 sections_[section]->PopulateHeader(headers.at(section));
592 sections_[section]->WriteBody(headers.at(section), w);
594 cmd->filesize = w->position() - (
uintptr_t)cmd->fileoff;
598 ZoneList<MachOSection*> sections_;
606 explicit ELF(Zone* zone) : zone_(zone), sections_(6, zone) {
607 sections_.Add(
new(zone) ELFSection(
"", ELFSection::TYPE_NULL, 0), zone);
608 sections_.Add(
new(zone) ELFStringTable(
".shstrtab"), zone);
611 void Write(Writer* w) {
613 WriteSectionTable(w);
617 ELFSection* SectionAt(
uint32_t index) {
618 return sections_[index];
621 uint32_t AddSection(ELFSection* section) {
622 sections_.Add(section, zone_);
623 section->set_index(sections_.length() - 1);
624 return sections_.length() - 1;
646 void WriteHeader(Writer* w) {
647 DCHECK(w->position() == 0);
648 Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
649 #if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87 || \
650 (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT))
651 const uint8_t ident[16] =
652 { 0x7f,
'E',
'L',
'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
653 #elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
654 const uint8_t ident[16] =
655 { 0x7f,
'E',
'L',
'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
657 #error Unsupported target architecture.
659 memcpy(header->ident, ident, 16);
661 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
663 #elif V8_TARGET_ARCH_X64
667 header->machine = 62;
668 #elif V8_TARGET_ARCH_ARM
671 header->machine = 40;
673 #error Unsupported target architecture.
677 header->pht_offset = 0;
678 header->sht_offset =
sizeof(ELFHeader);
680 header->header_size =
sizeof(ELFHeader);
681 header->pht_entry_size = 0;
682 header->pht_entry_num = 0;
683 header->sht_entry_size =
sizeof(ELFSection::Header);
684 header->sht_entry_num = sections_.length();
685 header->sht_strtab_index = 1;
688 void WriteSectionTable(Writer* w) {
690 DCHECK(w->position() ==
sizeof(ELFHeader));
692 Writer::Slot<ELFSection::Header> headers =
693 w->CreateSlotsHere<ELFSection::Header>(sections_.length());
696 ELFStringTable* strtab =
static_cast<ELFStringTable*
>(SectionAt(1));
697 strtab->AttachWriter(w);
698 for (
int i = 0, length = sections_.length();
701 sections_[
i]->PopulateHeader(headers.at(
i), strtab);
703 strtab->DetachWriter();
706 int SectionHeaderPosition(
uint32_t section_index) {
707 return sizeof(ELFHeader) +
sizeof(ELFSection::Header) * section_index;
710 void WriteSections(Writer* w) {
711 Writer::Slot<ELFSection::Header> headers =
712 w->SlotAt<ELFSection::Header>(
sizeof(ELFHeader));
714 for (
int i = 0, length = sections_.length();
717 sections_[
i]->WriteBody(headers.at(
i), w);
722 ZoneList<ELFSection*> sections_;
746 ELFSymbol(
const char*
name,
755 info((binding << 4) | type),
760 Binding binding()
const {
761 return static_cast<Binding
>(info >> 4);
763 #if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87 || \
764 (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT))
765 struct SerializedLayout {
775 info((binding << 4) | type),
787 #elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
788 struct SerializedLayout {
796 info((binding << 4) | type),
812 void Write(Writer::Slot<SerializedLayout> s, ELFStringTable* t) {
814 s->name = t->Add(
name);
819 s->section = section;
832 class ELFSymbolTable :
public ELFSection {
834 ELFSymbolTable(
const char*
name, Zone* zone)
840 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
841 w->Align(header->alignment);
842 int total_symbols = locals_.length() + globals_.length() + 1;
843 header->offset = w->position();
845 Writer::Slot<ELFSymbol::SerializedLayout> symbols =
846 w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols);
848 header->size = w->position() - header->offset;
851 ELFStringTable* strtab =
852 static_cast<ELFStringTable*
>(w->debug_object()->SectionAt(index() + 1));
853 strtab->AttachWriter(w);
854 symbols.at(0).set(ELFSymbol::SerializedLayout(0,
857 ELFSymbol::BIND_LOCAL,
858 ELFSymbol::TYPE_NOTYPE,
860 WriteSymbolsList(&locals_, symbols.at(1), strtab);
861 WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab);
862 strtab->DetachWriter();
865 void Add(
const ELFSymbol& symbol, Zone* zone) {
866 if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
867 locals_.Add(symbol, zone);
869 globals_.Add(symbol, zone);
874 virtual void PopulateHeader(Writer::Slot<Header> header) {
875 ELFSection::PopulateHeader(header);
877 header->link = index() + 1;
878 header->info = locals_.length() + 1;
879 header->entry_size =
sizeof(ELFSymbol::SerializedLayout);
883 void WriteSymbolsList(
const ZoneList<ELFSymbol>* src,
884 Writer::Slot<ELFSymbol::SerializedLayout> dst,
885 ELFStringTable* strtab) {
886 for (
int i = 0, len = src->length();
889 src->at(
i).Write(dst.at(
i), strtab);
893 ZoneList<ELFSymbol> locals_;
894 ZoneList<ELFSymbol> globals_;
899 class LineInfo :
public Malloced {
901 LineInfo() : pc_info_(10) {}
903 void SetPosition(intptr_t
pc,
int pos,
bool is_statement) {
904 AddPCInfo(PCInfo(
pc, pos, is_statement));
908 PCInfo(intptr_t
pc,
int pos,
bool is_statement)
909 : pc_(
pc), pos_(pos), is_statement_(is_statement) {}
916 List<PCInfo>* pc_info() {
return &pc_info_; }
919 void AddPCInfo(
const PCInfo& pc_info) { pc_info_.Add(pc_info); }
921 List<PCInfo> pc_info_;
927 #if V8_TARGET_ARCH_X64
936 CodeDescription(
const char*
name, Code* code, Handle<Script> script,
937 LineInfo* lineinfo, GDBJITInterface::CodeTag tag,
938 CompilationInfo* info)
946 const char*
name()
const {
950 LineInfo* lineinfo()
const {
return lineinfo_; }
952 GDBJITInterface::CodeTag tag()
const {
956 CompilationInfo* info()
const {
960 bool IsInfoAvailable()
const {
961 return info_ !=
NULL;
965 return reinterpret_cast<uintptr_t>(code_->instruction_start());
969 return reinterpret_cast<uintptr_t>(code_->instruction_end());
973 return CodeEnd() - CodeStart();
976 bool IsLineInfoAvailable() {
977 return !script_.is_null() &&
978 script_->source()->IsString() &&
979 script_->HasValidSource() &&
980 script_->name()->IsString() &&
984 #if V8_TARGET_ARCH_X64
985 uintptr_t GetStackStateStartAddress(StackState state)
const {
986 DCHECK(state < STACK_STATE_MAX);
987 return stack_state_start_addresses_[state];
990 void SetStackStateStartAddress(StackState state,
uintptr_t addr) {
991 DCHECK(state < STACK_STATE_MAX);
992 stack_state_start_addresses_[state] = addr;
996 SmartArrayPointer<char> GetFilename() {
997 return String::cast(script_->name())->ToCString();
1000 int GetScriptLineNumber(
int pos) {
1001 return script_->GetLineNumber(pos) + 1;
1008 Handle<Script> script_;
1009 LineInfo* lineinfo_;
1010 GDBJITInterface::CodeTag tag_;
1011 CompilationInfo* info_;
1012 #if V8_TARGET_ARCH_X64
1013 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
1018 static void CreateSymbolsTable(CodeDescription* desc,
1021 int text_section_index) {
1022 ELFSymbolTable* symtab =
new(zone) ELFSymbolTable(
".symtab", zone);
1023 ELFStringTable* strtab =
new(zone) ELFStringTable(
".strtab");
1026 elf->AddSection(symtab);
1027 elf->AddSection(strtab);
1029 symtab->Add(ELFSymbol(
"V8 Code",
1032 ELFSymbol::BIND_LOCAL,
1033 ELFSymbol::TYPE_FILE,
1034 ELFSection::INDEX_ABSOLUTE),
1037 symtab->Add(ELFSymbol(desc->name(),
1040 ELFSymbol::BIND_GLOBAL,
1041 ELFSymbol::TYPE_FUNC,
1042 text_section_index),
1048 class DebugInfoSection :
public DebugSection {
1050 explicit DebugInfoSection(CodeDescription* desc)
1052 : ELFSection(
".debug_info", TYPE_PROGBITS, 1),
1054 : MachOSection(
"__debug_info",
1057 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1062 enum DWARF2LocationOp {
1074 enum DWARF2Encoding {
1075 DW_ATE_ADDRESS = 0x1,
1079 bool WriteBodyInternal(Writer* w) {
1081 Writer::Slot<uint32_t>
size = w->CreateSlotHere<
uint32_t>();
1085 w->Write<uint8_t>(
sizeof(intptr_t));
1088 w->WriteString(desc_->GetFilename().get());
1089 w->Write<intptr_t>(desc_->CodeStart());
1090 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1096 w->WriteString(
"v8value");
1098 if (desc_->IsInfoAvailable()) {
1099 Scope* scope = desc_->info()->scope();
1101 w->WriteString(desc_->name());
1102 w->Write<intptr_t>(desc_->CodeStart());
1103 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1104 Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<
uint32_t>();
1105 uintptr_t fb_block_start = w->position();
1106 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
1107 w->Write<uint8_t>(DW_OP_reg5);
1108 #elif V8_TARGET_ARCH_X64
1109 w->Write<uint8_t>(DW_OP_reg6);
1110 #elif V8_TARGET_ARCH_ARM
1112 #elif V8_TARGET_ARCH_MIPS
1114 #elif V8_TARGET_ARCH_MIPS64
1117 #error Unsupported target architecture.
1119 fb_block_size.set(
static_cast<uint32_t>(w->position() - fb_block_start));
1121 int params = scope->num_parameters();
1122 int slots = scope->num_stack_slots();
1123 int context_slots = scope->ContextLocalCount();
1126 int locals = scope->StackLocalCount();
1127 int current_abbreviation = 4;
1129 for (
int param = 0; param < params; ++param) {
1130 w->WriteULEB128(current_abbreviation++);
1132 scope->parameter(param)->name()->ToCString(
DISALLOW_NULLS).get());
1134 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<
uint32_t>();
1136 w->Write<uint8_t>(DW_OP_fbreg);
1140 block_size.set(
static_cast<uint32_t>(w->position() - block_start));
1143 EmbeddedVector<char, 256> buffer;
1144 StringBuilder builder(buffer.start(), buffer.length());
1146 for (
int slot = 0; slot < slots; ++slot) {
1147 w->WriteULEB128(current_abbreviation++);
1149 builder.AddFormatted(
"slot%d", slot);
1150 w->WriteString(builder.Finalize());
1159 w->WriteULEB128(current_abbreviation++);
1160 w->WriteString(
".closure");
1161 w->WriteULEB128(current_abbreviation++);
1162 w->WriteString(
".previous");
1163 w->WriteULEB128(current_abbreviation++);
1164 w->WriteString(
".extension");
1165 w->WriteULEB128(current_abbreviation++);
1166 w->WriteString(
".global");
1168 for (
int context_slot = 0;
1169 context_slot < context_slots;
1171 w->WriteULEB128(current_abbreviation++);
1173 builder.AddFormatted(
"context_slot%d", context_slot + internal_slots);
1174 w->WriteString(builder.Finalize());
1177 ZoneList<Variable*> stack_locals(locals, scope->zone());
1178 ZoneList<Variable*> context_locals(context_slots, scope->zone());
1179 scope->CollectStackAndContextLocals(&stack_locals, &context_locals);
1180 for (
int local = 0; local < locals; ++local) {
1181 w->WriteULEB128(current_abbreviation++);
1185 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<
uint32_t>();
1187 w->Write<uint8_t>(DW_OP_fbreg);
1191 block_size.set(
static_cast<uint32_t>(w->position() - block_start));
1195 w->WriteULEB128(current_abbreviation++);
1196 w->WriteString(
"__function");
1198 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<
uint32_t>();
1200 w->Write<uint8_t>(DW_OP_fbreg);
1202 block_size.set(
static_cast<uint32_t>(w->position() - block_start));
1206 w->WriteULEB128(current_abbreviation++);
1207 w->WriteString(
"__context");
1209 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<
uint32_t>();
1211 w->Write<uint8_t>(DW_OP_fbreg);
1213 block_size.set(
static_cast<uint32_t>(w->position() - block_start));
1220 size.set(
static_cast<uint32_t>(w->position() - start));
1225 CodeDescription* desc_;
1229 class DebugAbbrevSection :
public DebugSection {
1231 explicit DebugAbbrevSection(CodeDescription* desc)
1233 : ELFSection(
".debug_abbrev", TYPE_PROGBITS, 1),
1235 : MachOSection(
"__debug_abbrev",
1238 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1244 DW_TAG_FORMAL_PARAMETER = 0x05,
1245 DW_TAG_POINTER_TYPE = 0xf,
1246 DW_TAG_COMPILE_UNIT = 0x11,
1247 DW_TAG_STRUCTURE_TYPE = 0x13,
1248 DW_TAG_BASE_TYPE = 0x24,
1249 DW_TAG_SUBPROGRAM = 0x2e,
1250 DW_TAG_VARIABLE = 0x34
1254 enum DWARF2ChildrenDetermination {
1260 enum DWARF2Attribute {
1261 DW_AT_LOCATION = 0x2,
1263 DW_AT_BYTE_SIZE = 0xb,
1264 DW_AT_STMT_LIST = 0x10,
1265 DW_AT_LOW_PC = 0x11,
1266 DW_AT_HIGH_PC = 0x12,
1267 DW_AT_ENCODING = 0x3e,
1268 DW_AT_FRAME_BASE = 0x40,
1273 enum DWARF2AttributeForm {
1275 DW_FORM_BLOCK4 = 0x4,
1276 DW_FORM_STRING = 0x8,
1277 DW_FORM_DATA4 = 0x6,
1278 DW_FORM_BLOCK = 0x9,
1279 DW_FORM_DATA1 = 0xb,
1284 void WriteVariableAbbreviation(Writer* w,
1285 int abbreviation_code,
1287 bool is_parameter) {
1288 w->WriteULEB128(abbreviation_code);
1289 w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
1290 w->Write<uint8_t>(DW_CHILDREN_NO);
1291 w->WriteULEB128(DW_AT_NAME);
1292 w->WriteULEB128(DW_FORM_STRING);
1294 w->WriteULEB128(DW_AT_TYPE);
1295 w->WriteULEB128(DW_FORM_REF4);
1296 w->WriteULEB128(DW_AT_LOCATION);
1297 w->WriteULEB128(DW_FORM_BLOCK4);
1303 bool WriteBodyInternal(Writer* w) {
1304 int current_abbreviation = 1;
1305 bool extra_info = desc_->IsInfoAvailable();
1306 DCHECK(desc_->IsLineInfoAvailable());
1307 w->WriteULEB128(current_abbreviation++);
1308 w->WriteULEB128(DW_TAG_COMPILE_UNIT);
1309 w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1310 w->WriteULEB128(DW_AT_NAME);
1311 w->WriteULEB128(DW_FORM_STRING);
1312 w->WriteULEB128(DW_AT_LOW_PC);
1313 w->WriteULEB128(DW_FORM_ADDR);
1314 w->WriteULEB128(DW_AT_HIGH_PC);
1315 w->WriteULEB128(DW_FORM_ADDR);
1316 w->WriteULEB128(DW_AT_STMT_LIST);
1317 w->WriteULEB128(DW_FORM_DATA4);
1322 Scope* scope = desc_->info()->scope();
1323 int params = scope->num_parameters();
1324 int slots = scope->num_stack_slots();
1325 int context_slots = scope->ContextLocalCount();
1328 int locals = scope->StackLocalCount();
1334 w->WriteULEB128(current_abbreviation++);
1335 w->WriteULEB128(DW_TAG_SUBPROGRAM);
1336 w->Write<uint8_t>(DW_CHILDREN_YES);
1337 w->WriteULEB128(DW_AT_NAME);
1338 w->WriteULEB128(DW_FORM_STRING);
1339 w->WriteULEB128(DW_AT_LOW_PC);
1340 w->WriteULEB128(DW_FORM_ADDR);
1341 w->WriteULEB128(DW_AT_HIGH_PC);
1342 w->WriteULEB128(DW_FORM_ADDR);
1343 w->WriteULEB128(DW_AT_FRAME_BASE);
1344 w->WriteULEB128(DW_FORM_BLOCK4);
1348 w->WriteULEB128(current_abbreviation++);
1349 w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
1350 w->Write<uint8_t>(DW_CHILDREN_NO);
1351 w->WriteULEB128(DW_AT_BYTE_SIZE);
1352 w->WriteULEB128(DW_FORM_DATA1);
1353 w->WriteULEB128(DW_AT_NAME);
1354 w->WriteULEB128(DW_FORM_STRING);
1358 for (
int param = 0; param < params; ++param) {
1359 WriteVariableAbbreviation(w, current_abbreviation++,
true,
true);
1362 for (
int slot = 0; slot < slots; ++slot) {
1363 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1366 for (
int internal_slot = 0;
1367 internal_slot < internal_slots;
1369 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1372 for (
int context_slot = 0;
1373 context_slot < context_slots;
1375 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1378 for (
int local = 0; local < locals; ++local) {
1379 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1383 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1386 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1396 CodeDescription* desc_;
1400 class DebugLineSection :
public DebugSection {
1402 explicit DebugLineSection(CodeDescription* desc)
1404 : ELFSection(
".debug_line", TYPE_PROGBITS, 1),
1406 : MachOSection(
"__debug_line",
1409 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1414 enum DWARF2Opcodes {
1416 DW_LNS_ADVANCE_PC = 2,
1417 DW_LNS_ADVANCE_LINE = 3,
1418 DW_LNS_SET_FILE = 4,
1419 DW_LNS_SET_COLUMN = 5,
1420 DW_LNS_NEGATE_STMT = 6
1424 enum DWARF2ExtendedOpcode {
1425 DW_LNE_END_SEQUENCE = 1,
1426 DW_LNE_SET_ADDRESS = 2,
1427 DW_LNE_DEFINE_FILE = 3
1430 bool WriteBodyInternal(Writer* w) {
1432 Writer::Slot<uint32_t> total_length = w->CreateSlotHere<
uint32_t>();
1436 const int8_t line_base = 1;
1437 const uint8_t line_range = 7;
1438 const int8_t max_line_incr = (line_base + line_range - 1);
1439 const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
1442 Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<
uint32_t>();
1443 uintptr_t prologue_start = w->position();
1444 w->Write<uint8_t>(1);
1445 w->Write<uint8_t>(1);
1446 w->Write<int8_t>(line_base);
1447 w->Write<uint8_t>(line_range);
1448 w->Write<uint8_t>(opcode_base);
1449 w->Write<uint8_t>(0);
1450 w->Write<uint8_t>(1);
1451 w->Write<uint8_t>(1);
1452 w->Write<uint8_t>(1);
1453 w->Write<uint8_t>(1);
1454 w->Write<uint8_t>(0);
1455 w->Write<uint8_t>(0);
1456 w->WriteString(desc_->GetFilename().get());
1460 w->Write<uint8_t>(0);
1461 prologue_length.set(
static_cast<uint32_t>(w->position() - prologue_start));
1463 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS,
sizeof(intptr_t));
1464 w->Write<intptr_t>(desc_->CodeStart());
1465 w->Write<uint8_t>(DW_LNS_COPY);
1469 bool is_statement =
true;
1471 List<LineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
1472 pc_info->Sort(&ComparePCInfo);
1474 int pc_info_length = pc_info->length();
1475 for (
int i = 0;
i < pc_info_length;
i++) {
1476 LineInfo::PCInfo* info = &pc_info->at(
i);
1481 intptr_t new_line = desc_->GetScriptLineNumber(info->pos_);
1482 if (new_line == line) {
1490 if ((
i+1) == pc_info_length) {
1491 if (!is_statement) {
1492 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1494 }
else if (is_statement != info->is_statement_) {
1495 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1496 is_statement = !is_statement;
1503 intptr_t line_diff = new_line - line;
1506 intptr_t special_opcode = (line_diff - line_base) +
1507 (line_range * pc_diff) + opcode_base;
1514 if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
1515 (line_diff <= max_line_incr) && (line_diff >= line_base)) {
1516 w->Write<uint8_t>(special_opcode);
1518 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1519 w->WriteSLEB128(pc_diff);
1520 w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
1521 w->WriteSLEB128(line_diff);
1522 w->Write<uint8_t>(DW_LNS_COPY);
1531 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1532 w->WriteSLEB128(desc_->CodeSize() -
pc);
1533 WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
1534 total_length.set(
static_cast<uint32_t>(w->position() - start));
1539 void WriteExtendedOpcode(Writer* w,
1540 DWARF2ExtendedOpcode op,
1541 size_t operands_size) {
1542 w->Write<uint8_t>(0);
1543 w->WriteULEB128(operands_size + 1);
1544 w->Write<uint8_t>(op);
1547 static int ComparePCInfo(
const LineInfo::PCInfo* a,
1548 const LineInfo::PCInfo* b) {
1549 if (a->pc_ == b->pc_) {
1550 if (a->is_statement_ != b->is_statement_) {
1551 return b->is_statement_ ? +1 : -1;
1554 }
else if (a->pc_ > b->pc_) {
1561 CodeDescription* desc_;
1565 #if V8_TARGET_ARCH_X64
1567 class UnwindInfoSection :
public DebugSection {
1569 explicit UnwindInfoSection(CodeDescription* desc);
1570 virtual bool WriteBodyInternal(Writer* w);
1572 int WriteCIE(Writer* w);
1573 void WriteFDE(Writer* w,
int);
1575 void WriteFDEStateOnEntry(Writer* w);
1576 void WriteFDEStateAfterRBPPush(Writer* w);
1577 void WriteFDEStateAfterRBPSet(Writer* w);
1578 void WriteFDEStateAfterRBPPop(Writer* w);
1580 void WriteLength(Writer* w,
1581 Writer::Slot<uint32_t>* length_slot,
1582 int initial_position);
1585 CodeDescription* desc_;
1588 enum CFIInstructions {
1589 DW_CFA_ADVANCE_LOC = 0x40,
1590 DW_CFA_OFFSET = 0x80,
1591 DW_CFA_RESTORE = 0xC0,
1593 DW_CFA_SET_LOC = 0x01,
1594 DW_CFA_ADVANCE_LOC1 = 0x02,
1595 DW_CFA_ADVANCE_LOC2 = 0x03,
1596 DW_CFA_ADVANCE_LOC4 = 0x04,
1597 DW_CFA_OFFSET_EXTENDED = 0x05,
1598 DW_CFA_RESTORE_EXTENDED = 0x06,
1599 DW_CFA_UNDEFINED = 0x07,
1600 DW_CFA_SAME_VALUE = 0x08,
1601 DW_CFA_REGISTER = 0x09,
1602 DW_CFA_REMEMBER_STATE = 0x0A,
1603 DW_CFA_RESTORE_STATE = 0x0B,
1604 DW_CFA_DEF_CFA = 0x0C,
1605 DW_CFA_DEF_CFA_REGISTER = 0x0D,
1606 DW_CFA_DEF_CFA_OFFSET = 0x0E,
1608 DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
1609 DW_CFA_EXPRESSION = 0x10,
1610 DW_CFA_OFFSET_EXTENDED_SF = 0x11,
1611 DW_CFA_DEF_CFA_SF = 0x12,
1612 DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
1613 DW_CFA_VAL_OFFSET = 0x14,
1614 DW_CFA_VAL_OFFSET_SF = 0x15,
1615 DW_CFA_VAL_EXPRESSION = 0x16
1619 enum RegisterMapping {
1629 CODE_ALIGN_FACTOR = 1,
1630 DATA_ALIGN_FACTOR = 1,
1631 RETURN_ADDRESS_REGISTER = AMD64_RA
1636 void UnwindInfoSection::WriteLength(Writer* w,
1637 Writer::Slot<uint32_t>* length_slot,
1638 int initial_position) {
1643 w->Write<uint8_t>(DW_CFA_NOP);
1648 length_slot->set(w->position() - initial_position);
1652 UnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
1654 : ELFSection(
".eh_frame", TYPE_X86_64_UNWIND, 1),
1656 : MachOSection(
"__eh_frame",
"__TEXT",
sizeof(
uintptr_t),
1657 MachOSection::S_REGULAR),
1661 int UnwindInfoSection::WriteCIE(Writer* w) {
1662 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<
uint32_t>();
1663 uint32_t cie_position = w->position();
1669 w->Write<uint8_t>(CIE_VERSION);
1670 w->Write<uint8_t>(0);
1671 w->WriteSLEB128(CODE_ALIGN_FACTOR);
1672 w->WriteSLEB128(DATA_ALIGN_FACTOR);
1673 w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
1675 WriteLength(w, &cie_length_slot, cie_position);
1677 return cie_position;
1681 void UnwindInfoSection::WriteFDE(Writer* w,
int cie_position) {
1683 Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<
uint32_t>();
1684 int fde_position = w->position();
1685 w->Write<
int32_t>(fde_position - cie_position + 4);
1687 w->Write<
uintptr_t>(desc_->CodeStart());
1690 WriteFDEStateOnEntry(w);
1691 WriteFDEStateAfterRBPPush(w);
1692 WriteFDEStateAfterRBPSet(w);
1693 WriteFDEStateAfterRBPPop(w);
1695 WriteLength(w, &fde_length_slot, fde_position);
1699 void UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
1705 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1706 w->WriteULEB128(AMD64_RSP);
1711 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1712 w->WriteULEB128(AMD64_RA);
1716 w->Write<uint8_t>(DW_CFA_SAME_VALUE);
1717 w->WriteULEB128(AMD64_RBP);
1720 w->Write<uint8_t>(DW_CFA_SET_LOC);
1722 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
1726 void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
1731 w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
1736 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1737 w->WriteULEB128(AMD64_RBP);
1741 w->Write<uint8_t>(DW_CFA_SET_LOC);
1743 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
1747 void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
1751 w->Write<uint8_t>(DW_CFA_DEF_CFA);
1752 w->WriteULEB128(AMD64_RBP);
1756 w->Write<uint8_t>(DW_CFA_SET_LOC);
1758 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
1762 void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
1767 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1768 w->WriteULEB128(AMD64_RSP);
1772 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1773 w->WriteULEB128(AMD64_RBP);
1777 w->Write<uint8_t>(DW_CFA_SET_LOC);
1778 w->Write<uint64_t>(desc_->CodeEnd());
1782 bool UnwindInfoSection::WriteBodyInternal(Writer* w) {
1783 uint32_t cie_position = WriteCIE(w);
1784 WriteFDE(w, cie_position);
1791 static void CreateDWARFSections(CodeDescription* desc,
1794 if (desc->IsLineInfoAvailable()) {
1795 obj->AddSection(
new(zone) DebugInfoSection(desc));
1796 obj->AddSection(
new(zone) DebugAbbrevSection(desc));
1797 obj->AddSection(
new(zone) DebugLineSection(desc));
1799 #if V8_TARGET_ARCH_X64
1800 obj->AddSection(
new(zone) UnwindInfoSection(desc));
1815 struct JITCodeEntry {
1816 JITCodeEntry* next_;
1817 JITCodeEntry* prev_;
1819 uint64_t symfile_size_;
1822 struct JITDescriptor {
1825 JITCodeEntry* relevant_entry_;
1826 JITCodeEntry* first_entry_;
1832 void __attribute__((noinline)) __jit_debug_register_code() {
1839 JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
1842 void __gdb_print_v8_object(
Object*
object) {
1843 OFStream os(stdout);
1851 static JITCodeEntry* CreateCodeEntry(
Address symfile_addr,
1853 JITCodeEntry* entry =
static_cast<JITCodeEntry*
>(
1854 malloc(
sizeof(JITCodeEntry) + symfile_size));
1856 entry->symfile_addr_ =
reinterpret_cast<Address>(entry + 1);
1857 entry->symfile_size_ = symfile_size;
1858 MemCopy(entry->symfile_addr_, symfile_addr, symfile_size);
1860 entry->prev_ = entry->next_ =
NULL;
1866 static void DestroyCodeEntry(JITCodeEntry* entry) {
1871 static void RegisterCodeEntry(JITCodeEntry* entry,
1872 bool dump_if_enabled,
1873 const char* name_hint) {
1874 #if defined(DEBUG) && !V8_OS_WIN
1875 static int file_num = 0;
1876 if (FLAG_gdbjit_dump && dump_if_enabled) {
1877 static const int kMaxFileNameSize = 64;
1878 static const char* kElfFilePrefix =
"/tmp/elfdump";
1879 static const char* kObjFileExt =
".o";
1882 SNPrintF(Vector<char>(file_name, kMaxFileNameSize),
1885 (name_hint !=
NULL) ? name_hint :
"",
1888 WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
1892 entry->next_ = __jit_debug_descriptor.first_entry_;
1893 if (entry->next_ !=
NULL) entry->next_->prev_ = entry;
1894 __jit_debug_descriptor.first_entry_ =
1895 __jit_debug_descriptor.relevant_entry_ = entry;
1897 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
1898 __jit_debug_register_code();
1902 static void UnregisterCodeEntry(JITCodeEntry* entry) {
1903 if (entry->prev_ !=
NULL) {
1904 entry->prev_->next_ = entry->next_;
1906 __jit_debug_descriptor.first_entry_ = entry->next_;
1909 if (entry->next_ !=
NULL) {
1910 entry->next_->prev_ = entry->prev_;
1913 __jit_debug_descriptor.relevant_entry_ = entry;
1914 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
1915 __jit_debug_register_code();
1919 static JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) {
1922 MachO mach_o(&zone);
1929 CreateDWARFSections(desc, &zone, &mach_o);
1931 mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
1937 int text_section_index = elf.AddSection(
1938 new(&zone) FullHeaderELFSection(
1940 ELFSection::TYPE_NOBITS,
1945 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
1947 CreateSymbolsTable(desc, &zone, &elf, text_section_index);
1949 CreateDWARFSections(desc, &zone, &elf);
1954 return CreateCodeEntry(w.buffer(), w.position());
1958 static bool SameCodeObjects(
void* key1,
void* key2) {
1959 return key1 == key2;
1965 if (entries ==
NULL) {
1966 entries =
new HashMap(&SameCodeObjects);
1972 static uint32_t HashForCodeObject(Code* code) {
1973 static const uintptr_t kGoldenRatio = 2654435761u;
1979 static const intptr_t kLineInfoTag = 0x1;
1983 return 0 != (
reinterpret_cast<intptr_t
>(ptr) & kLineInfoTag);
1987 static void* TagLineInfo(LineInfo* ptr) {
1988 return reinterpret_cast<void*
>(
1989 reinterpret_cast<intptr_t
>(ptr) | kLineInfoTag);
1994 return reinterpret_cast<LineInfo*
>(
reinterpret_cast<intptr_t
>(ptr) &
1999 void GDBJITInterface::AddCode(Handle<Name>
name,
2000 Handle<Script> script,
2002 CompilationInfo* info) {
2003 if (!FLAG_gdbjit)
return;
2007 if (!
name.is_null() &&
name->IsString()) {
2008 SmartArrayPointer<char> name_cstring =
2010 AddCode(name_cstring.get(), *code, GDBJITInterface::FUNCTION, *script,
2013 AddCode(
"", *code, GDBJITInterface::FUNCTION, *script, info);
2018 static void AddUnwindInfo(CodeDescription* desc) {
2019 #if V8_TARGET_ARCH_X64
2020 if (desc->tag() == GDBJITInterface::FUNCTION) {
2024 static const int kFramePointerPushOffset = 1;
2025 static const int kFramePointerSetOffset = 4;
2026 static const int kFramePointerPopOffset = -3;
2029 desc->CodeStart() + kFramePointerPushOffset;
2032 desc->CodeStart() + kFramePointerSetOffset;
2035 desc->CodeEnd() + kFramePointerPopOffset;
2037 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2038 frame_pointer_push_address);
2039 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2040 frame_pointer_set_address);
2041 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2042 frame_pointer_pop_address);
2044 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2046 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2048 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2058 void GDBJITInterface::AddCode(
const char*
name,
2060 GDBJITInterface::CodeTag tag,
2062 CompilationInfo* info) {
2063 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
2066 HashMap::Entry* e =
GetEntries()->Lookup(code, HashForCodeObject(code),
true);
2070 CodeDescription code_desc(
name,
2072 script !=
NULL ? Handle<Script>(script)
2078 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
2080 GetEntries()->Remove(code, HashForCodeObject(code));
2084 AddUnwindInfo(&code_desc);
2085 Isolate* isolate = code->GetIsolate();
2086 JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
2092 const char* name_hint =
NULL;
2093 bool should_dump =
false;
2094 if (FLAG_gdbjit_dump) {
2095 if (strlen(FLAG_gdbjit_dump_filter) == 0) {
2099 name_hint = strstr(
name, FLAG_gdbjit_dump_filter);
2100 should_dump = (name_hint !=
NULL);
2103 RegisterCodeEntry(entry, should_dump, name_hint);
2107 void GDBJITInterface::RemoveCode(Code* code) {
2108 if (!FLAG_gdbjit)
return;
2110 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
2111 HashMap::Entry* e =
GetEntries()->Lookup(code,
2112 HashForCodeObject(code),
2114 if (e ==
NULL)
return;
2119 JITCodeEntry* entry =
static_cast<JITCodeEntry*
>(e->value);
2120 UnregisterCodeEntry(entry);
2121 DestroyCodeEntry(entry);
2124 GetEntries()->Remove(code, HashForCodeObject(code));
2128 void GDBJITInterface::RemoveCodeRange(
Address start,
Address end) {
2130 Zone zone(Isolate::Current());
2131 ZoneList<Code*> dead_codes(1, &zone);
2133 for (HashMap::Entry* e = entries->Start(); e !=
NULL; e = entries->Next(e)) {
2134 Code* code =
reinterpret_cast<Code*
>(e->key);
2135 if (code->address() >= start && code->address() < end) {
2136 dead_codes.Add(code, &zone);
2140 for (
int i = 0;
i < dead_codes.length();
i++) {
2141 RemoveCode(dead_codes.at(
i));
2146 static void RegisterDetailedLineInfo(Code* code, LineInfo* line_info) {
2147 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
2149 HashMap::Entry* e =
GetEntries()->Lookup(code, HashForCodeObject(code),
true);
2151 e->value = TagLineInfo(line_info);
2156 if (!FLAG_gdbjit)
return;
2157 switch (event->
type) {
2161 if (code->kind() == Code::OPTIMIZED_FUNCTION ||
2162 code->kind() == Code::FUNCTION) {
2165 EmbeddedVector<char, 256> buffer;
2166 StringBuilder builder(buffer.start(), buffer.length());
2167 builder.AddSubstring(event->
name.
str,
static_cast<int>(event->
name.
len));
2168 AddCode(builder.Finalize(), code, NON_FUNCTION,
NULL,
NULL);
2180 LineInfo* line_info =
reinterpret_cast<LineInfo*
>(
event->user_data);
2181 line_info->SetPosition(
static_cast<intptr_t
>(event->
line_info.
offset),
2182 static_cast<int>(
event->line_info.pos),
2189 mutable_event->
user_data =
new LineInfo();
2193 LineInfo* line_info =
reinterpret_cast<LineInfo*
>(
event->user_data);
2196 RegisterDetailedLineInfo(code, line_info);
static Code * GetCodeFromTargetAddress(Address address)
static Handle< T > cast(Handle< S > that)
static const int kLastParameterOffset
static const int kLocal0Offset
static const int kFunctionOffset
static void InitLineEnds(Handle< Script > script)
static const int kContextOffset
static const int kCallerPCOffset
static const int kCallerFPOffset
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
#define LAZY_MUTEX_INITIALIZER
bool IsPowerOfTwo32(uint32_t value)
LazyStaticInstance< Mutex, DefaultConstructTrait< Mutex >, ThreadSafeInitOnceTrait >::type LazyMutex
int WhichPowerOf2(uint32_t x)
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
TypeImpl< ZoneTypeConfig > Type
const intptr_t kCodeAlignment
int SNPrintF(Vector< char > str, const char *format,...)
kSerializedDataOffset Object
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
OStream & flush(OStream &os)
const int kCodeAlignmentBits
int WriteBytes(const char *filename, const byte *bytes, int size, bool verbose)
void MemCopy(void *dest, const void *src, size_t size)
Debugger support for the V8 JavaScript engine.
static const uint16_t * Align(const uint16_t *chars)
static JitInfoMap * GetEntries()
static JITCodeLineInfo * UntagLineInfo(void *ptr)
static bool IsLineInfoTagged(void *ptr)
PositionType position_type
A JIT code event is issued each time code is added, moved or removed.
struct line_info_t line_info
@ CODE_END_LINE_INFO_RECORDING
@ CODE_START_LINE_INFO_RECORDING
#define T(name, string, precedence)