28 #ifdef ENABLE_GDB_JIT_INTERFACE
49 typedef MachO DebugObject;
50 typedef MachOSection DebugSection;
55 typedef ELF DebugObject;
56 typedef ELFSection DebugSection;
61 explicit Writer(DebugObject* debug_object)
62 : debug_object_(debug_object),
65 buffer_(reinterpret_cast<
byte*>(malloc(capacity_))) {
72 uintptr_t position()
const {
79 Slot(Writer* w, uintptr_t offset) : w_(w), offset_(offset) { }
82 return w_->RawSlotAt<
T>(offset_);
85 void set(
const T& value) {
86 *w_->RawSlotAt<
T>(offset_) = value;
90 return Slot<T>(w_, offset_ +
sizeof(
T) * i);
99 void Write(
const T& val) {
100 Ensure(position_ +
sizeof(
T));
101 *RawSlotAt<T>(position_) = val;
102 position_ +=
sizeof(
T);
106 Slot<T> SlotAt(uintptr_t offset) {
107 Ensure(offset +
sizeof(
T));
108 return Slot<T>(
this, offset);
112 Slot<T> CreateSlotHere() {
113 return CreateSlotsHere<T>(1);
117 Slot<T> CreateSlotsHere(uint32_t count) {
118 uintptr_t slot_position = position_;
119 position_ +=
sizeof(
T) * count;
121 return SlotAt<T>(slot_position);
124 void Ensure(uintptr_t pos) {
125 if (capacity_ < pos) {
126 while (capacity_ < pos) capacity_ *= 2;
127 buffer_ =
reinterpret_cast<byte*
>(realloc(buffer_, capacity_));
131 DebugObject* debug_object() {
return debug_object_; }
133 byte* buffer() {
return buffer_; }
135 void Align(uintptr_t align) {
136 uintptr_t delta = position_ % align;
137 if (delta == 0)
return;
138 uintptr_t padding = align - delta;
139 Ensure(position_ += padding);
140 ASSERT((position_ % align) == 0);
143 void WriteULEB128(uintptr_t value) {
145 uint8_t
byte = value & 0x7F;
147 if (value != 0) byte |= 0x80;
148 Write<uint8_t>(
byte);
149 }
while (value != 0);
152 void WriteSLEB128(intptr_t value) {
155 int8_t byte = value & 0x7F;
156 bool byte_sign = byte & 0x40;
159 if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) {
169 void WriteString(
const char* str) {
176 template<
typename T>
friend class Slot;
179 T* RawSlotAt(uintptr_t offset) {
180 ASSERT(offset < capacity_ && offset +
sizeof(
T) <= capacity_);
181 return reinterpret_cast<T*
>(&buffer_[offset]);
184 DebugObject* debug_object_;
190 class ELFStringTable;
192 template<
typename THeader>
193 class DebugSectionBase :
public ZoneObject {
195 virtual ~DebugSectionBase() { }
197 virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) {
198 uintptr_t start = writer->position();
199 if (WriteBodyInternal(writer)) {
200 uintptr_t end = writer->position();
201 header->offset = start;
202 #if defined(__MACH_O)
205 header->size = end - start;
209 virtual bool WriteBodyInternal(Writer* writer) {
213 typedef THeader Header;
217 struct MachOSectionHeader {
220 #if V8_TARGET_ARCH_IA32
237 class MachOSection :
public DebugSectionBase<MachOSectionHeader> {
241 S_ATTR_COALESCED = 0xbu,
242 S_ATTR_SOME_INSTRUCTIONS = 0x400u,
243 S_ATTR_DEBUG = 0x02000000u,
244 S_ATTR_PURE_INSTRUCTIONS = 0x80000000u
247 MachOSection(
const char*
name,
261 virtual ~MachOSection() { }
263 virtual void PopulateHeader(Writer::Slot<Header> header) {
267 header->align = align_;
270 header->flags = flags_;
271 header->reserved1 = 0;
272 header->reserved2 = 0;
273 memset(header->sectname, 0,
sizeof(header->sectname));
274 memset(header->segname, 0,
sizeof(header->segname));
275 ASSERT(strlen(name_) <
sizeof(header->sectname));
276 ASSERT(strlen(segment_) <
sizeof(header->segname));
277 strncpy(header->sectname, name_,
sizeof(header->sectname));
278 strncpy(header->segname, segment_,
sizeof(header->segname));
283 const char* segment_;
289 struct ELFSectionHeader {
299 uintptr_t entry_size;
304 class ELFSection :
public DebugSectionBase<ELFSectionHeader> {
319 TYPE_LOPROC = 0x70000000,
320 TYPE_X86_64_UNWIND = 0x70000001,
321 TYPE_HIPROC = 0x7fffffff,
322 TYPE_LOUSER = 0x80000000,
323 TYPE_HIUSER = 0xffffffff
332 enum SpecialIndexes {
333 INDEX_ABSOLUTE = 0xfff1
336 ELFSection(
const char* name,
Type type, uintptr_t align)
337 : name_(name), type_(type), align_(align) { }
339 virtual ~ELFSection() { }
341 void PopulateHeader(Writer::Slot<Header> header, ELFStringTable* strtab);
343 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
344 uintptr_t start = w->position();
345 if (WriteBodyInternal(w)) {
346 uintptr_t end = w->position();
347 header->offset = start;
348 header->size = end - start;
352 virtual bool WriteBodyInternal(Writer* w) {
356 uint16_t index()
const {
return index_; }
357 void set_index(
uint16_t index) { index_ = index; }
360 virtual void PopulateHeader(Writer::Slot<Header> header) {
367 header->entry_size = 0;
376 #endif // defined(__ELF)
379 #if defined(__MACH_O)
380 class MachOTextSection :
public MachOSection {
382 MachOTextSection(uintptr_t align,
385 : MachOSection(
"__text",
388 MachOSection::S_REGULAR |
389 MachOSection::S_ATTR_SOME_INSTRUCTIONS |
390 MachOSection::S_ATTR_PURE_INSTRUCTIONS),
395 virtual void PopulateHeader(Writer::Slot<Header> header) {
396 MachOSection::PopulateHeader(header);
397 header->addr = addr_;
398 header->size = size_;
405 #endif // defined(__MACH_O)
409 class FullHeaderELFSection :
public ELFSection {
411 FullHeaderELFSection(
const char* name,
418 : ELFSection(name, type, align),
425 virtual void PopulateHeader(Writer::Slot<Header> header) {
426 ELFSection::PopulateHeader(header);
427 header->address = addr_;
428 header->offset = offset_;
429 header->size = size_;
430 header->flags = flags_;
441 class ELFStringTable :
public ELFSection {
443 explicit ELFStringTable(
const char* name)
444 : ELFSection(name, TYPE_STRTAB, 1), writer_(
NULL), offset_(0), size_(0) {
447 uintptr_t Add(
const char* str) {
448 if (*str ==
'\0')
return 0;
450 uintptr_t offset = size_;
455 void AttachWriter(Writer* w) {
457 offset_ = writer_->position();
463 void DetachWriter() {
467 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
469 header->offset = offset_;
470 header->size = size_;
474 void WriteString(
const char* str) {
475 uintptr_t written = 0;
477 writer_->Write(*str);
490 void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
491 ELFStringTable* strtab) {
492 header->name = strtab->Add(name_);
493 header->type = type_;
494 header->alignment = align_;
495 PopulateHeader(header);
497 #endif // defined(__ELF)
500 #if defined(__MACH_O)
503 explicit MachO(Zone* zone) : zone_(zone), sections_(6, zone) { }
505 uint32_t AddSection(MachOSection* section) {
506 sections_.Add(section, zone_);
507 return sections_.length() - 1;
510 void Write(Writer* w, uintptr_t code_start, uintptr_t code_size) {
511 Writer::Slot<MachOHeader> header = WriteHeader(w);
512 uintptr_t load_command_start = w->position();
513 Writer::Slot<MachOSegmentCommand> cmd = WriteSegmentCommand(w,
516 WriteSections(w, cmd, header, load_command_start);
528 #if V8_TARGET_ARCH_X64
533 struct MachOSegmentCommand {
537 #if V8_TARGET_ARCH_IA32
554 enum MachOLoadCommandCmd {
555 LC_SEGMENT_32 = 0x00000001u,
556 LC_SEGMENT_64 = 0x00000019u
560 Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
561 ASSERT(w->position() == 0);
562 Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
563 #if V8_TARGET_ARCH_IA32
564 header->magic = 0xFEEDFACEu;
566 header->cpusubtype = 3;
567 #elif V8_TARGET_ARCH_X64
568 header->magic = 0xFEEDFACFu;
569 header->cputype = 7 | 0x01000000;
570 header->cpusubtype = 3;
571 header->reserved = 0;
573 #error Unsupported target architecture.
575 header->filetype = 0x1;
577 header->sizeofcmds = 0;
583 Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w,
584 uintptr_t code_start,
585 uintptr_t code_size) {
586 Writer::Slot<MachOSegmentCommand> cmd =
587 w->CreateSlotHere<MachOSegmentCommand>();
588 #if V8_TARGET_ARCH_IA32
589 cmd->cmd = LC_SEGMENT_32;
591 cmd->cmd = LC_SEGMENT_64;
593 cmd->vmaddr = code_start;
594 cmd->vmsize = code_size;
600 cmd->nsects = sections_.length();
601 memset(cmd->segname, 0, 16);
602 cmd->cmdsize =
sizeof(MachOSegmentCommand) +
sizeof(MachOSection::Header) *
608 void WriteSections(Writer* w,
609 Writer::Slot<MachOSegmentCommand> cmd,
610 Writer::Slot<MachOHeader> header,
611 uintptr_t load_command_start) {
612 Writer::Slot<MachOSection::Header> headers =
613 w->CreateSlotsHere<MachOSection::Header>(sections_.length());
614 cmd->fileoff = w->position();
615 header->sizeofcmds = w->position() - load_command_start;
616 for (
int section = 0; section < sections_.length(); ++section) {
617 sections_[section]->PopulateHeader(headers.at(section));
618 sections_[section]->WriteBody(headers.at(section), w);
620 cmd->filesize = w->position() - (uintptr_t)cmd->fileoff;
624 ZoneList<MachOSection*> sections_;
626 #endif // defined(__MACH_O)
632 explicit ELF(Zone* zone) : zone_(zone), sections_(6, zone) {
633 sections_.Add(
new(zone) ELFSection(
"", ELFSection::TYPE_NULL, 0), zone);
634 sections_.Add(
new(zone) ELFStringTable(
".shstrtab"), zone);
637 void Write(Writer* w) {
639 WriteSectionTable(w);
643 ELFSection* SectionAt(uint32_t index) {
644 return sections_[index];
647 uint32_t AddSection(ELFSection* section) {
648 sections_.Add(section, zone_);
649 section->set_index(sections_.length() - 1);
650 return sections_.length() - 1;
660 uintptr_t pht_offset;
661 uintptr_t sht_offset;
672 void WriteHeader(Writer* w) {
673 ASSERT(w->position() == 0);
674 Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
675 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM
676 const uint8_t ident[16] =
677 { 0x7f,
'E',
'L',
'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
678 #elif V8_TARGET_ARCH_X64
679 const uint8_t ident[16] =
680 { 0x7f,
'E',
'L',
'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
682 #error Unsupported target architecture.
686 #if V8_TARGET_ARCH_IA32
688 #elif V8_TARGET_ARCH_X64
692 header->machine = 62;
693 #elif V8_TARGET_ARCH_ARM
696 header->machine = 40;
698 #error Unsupported target architecture.
702 header->pht_offset = 0;
703 header->sht_offset =
sizeof(ELFHeader);
705 header->header_size =
sizeof(ELFHeader);
706 header->pht_entry_size = 0;
707 header->pht_entry_num = 0;
708 header->sht_entry_size =
sizeof(ELFSection::Header);
709 header->sht_entry_num = sections_.length();
710 header->sht_strtab_index = 1;
713 void WriteSectionTable(Writer* w) {
715 ASSERT(w->position() ==
sizeof(ELFHeader));
717 Writer::Slot<ELFSection::Header> headers =
718 w->CreateSlotsHere<ELFSection::Header>(sections_.length());
721 ELFStringTable* strtab =
static_cast<ELFStringTable*
>(SectionAt(1));
722 strtab->AttachWriter(w);
723 for (
int i = 0, length = sections_.length();
726 sections_[i]->PopulateHeader(headers.at(i), strtab);
728 strtab->DetachWriter();
731 int SectionHeaderPosition(uint32_t section_index) {
732 return sizeof(ELFHeader) +
sizeof(ELFSection::Header) * section_index;
735 void WriteSections(Writer* w) {
736 Writer::Slot<ELFSection::Header> headers =
737 w->SlotAt<ELFSection::Header>(
sizeof(ELFHeader));
739 for (
int i = 0, length = sections_.length();
742 sections_[i]->WriteBody(headers.at(i), w);
747 ZoneList<ELFSection*> sections_;
771 ELFSymbol(
const char* name,
780 info((binding << 4) | type),
785 Binding binding()
const {
786 return static_cast<Binding
>(
info >> 4);
788 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM
789 struct SerializedLayout {
790 SerializedLayout(uint32_t name,
799 info((binding << 4) | type),
811 #elif V8_TARGET_ARCH_X64
812 struct SerializedLayout {
813 SerializedLayout(uint32_t name,
820 info((binding << 4) | type),
836 void Write(Writer::Slot<SerializedLayout> s, ELFStringTable* t) {
838 s->name = t->Add(name);
843 s->section = section;
856 class ELFSymbolTable :
public ELFSection {
858 ELFSymbolTable(
const char* name, Zone* zone)
859 : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
864 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
865 w->Align(header->alignment);
866 int total_symbols = locals_.length() + globals_.length() + 1;
867 header->offset = w->position();
869 Writer::Slot<ELFSymbol::SerializedLayout>
symbols =
870 w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols);
872 header->size = w->position() - header->offset;
875 ELFStringTable* strtab =
876 static_cast<ELFStringTable*
>(w->debug_object()->SectionAt(index() + 1));
877 strtab->AttachWriter(w);
878 symbols.at(0).set(ELFSymbol::SerializedLayout(0,
881 ELFSymbol::BIND_LOCAL,
882 ELFSymbol::TYPE_NOTYPE,
884 WriteSymbolsList(&locals_, symbols.at(1), strtab);
885 WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab);
886 strtab->DetachWriter();
889 void Add(
const ELFSymbol& symbol, Zone* zone) {
890 if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
891 locals_.Add(symbol, zone);
893 globals_.Add(symbol, zone);
898 virtual void PopulateHeader(Writer::Slot<Header> header) {
899 ELFSection::PopulateHeader(header);
901 header->link = index() + 1;
902 header->info = locals_.length() + 1;
903 header->entry_size =
sizeof(ELFSymbol::SerializedLayout);
907 void WriteSymbolsList(
const ZoneList<ELFSymbol>* src,
908 Writer::Slot<ELFSymbol::SerializedLayout> dst,
909 ELFStringTable* strtab) {
910 for (
int i = 0, len = src->length();
913 src->at(i).Write(dst.at(i), strtab);
917 ZoneList<ELFSymbol> locals_;
918 ZoneList<ELFSymbol> globals_;
920 #endif // defined(__ELF)
925 #if V8_TARGET_ARCH_X64
934 CodeDescription(
const char* name,
936 Handle<Script> script,
937 GDBJITLineInfo* lineinfo,
938 GDBJITInterface::CodeTag tag,
939 CompilationInfo*
info)
948 const char*
name()
const {
952 GDBJITLineInfo* lineinfo()
const {
956 GDBJITInterface::CodeTag tag()
const {
960 CompilationInfo*
info()
const {
964 bool IsInfoAvailable()
const {
965 return info_ !=
NULL;
968 uintptr_t CodeStart()
const {
969 return reinterpret_cast<uintptr_t
>(code_->instruction_start());
972 uintptr_t CodeEnd()
const {
973 return reinterpret_cast<uintptr_t
>(code_->instruction_end());
976 uintptr_t CodeSize()
const {
977 return CodeEnd() - CodeStart();
980 bool IsLineInfoAvailable() {
981 return !script_.is_null() &&
982 script_->source()->IsString() &&
983 script_->HasValidSource() &&
984 script_->name()->IsString() &&
988 #if V8_TARGET_ARCH_X64
989 uintptr_t GetStackStateStartAddress(StackState state)
const {
990 ASSERT(state < STACK_STATE_MAX);
991 return stack_state_start_addresses_[state];
994 void SetStackStateStartAddress(StackState state, uintptr_t addr) {
995 ASSERT(state < STACK_STATE_MAX);
996 stack_state_start_addresses_[state] = addr;
1000 SmartArrayPointer<char> GetFilename() {
1012 Handle<Script> script_;
1013 GDBJITLineInfo* lineinfo_;
1014 GDBJITInterface::CodeTag tag_;
1015 CompilationInfo* info_;
1016 #if V8_TARGET_ARCH_X64
1017 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
1022 static void CreateSymbolsTable(CodeDescription* desc,
1025 int text_section_index) {
1026 ELFSymbolTable* symtab =
new(zone) ELFSymbolTable(
".symtab", zone);
1027 ELFStringTable* strtab =
new(zone) ELFStringTable(
".strtab");
1030 elf->AddSection(symtab);
1031 elf->AddSection(strtab);
1033 symtab->Add(ELFSymbol(
"V8 Code",
1036 ELFSymbol::BIND_LOCAL,
1037 ELFSymbol::TYPE_FILE,
1038 ELFSection::INDEX_ABSOLUTE),
1041 symtab->Add(ELFSymbol(desc->name(),
1044 ELFSymbol::BIND_GLOBAL,
1045 ELFSymbol::TYPE_FUNC,
1046 text_section_index),
1049 #endif // defined(__ELF)
1052 class DebugInfoSection :
public DebugSection {
1054 explicit DebugInfoSection(CodeDescription* desc)
1056 : ELFSection(
".debug_info", TYPE_PROGBITS, 1),
1058 : MachOSection(
"__debug_info",
1061 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1066 enum DWARF2LocationOp {
1078 enum DWARF2Encoding {
1079 DW_ATE_ADDRESS = 0x1,
1083 bool WriteBodyInternal(Writer* w) {
1084 uintptr_t cu_start = w->position();
1085 Writer::Slot<uint32_t>
size = w->CreateSlotHere<uint32_t>();
1086 uintptr_t start = w->position();
1088 w->Write<uint32_t>(0);
1089 w->Write<uint8_t>(
sizeof(intptr_t));
1092 w->WriteString(desc_->GetFilename().get());
1093 w->Write<intptr_t>(desc_->CodeStart());
1094 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1095 w->Write<uint32_t>(0);
1097 uint32_t ty_offset =
static_cast<uint32_t
>(w->position() - cu_start);
1100 w->WriteString(
"v8value");
1102 if (desc_->IsInfoAvailable()) {
1103 Scope* scope = desc_->info()->scope();
1105 w->WriteString(desc_->name());
1106 w->Write<intptr_t>(desc_->CodeStart());
1107 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1108 Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
1109 uintptr_t fb_block_start = w->position();
1110 #if V8_TARGET_ARCH_IA32
1111 w->Write<uint8_t>(DW_OP_reg5);
1112 #elif V8_TARGET_ARCH_X64
1113 w->Write<uint8_t>(DW_OP_reg6);
1114 #elif V8_TARGET_ARCH_ARM
1116 #elif V8_TARGET_ARCH_MIPS
1119 #error Unsupported target architecture.
1121 fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
1123 int params = scope->num_parameters();
1124 int slots = scope->num_stack_slots();
1125 int context_slots = scope->ContextLocalCount();
1128 int locals = scope->StackLocalCount();
1129 int current_abbreviation = 4;
1131 for (
int param = 0; param < params; ++param) {
1132 w->WriteULEB128(current_abbreviation++);
1134 scope->parameter(param)->name()->ToCString(
DISALLOW_NULLS).get());
1135 w->Write<uint32_t>(ty_offset);
1136 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1137 uintptr_t block_start = w->position();
1138 w->Write<uint8_t>(DW_OP_fbreg);
1142 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1145 EmbeddedVector<char, 256> buffer;
1146 StringBuilder builder(buffer.start(), buffer.length());
1148 for (
int slot = 0; slot < slots; ++slot) {
1149 w->WriteULEB128(current_abbreviation++);
1151 builder.AddFormatted(
"slot%d", slot);
1152 w->WriteString(builder.Finalize());
1161 w->WriteULEB128(current_abbreviation++);
1162 w->WriteString(
".closure");
1163 w->WriteULEB128(current_abbreviation++);
1164 w->WriteString(
".previous");
1165 w->WriteULEB128(current_abbreviation++);
1166 w->WriteString(
".extension");
1167 w->WriteULEB128(current_abbreviation++);
1168 w->WriteString(
".global");
1170 for (
int context_slot = 0;
1171 context_slot < context_slots;
1173 w->WriteULEB128(current_abbreviation++);
1175 builder.AddFormatted(
"context_slot%d", context_slot + internal_slots);
1176 w->WriteString(builder.Finalize());
1179 ZoneList<Variable*> stack_locals(locals, scope->zone());
1180 ZoneList<Variable*> context_locals(context_slots, scope->zone());
1181 scope->CollectStackAndContextLocals(&stack_locals, &context_locals);
1182 for (
int local = 0; local < locals; ++local) {
1183 w->WriteULEB128(current_abbreviation++);
1186 w->Write<uint32_t>(ty_offset);
1187 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1188 uintptr_t block_start = w->position();
1189 w->Write<uint8_t>(DW_OP_fbreg);
1193 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1197 w->WriteULEB128(current_abbreviation++);
1198 w->WriteString(
"__function");
1199 w->Write<uint32_t>(ty_offset);
1200 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1201 uintptr_t block_start = w->position();
1202 w->Write<uint8_t>(DW_OP_fbreg);
1204 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1208 w->WriteULEB128(current_abbreviation++);
1209 w->WriteString(
"__context");
1210 w->Write<uint32_t>(ty_offset);
1211 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1212 uintptr_t block_start = w->position();
1213 w->Write<uint8_t>(DW_OP_fbreg);
1215 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1222 size.set(static_cast<uint32_t>(w->position() - start));
1227 CodeDescription* desc_;
1231 class DebugAbbrevSection :
public DebugSection {
1233 explicit DebugAbbrevSection(CodeDescription* desc)
1235 : ELFSection(
".debug_abbrev", TYPE_PROGBITS, 1),
1237 : MachOSection(
"__debug_abbrev",
1240 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1246 DW_TAG_FORMAL_PARAMETER = 0x05,
1247 DW_TAG_POINTER_TYPE = 0xf,
1248 DW_TAG_COMPILE_UNIT = 0x11,
1249 DW_TAG_STRUCTURE_TYPE = 0x13,
1250 DW_TAG_BASE_TYPE = 0x24,
1251 DW_TAG_SUBPROGRAM = 0x2e,
1252 DW_TAG_VARIABLE = 0x34
1256 enum DWARF2ChildrenDetermination {
1262 enum DWARF2Attribute {
1263 DW_AT_LOCATION = 0x2,
1265 DW_AT_BYTE_SIZE = 0xb,
1266 DW_AT_STMT_LIST = 0x10,
1267 DW_AT_LOW_PC = 0x11,
1268 DW_AT_HIGH_PC = 0x12,
1269 DW_AT_ENCODING = 0x3e,
1270 DW_AT_FRAME_BASE = 0x40,
1275 enum DWARF2AttributeForm {
1277 DW_FORM_BLOCK4 = 0x4,
1278 DW_FORM_STRING = 0x8,
1279 DW_FORM_DATA4 = 0x6,
1280 DW_FORM_BLOCK = 0x9,
1281 DW_FORM_DATA1 = 0xb,
1286 void WriteVariableAbbreviation(Writer* w,
1287 int abbreviation_code,
1289 bool is_parameter) {
1290 w->WriteULEB128(abbreviation_code);
1291 w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
1292 w->Write<uint8_t>(DW_CHILDREN_NO);
1293 w->WriteULEB128(DW_AT_NAME);
1294 w->WriteULEB128(DW_FORM_STRING);
1296 w->WriteULEB128(DW_AT_TYPE);
1297 w->WriteULEB128(DW_FORM_REF4);
1298 w->WriteULEB128(DW_AT_LOCATION);
1299 w->WriteULEB128(DW_FORM_BLOCK4);
1305 bool WriteBodyInternal(Writer* w) {
1306 int current_abbreviation = 1;
1307 bool extra_info = desc_->IsInfoAvailable();
1308 ASSERT(desc_->IsLineInfoAvailable());
1309 w->WriteULEB128(current_abbreviation++);
1310 w->WriteULEB128(DW_TAG_COMPILE_UNIT);
1311 w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1312 w->WriteULEB128(DW_AT_NAME);
1313 w->WriteULEB128(DW_FORM_STRING);
1314 w->WriteULEB128(DW_AT_LOW_PC);
1315 w->WriteULEB128(DW_FORM_ADDR);
1316 w->WriteULEB128(DW_AT_HIGH_PC);
1317 w->WriteULEB128(DW_FORM_ADDR);
1318 w->WriteULEB128(DW_AT_STMT_LIST);
1319 w->WriteULEB128(DW_FORM_DATA4);
1324 Scope* scope = desc_->info()->scope();
1325 int params = scope->num_parameters();
1326 int slots = scope->num_stack_slots();
1327 int context_slots = scope->ContextLocalCount();
1330 int locals = scope->StackLocalCount();
1336 w->WriteULEB128(current_abbreviation++);
1337 w->WriteULEB128(DW_TAG_SUBPROGRAM);
1338 w->Write<uint8_t>(DW_CHILDREN_YES);
1339 w->WriteULEB128(DW_AT_NAME);
1340 w->WriteULEB128(DW_FORM_STRING);
1341 w->WriteULEB128(DW_AT_LOW_PC);
1342 w->WriteULEB128(DW_FORM_ADDR);
1343 w->WriteULEB128(DW_AT_HIGH_PC);
1344 w->WriteULEB128(DW_FORM_ADDR);
1345 w->WriteULEB128(DW_AT_FRAME_BASE);
1346 w->WriteULEB128(DW_FORM_BLOCK4);
1350 w->WriteULEB128(current_abbreviation++);
1351 w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
1352 w->Write<uint8_t>(DW_CHILDREN_NO);
1353 w->WriteULEB128(DW_AT_BYTE_SIZE);
1354 w->WriteULEB128(DW_FORM_DATA1);
1355 w->WriteULEB128(DW_AT_NAME);
1356 w->WriteULEB128(DW_FORM_STRING);
1360 for (
int param = 0; param < params; ++param) {
1361 WriteVariableAbbreviation(w, current_abbreviation++,
true,
true);
1364 for (
int slot = 0; slot < slots; ++slot) {
1365 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1368 for (
int internal_slot = 0;
1369 internal_slot < internal_slots;
1371 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1374 for (
int context_slot = 0;
1375 context_slot < context_slots;
1377 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1380 for (
int local = 0; local < locals; ++local) {
1381 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1385 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1388 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1398 CodeDescription* desc_;
1402 class DebugLineSection :
public DebugSection {
1404 explicit DebugLineSection(CodeDescription* desc)
1406 : ELFSection(
".debug_line", TYPE_PROGBITS, 1),
1408 : MachOSection(
"__debug_line",
1411 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1416 enum DWARF2Opcodes {
1418 DW_LNS_ADVANCE_PC = 2,
1419 DW_LNS_ADVANCE_LINE = 3,
1420 DW_LNS_SET_FILE = 4,
1421 DW_LNS_SET_COLUMN = 5,
1422 DW_LNS_NEGATE_STMT = 6
1426 enum DWARF2ExtendedOpcode {
1427 DW_LNE_END_SEQUENCE = 1,
1428 DW_LNE_SET_ADDRESS = 2,
1429 DW_LNE_DEFINE_FILE = 3
1432 bool WriteBodyInternal(Writer* w) {
1434 Writer::Slot<uint32_t> total_length = w->CreateSlotHere<uint32_t>();
1435 uintptr_t start = w->position();
1438 const int8_t line_base = 1;
1439 const uint8_t line_range = 7;
1440 const int8_t max_line_incr = (line_base + line_range - 1);
1441 const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
1444 Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<uint32_t>();
1445 uintptr_t prologue_start = w->position();
1446 w->Write<uint8_t>(1);
1447 w->Write<uint8_t>(1);
1448 w->Write<int8_t>(line_base);
1449 w->Write<uint8_t>(line_range);
1450 w->Write<uint8_t>(opcode_base);
1451 w->Write<uint8_t>(0);
1452 w->Write<uint8_t>(1);
1453 w->Write<uint8_t>(1);
1454 w->Write<uint8_t>(1);
1455 w->Write<uint8_t>(1);
1456 w->Write<uint8_t>(0);
1457 w->Write<uint8_t>(0);
1458 w->WriteString(desc_->GetFilename().get());
1462 w->Write<uint8_t>(0);
1463 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
1465 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS,
sizeof(intptr_t));
1466 w->Write<intptr_t>(desc_->CodeStart());
1467 w->Write<uint8_t>(DW_LNS_COPY);
1471 bool is_statement =
true;
1473 List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
1474 pc_info->Sort(&ComparePCInfo);
1476 int pc_info_length = pc_info->length();
1477 for (
int i = 0; i < pc_info_length; i++) {
1478 GDBJITLineInfo::PCInfo*
info = &pc_info->at(i);
1483 intptr_t new_line = desc_->GetScriptLineNumber(info->pos_);
1484 if (new_line == line) {
1492 if ((i+1) == pc_info_length) {
1493 if (!is_statement) {
1494 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1496 }
else if (is_statement != info->is_statement_) {
1497 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1498 is_statement = !is_statement;
1504 uintptr_t pc_diff = info->pc_ -
pc;
1505 intptr_t line_diff = new_line - line;
1508 intptr_t special_opcode = (line_diff - line_base) +
1509 (line_range * pc_diff) + opcode_base;
1516 if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
1517 (line_diff <= max_line_incr) && (line_diff >= line_base)) {
1518 w->Write<uint8_t>(special_opcode);
1520 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1521 w->WriteSLEB128(pc_diff);
1522 w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
1523 w->WriteSLEB128(line_diff);
1524 w->Write<uint8_t>(DW_LNS_COPY);
1533 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1534 w->WriteSLEB128(desc_->CodeSize() -
pc);
1535 WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
1536 total_length.set(static_cast<uint32_t>(w->position() - start));
1541 void WriteExtendedOpcode(Writer* w,
1542 DWARF2ExtendedOpcode op,
1543 size_t operands_size) {
1544 w->Write<uint8_t>(0);
1545 w->WriteULEB128(operands_size + 1);
1546 w->Write<uint8_t>(op);
1549 static int ComparePCInfo(
const GDBJITLineInfo::PCInfo* a,
1550 const GDBJITLineInfo::PCInfo* b) {
1551 if (a->pc_ == b->pc_) {
1552 if (a->is_statement_ != b->is_statement_) {
1553 return b->is_statement_ ? +1 : -1;
1556 }
else if (a->pc_ > b->pc_) {
1563 CodeDescription* desc_;
1567 #if V8_TARGET_ARCH_X64
1569 class UnwindInfoSection :
public DebugSection {
1571 explicit UnwindInfoSection(CodeDescription* desc);
1572 virtual bool WriteBodyInternal(Writer* w);
1574 int WriteCIE(Writer* w);
1575 void WriteFDE(Writer* w,
int);
1577 void WriteFDEStateOnEntry(Writer* w);
1578 void WriteFDEStateAfterRBPPush(Writer* w);
1579 void WriteFDEStateAfterRBPSet(Writer* w);
1580 void WriteFDEStateAfterRBPPop(Writer* w);
1582 void WriteLength(Writer* w,
1583 Writer::Slot<uint32_t>* length_slot,
1584 int initial_position);
1587 CodeDescription* desc_;
1590 enum CFIInstructions {
1591 DW_CFA_ADVANCE_LOC = 0x40,
1592 DW_CFA_OFFSET = 0x80,
1593 DW_CFA_RESTORE = 0xC0,
1595 DW_CFA_SET_LOC = 0x01,
1596 DW_CFA_ADVANCE_LOC1 = 0x02,
1597 DW_CFA_ADVANCE_LOC2 = 0x03,
1598 DW_CFA_ADVANCE_LOC4 = 0x04,
1599 DW_CFA_OFFSET_EXTENDED = 0x05,
1600 DW_CFA_RESTORE_EXTENDED = 0x06,
1601 DW_CFA_UNDEFINED = 0x07,
1602 DW_CFA_SAME_VALUE = 0x08,
1603 DW_CFA_REGISTER = 0x09,
1604 DW_CFA_REMEMBER_STATE = 0x0A,
1605 DW_CFA_RESTORE_STATE = 0x0B,
1606 DW_CFA_DEF_CFA = 0x0C,
1607 DW_CFA_DEF_CFA_REGISTER = 0x0D,
1608 DW_CFA_DEF_CFA_OFFSET = 0x0E,
1610 DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
1611 DW_CFA_EXPRESSION = 0x10,
1612 DW_CFA_OFFSET_EXTENDED_SF = 0x11,
1613 DW_CFA_DEF_CFA_SF = 0x12,
1614 DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
1615 DW_CFA_VAL_OFFSET = 0x14,
1616 DW_CFA_VAL_OFFSET_SF = 0x15,
1617 DW_CFA_VAL_EXPRESSION = 0x16
1621 enum RegisterMapping {
1631 CODE_ALIGN_FACTOR = 1,
1632 DATA_ALIGN_FACTOR = 1,
1633 RETURN_ADDRESS_REGISTER = AMD64_RA
1638 void UnwindInfoSection::WriteLength(Writer* w,
1639 Writer::Slot<uint32_t>* length_slot,
1640 int initial_position) {
1641 uint32_t align = (w->position() - initial_position) %
kPointerSize;
1644 for (uint32_t i = 0; i < (
kPointerSize - align); i++) {
1645 w->Write<uint8_t>(DW_CFA_NOP);
1650 length_slot->set(w->position() - initial_position);
1654 UnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
1656 : ELFSection(
".eh_frame", TYPE_X86_64_UNWIND, 1),
1658 : MachOSection(
"__eh_frame",
"__TEXT",
sizeof(uintptr_t),
1659 MachOSection::S_REGULAR),
1663 int UnwindInfoSection::WriteCIE(Writer* w) {
1664 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
1665 uint32_t cie_position = w->position();
1670 w->Write<uint32_t>(CIE_ID);
1671 w->Write<uint8_t>(CIE_VERSION);
1672 w->Write<uint8_t>(0);
1673 w->WriteSLEB128(CODE_ALIGN_FACTOR);
1674 w->WriteSLEB128(DATA_ALIGN_FACTOR);
1675 w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
1677 WriteLength(w, &cie_length_slot, cie_position);
1679 return cie_position;
1683 void UnwindInfoSection::WriteFDE(Writer* w,
int cie_position) {
1685 Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
1686 int fde_position = w->position();
1687 w->Write<
int32_t>(fde_position - cie_position + 4);
1689 w->Write<uintptr_t>(desc_->CodeStart());
1690 w->Write<uintptr_t>(desc_->CodeSize());
1692 WriteFDEStateOnEntry(w);
1693 WriteFDEStateAfterRBPPush(w);
1694 WriteFDEStateAfterRBPSet(w);
1695 WriteFDEStateAfterRBPPop(w);
1697 WriteLength(w, &fde_length_slot, fde_position);
1701 void UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
1707 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1708 w->WriteULEB128(AMD64_RSP);
1713 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1714 w->WriteULEB128(AMD64_RA);
1718 w->Write<uint8_t>(DW_CFA_SAME_VALUE);
1719 w->WriteULEB128(AMD64_RBP);
1722 w->Write<uint8_t>(DW_CFA_SET_LOC);
1724 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
1728 void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
1733 w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
1738 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1739 w->WriteULEB128(AMD64_RBP);
1743 w->Write<uint8_t>(DW_CFA_SET_LOC);
1745 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
1749 void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
1753 w->Write<uint8_t>(DW_CFA_DEF_CFA);
1754 w->WriteULEB128(AMD64_RBP);
1758 w->Write<uint8_t>(DW_CFA_SET_LOC);
1760 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
1764 void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
1769 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1770 w->WriteULEB128(AMD64_RSP);
1774 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1775 w->WriteULEB128(AMD64_RBP);
1779 w->Write<uint8_t>(DW_CFA_SET_LOC);
1780 w->Write<uint64_t>(desc_->CodeEnd());
1784 bool UnwindInfoSection::WriteBodyInternal(Writer* w) {
1785 uint32_t cie_position = WriteCIE(w);
1786 WriteFDE(w, cie_position);
1791 #endif // V8_TARGET_ARCH_X64
1793 static void CreateDWARFSections(CodeDescription* desc,
1796 if (desc->IsLineInfoAvailable()) {
1797 obj->AddSection(
new(zone) DebugInfoSection(desc));
1798 obj->AddSection(
new(zone) DebugAbbrevSection(desc));
1799 obj->AddSection(
new(zone) DebugLineSection(desc));
1801 #if V8_TARGET_ARCH_X64
1802 obj->AddSection(
new(zone) UnwindInfoSection(desc));
1817 struct JITCodeEntry {
1818 JITCodeEntry* next_;
1819 JITCodeEntry* prev_;
1821 uint64_t symfile_size_;
1824 struct JITDescriptor {
1826 uint32_t action_flag_;
1827 JITCodeEntry* relevant_entry_;
1828 JITCodeEntry* first_entry_;
1834 void __attribute__((noinline)) __jit_debug_register_code() {
1841 JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
1844 void __gdb_print_v8_object(MaybeObject*
object) {
1852 static JITCodeEntry* CreateCodeEntry(
Address symfile_addr,
1853 uintptr_t symfile_size) {
1854 JITCodeEntry* entry =
static_cast<JITCodeEntry*
>(
1855 malloc(
sizeof(JITCodeEntry) + symfile_size));
1857 entry->symfile_addr_ =
reinterpret_cast<Address>(entry + 1);
1858 entry->symfile_size_ = symfile_size;
1859 OS::MemCopy(entry->symfile_addr_, symfile_addr, symfile_size);
1861 entry->prev_ = entry->next_ =
NULL;
1867 static void DestroyCodeEntry(JITCodeEntry* entry) {
1872 static void RegisterCodeEntry(JITCodeEntry* entry,
1873 bool dump_if_enabled,
1874 const char* name_hint) {
1875 #if defined(DEBUG) && !V8_OS_WIN
1876 static int file_num = 0;
1877 if (FLAG_gdbjit_dump && dump_if_enabled) {
1878 static const int kMaxFileNameSize = 64;
1879 static const char* kElfFilePrefix =
"/tmp/elfdump";
1880 static const char* kObjFileExt =
".o";
1883 OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize),
1886 (name_hint !=
NULL) ? name_hint :
"",
1889 WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
1893 entry->next_ = __jit_debug_descriptor.first_entry_;
1894 if (entry->next_ !=
NULL) entry->next_->prev_ = entry;
1895 __jit_debug_descriptor.first_entry_ =
1896 __jit_debug_descriptor.relevant_entry_ = entry;
1898 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
1899 __jit_debug_register_code();
1903 static void UnregisterCodeEntry(JITCodeEntry* entry) {
1904 if (entry->prev_ !=
NULL) {
1905 entry->prev_->next_ = entry->next_;
1907 __jit_debug_descriptor.first_entry_ = entry->next_;
1910 if (entry->next_ !=
NULL) {
1911 entry->next_->prev_ = entry->prev_;
1914 __jit_debug_descriptor.relevant_entry_ = entry;
1915 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
1916 __jit_debug_register_code();
1920 static JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) {
1923 MachO mach_o(&zone);
1930 CreateDWARFSections(desc, &zone, &mach_o);
1932 mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
1938 int text_section_index = elf.AddSection(
1939 new(&zone) FullHeaderELFSection(
1941 ELFSection::TYPE_NOBITS,
1946 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
1948 CreateSymbolsTable(desc, &zone, &elf, text_section_index);
1950 CreateDWARFSections(desc, &zone, &elf);
1955 return CreateCodeEntry(w.buffer(), w.position());
1959 static bool SameCodeObjects(
void* key1,
void* key2) {
1960 return key1 == key2;
1964 static HashMap* GetEntries() {
1966 if (entries ==
NULL) {
1967 entries =
new HashMap(&SameCodeObjects);
1973 static uint32_t HashForCodeObject(Code*
code) {
1974 static const uintptr_t kGoldenRatio = 2654435761u;
1975 uintptr_t hash =
reinterpret_cast<uintptr_t
>(code->address());
1980 static const intptr_t kLineInfoTag = 0x1;
1983 static bool IsLineInfoTagged(
void* ptr) {
1984 return 0 != (
reinterpret_cast<intptr_t
>(ptr) & kLineInfoTag);
1988 static void* TagLineInfo(GDBJITLineInfo* ptr) {
1989 return reinterpret_cast<void*
>(
1990 reinterpret_cast<intptr_t
>(ptr) | kLineInfoTag);
1994 static GDBJITLineInfo* UntagLineInfo(
void* ptr) {
1995 return reinterpret_cast<GDBJITLineInfo*
>(
1996 reinterpret_cast<intptr_t
>(ptr) & ~kLineInfoTag);
2000 void GDBJITInterface::AddCode(Handle<Name> name,
2001 Handle<Script> script,
2003 CompilationInfo* info) {
2004 if (!FLAG_gdbjit)
return;
2009 if (!name.is_null() && name->IsString()) {
2010 SmartArrayPointer<char> name_cstring =
2012 AddCode(name_cstring.get(), *
code, GDBJITInterface::FUNCTION, *script,
2015 AddCode(
"", *code, GDBJITInterface::FUNCTION, *script, info);
2020 static void AddUnwindInfo(CodeDescription* desc) {
2021 #if V8_TARGET_ARCH_X64
2022 if (desc->tag() == GDBJITInterface::FUNCTION) {
2026 static const int kFramePointerPushOffset = 1;
2027 static const int kFramePointerSetOffset = 4;
2028 static const int kFramePointerPopOffset = -3;
2030 uintptr_t frame_pointer_push_address =
2031 desc->CodeStart() + kFramePointerPushOffset;
2033 uintptr_t frame_pointer_set_address =
2034 desc->CodeStart() + kFramePointerSetOffset;
2036 uintptr_t frame_pointer_pop_address =
2037 desc->CodeEnd() + kFramePointerPopOffset;
2039 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2040 frame_pointer_push_address);
2041 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2042 frame_pointer_set_address);
2043 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2044 frame_pointer_pop_address);
2046 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2048 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2050 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2053 #endif // V8_TARGET_ARCH_X64
2060 void GDBJITInterface::AddCode(
const char* name,
2062 GDBJITInterface::CodeTag tag,
2064 CompilationInfo* info) {
2065 if (!FLAG_gdbjit)
return;
2067 LockGuard<Mutex> lock_guard(mutex.Pointer());
2070 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code),
true);
2071 if (e->value !=
NULL && !IsLineInfoTagged(e->value))
return;
2073 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value);
2074 CodeDescription code_desc(name,
2076 script !=
NULL ? Handle<Script>(script)
2082 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
2084 GetEntries()->Remove(code, HashForCodeObject(code));
2088 AddUnwindInfo(&code_desc);
2089 Isolate* isolate = code->GetIsolate();
2090 JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
2091 ASSERT(!IsLineInfoTagged(entry));
2096 const char* name_hint =
NULL;
2097 bool should_dump =
false;
2098 if (FLAG_gdbjit_dump) {
2099 if (strlen(FLAG_gdbjit_dump_filter) == 0) {
2102 }
else if (name !=
NULL) {
2103 name_hint = strstr(name, FLAG_gdbjit_dump_filter);
2104 should_dump = (name_hint !=
NULL);
2107 RegisterCodeEntry(entry, should_dump, name_hint);
2111 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
2114 if (!FLAG_gdbjit)
return;
2116 EmbeddedVector<char, 256> buffer;
2117 StringBuilder builder(buffer.start(), buffer.length());
2119 builder.AddString(Tag2String(tag));
2120 if ((name !=
NULL) && (*name !=
'\0')) {
2121 builder.AddString(
": ");
2122 builder.AddString(name);
2124 builder.AddFormatted(
": code object %p", static_cast<void*>(code));
2131 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
2134 if (!FLAG_gdbjit)
return;
2138 AddCode(tag,
"", code);
2143 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, Code* code) {
2144 if (!FLAG_gdbjit)
return;
2146 AddCode(tag,
"", code);
2150 void GDBJITInterface::RemoveCode(Code* code) {
2151 if (!FLAG_gdbjit)
return;
2153 LockGuard<Mutex> lock_guard(mutex.Pointer());
2154 HashMap::Entry* e = GetEntries()->Lookup(code,
2155 HashForCodeObject(code),
2157 if (e ==
NULL)
return;
2159 if (IsLineInfoTagged(e->value)) {
2160 delete UntagLineInfo(e->value);
2162 JITCodeEntry* entry =
static_cast<JITCodeEntry*
>(e->value);
2163 UnregisterCodeEntry(entry);
2164 DestroyCodeEntry(entry);
2167 GetEntries()->Remove(code, HashForCodeObject(code));
2171 void GDBJITInterface::RemoveCodeRange(
Address start,
Address end) {
2172 HashMap* entries = GetEntries();
2173 Zone zone(Isolate::Current());
2174 ZoneList<Code*> dead_codes(1, &zone);
2176 for (HashMap::Entry* e = entries->Start(); e !=
NULL; e = entries->Next(e)) {
2177 Code* code =
reinterpret_cast<Code*
>(e->key);
2178 if (code->address() >= start && code->address() < end) {
2179 dead_codes.Add(code, &zone);
2183 for (
int i = 0; i < dead_codes.length(); i++) {
2184 RemoveCode(dead_codes.at(i));
2189 void GDBJITInterface::RegisterDetailedLineInfo(Code* code,
2190 GDBJITLineInfo* line_info) {
2191 LockGuard<Mutex> lock_guard(mutex.Pointer());
2192 ASSERT(!IsLineInfoTagged(line_info));
2193 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code),
true);
2195 e->value = TagLineInfo(line_info);
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
static const int kLastParameterOffset
const char * ToCString(const v8::String::Utf8Value &value)
#define LAZY_MUTEX_INITIALIZER
void PrintF(const char *format,...)
static String * cast(Object *obj)
static Handle< T > cast(Handle< S > that)
enable upcoming ES6 features enable harmony block scoping enable harmony symbols(a.k.a.private names)") DEFINE_bool(harmony_proxies
TypeImpl< ZoneTypeConfig > Type
#define ASSERT(condition)
static const int kContextOffset
const intptr_t kCodeAlignment
static const int kCallerFPOffset
int WhichPowerOf2(uint32_t x)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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 expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including flags
static void MemCopy(void *dest, const void *src, size_t size)
LazyStaticInstance< Mutex, DefaultConstructTrait< Mutex >, ThreadSafeInitOnceTrait >::type LazyMutex
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
int GetScriptLineNumberSafe(Handle< Script > script, int code_pos)
static const int kCallerPCOffset
#define T(name, string, precedence)
V8_INLINE bool IsString() const
static int SNPrintF(Vector< char > str, const char *format,...)
int GetScriptLineNumber(Handle< Script > script, int code_pos)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
static const int kFunctionOffset
const int kCodeAlignmentBits
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
int WriteBytes(const char *filename, const byte *bytes, int size, bool verbose)
static const int kLocal0Offset
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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 expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name