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;
131 DebugObject* debug_object() {
return debug_object_; }
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_;
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 defined(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, StringTable* 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 StringTable :
public ELFSection {
443 explicit StringTable(
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 StringTable* 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 MachO() : sections_(6) { }
505 uint32_t AddSection(MachOSection* section) {
506 sections_.Add(section);
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 defined(V8_TARGET_ARCH_X64)
533 struct MachOSegmentCommand {
537 #if defined(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 defined(V8_TARGET_ARCH_IA32)
564 header->magic = 0xFEEDFACEu;
566 header->cpusubtype = 3;
567 #elif defined(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 defined(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 ELF(Zone* zone) : sections_(6, zone) {
633 sections_.Add(
new(zone) ELFSection(
"", ELFSection::TYPE_NULL, 0), zone);
634 sections_.Add(
new(zone) StringTable(
".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, Zone* zone) {
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 defined(V8_TARGET_ARCH_IA32) || defined(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 defined(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.
684 memcpy(header->ident, ident, 16);
686 #if defined(V8_TARGET_ARCH_IA32)
688 #elif defined(V8_TARGET_ARCH_X64)
692 header->machine = 62;
693 #elif defined(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 StringTable* strtab =
static_cast<StringTable*
>(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);
746 ZoneList<ELFSection*> sections_;
770 ELFSymbol(
const char* name,
779 info((binding << 4) | type),
784 Binding binding()
const {
785 return static_cast<Binding
>(info >> 4);
787 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_ARM)
788 struct SerializedLayout {
789 SerializedLayout(uint32_t name,
798 info((binding << 4) | type),
810 #elif defined(V8_TARGET_ARCH_X64)
811 struct SerializedLayout {
812 SerializedLayout(uint32_t name,
819 info((binding << 4) | type),
835 void Write(Writer::Slot<SerializedLayout> s, StringTable* t) {
837 s->name = t->Add(name);
842 s->section = section;
855 class ELFSymbolTable :
public ELFSection {
857 ELFSymbolTable(
const char* name, Zone* zone)
858 : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
863 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
864 w->Align(header->alignment);
865 int total_symbols = locals_.length() + globals_.length() + 1;
866 header->offset = w->position();
868 Writer::Slot<ELFSymbol::SerializedLayout> symbols =
869 w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols);
871 header->size = w->position() - header->offset;
874 StringTable* strtab =
875 static_cast<StringTable*
>(w->debug_object()->SectionAt(index() + 1));
876 strtab->AttachWriter(w);
877 symbols.at(0).set(ELFSymbol::SerializedLayout(0,
880 ELFSymbol::BIND_LOCAL,
881 ELFSymbol::TYPE_NOTYPE,
883 WriteSymbolsList(&locals_, symbols.at(1), strtab);
884 WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab);
885 strtab->DetachWriter();
888 void Add(
const ELFSymbol& symbol, Zone* zone) {
889 if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
890 locals_.Add(symbol, zone);
892 globals_.Add(symbol, zone);
897 virtual void PopulateHeader(Writer::Slot<Header> header) {
898 ELFSection::PopulateHeader(header);
900 header->link = index() + 1;
901 header->info = locals_.length() + 1;
902 header->entry_size =
sizeof(ELFSymbol::SerializedLayout);
906 void WriteSymbolsList(
const ZoneList<ELFSymbol>* src,
907 Writer::Slot<ELFSymbol::SerializedLayout> dst,
908 StringTable* strtab) {
909 for (
int i = 0, len = src->length();
912 src->at(i).Write(dst.at(i), strtab);
916 ZoneList<ELFSymbol> locals_;
917 ZoneList<ELFSymbol> globals_;
919 #endif // defined(__ELF)
924 #ifdef V8_TARGET_ARCH_X64
933 CodeDescription(
const char* name,
935 Handle<Script> script,
936 GDBJITLineInfo* lineinfo,
937 GDBJITInterface::CodeTag tag,
938 CompilationInfo* info)
947 const char* name()
const {
951 GDBJITLineInfo* lineinfo()
const {
955 GDBJITInterface::CodeTag tag()
const {
959 CompilationInfo* info()
const {
963 bool IsInfoAvailable()
const {
964 return info_ !=
NULL;
967 uintptr_t CodeStart()
const {
968 return reinterpret_cast<uintptr_t
>(code_->instruction_start());
971 uintptr_t CodeEnd()
const {
972 return reinterpret_cast<uintptr_t
>(code_->instruction_end());
975 uintptr_t CodeSize()
const {
976 return CodeEnd() - CodeStart();
979 bool IsLineInfoAvailable() {
980 return !script_.is_null() &&
981 script_->source()->IsString() &&
982 script_->HasValidSource() &&
983 script_->name()->IsString() &&
987 #ifdef V8_TARGET_ARCH_X64
988 uintptr_t GetStackStateStartAddress(StackState state)
const {
989 ASSERT(state < STACK_STATE_MAX);
990 return stack_state_start_addresses_[state];
993 void SetStackStateStartAddress(StackState state, uintptr_t addr) {
994 ASSERT(state < STACK_STATE_MAX);
995 stack_state_start_addresses_[state] = addr;
999 SmartArrayPointer<char> GetFilename() {
1011 Handle<Script> script_;
1012 GDBJITLineInfo* lineinfo_;
1013 GDBJITInterface::CodeTag tag_;
1014 CompilationInfo* info_;
1015 #ifdef V8_TARGET_ARCH_X64
1016 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
1021 static void CreateSymbolsTable(CodeDescription* desc,
1023 int text_section_index) {
1024 Zone* zone = desc->info()->zone();
1025 ELFSymbolTable* symtab =
new(zone) ELFSymbolTable(
".symtab", zone);
1026 StringTable* strtab =
new(zone) StringTable(
".strtab");
1029 elf->AddSection(symtab, zone);
1030 elf->AddSection(strtab, zone);
1032 symtab->Add(ELFSymbol(
"V8 Code",
1035 ELFSymbol::BIND_LOCAL,
1036 ELFSymbol::TYPE_FILE,
1037 ELFSection::INDEX_ABSOLUTE),
1040 symtab->Add(ELFSymbol(desc->name(),
1043 ELFSymbol::BIND_GLOBAL,
1044 ELFSymbol::TYPE_FUNC,
1045 text_section_index),
1048 #endif // defined(__ELF)
1051 class DebugInfoSection :
public DebugSection {
1053 explicit DebugInfoSection(CodeDescription* desc)
1055 : ELFSection(
".debug_info", TYPE_PROGBITS, 1),
1057 : MachOSection(
"__debug_info",
1060 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1065 enum DWARF2LocationOp {
1077 enum DWARF2Encoding {
1078 DW_ATE_ADDRESS = 0x1,
1082 bool WriteBodyInternal(Writer* w) {
1083 uintptr_t cu_start = w->position();
1084 Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>();
1085 uintptr_t start = w->position();
1087 w->Write<uint32_t>(0);
1088 w->Write<uint8_t>(
sizeof(intptr_t));
1091 w->WriteString(*desc_->GetFilename());
1092 w->Write<intptr_t>(desc_->CodeStart());
1093 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1094 w->Write<uint32_t>(0);
1096 uint32_t ty_offset =
static_cast<uint32_t
>(w->position() - cu_start);
1099 w->WriteString(
"v8value");
1101 if (desc_->IsInfoAvailable()) {
1102 Scope* scope = desc_->info()->scope();
1104 w->WriteString(desc_->name());
1105 w->Write<intptr_t>(desc_->CodeStart());
1106 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1107 Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
1108 uintptr_t fb_block_start = w->position();
1109 #if defined(V8_TARGET_ARCH_IA32)
1110 w->Write<uint8_t>(DW_OP_reg5);
1111 #elif defined(V8_TARGET_ARCH_X64)
1112 w->Write<uint8_t>(DW_OP_reg6);
1113 #elif defined(V8_TARGET_ARCH_ARM)
1115 #elif defined(V8_TARGET_ARCH_MIPS)
1118 #error Unsupported target architecture.
1120 fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
1122 int params = scope->num_parameters();
1123 int slots = scope->num_stack_slots();
1124 int context_slots = scope->ContextLocalCount();
1127 int locals = scope->StackLocalCount();
1128 int current_abbreviation = 4;
1130 for (
int param = 0; param < params; ++param) {
1131 w->WriteULEB128(current_abbreviation++);
1134 w->Write<uint32_t>(ty_offset);
1135 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1136 uintptr_t block_start = w->position();
1137 w->Write<uint8_t>(DW_OP_fbreg);
1141 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1144 EmbeddedVector<char, 256> buffer;
1145 StringBuilder builder(buffer.start(), buffer.length());
1147 for (
int slot = 0; slot < slots; ++slot) {
1148 w->WriteULEB128(current_abbreviation++);
1150 builder.AddFormatted(
"slot%d", slot);
1151 w->WriteString(builder.Finalize());
1160 w->WriteULEB128(current_abbreviation++);
1161 w->WriteString(
".closure");
1162 w->WriteULEB128(current_abbreviation++);
1163 w->WriteString(
".previous");
1164 w->WriteULEB128(current_abbreviation++);
1165 w->WriteString(
".extension");
1166 w->WriteULEB128(current_abbreviation++);
1167 w->WriteString(
".global");
1169 for (
int context_slot = 0;
1170 context_slot < context_slots;
1172 w->WriteULEB128(current_abbreviation++);
1174 builder.AddFormatted(
"context_slot%d", context_slot + internal_slots);
1175 w->WriteString(builder.Finalize());
1178 ZoneList<Variable*> stack_locals(locals, scope->zone());
1179 ZoneList<Variable*> context_locals(context_slots, scope->zone());
1180 scope->CollectStackAndContextLocals(&stack_locals, &context_locals);
1181 for (
int local = 0; local < locals; ++local) {
1182 w->WriteULEB128(current_abbreviation++);
1185 w->Write<uint32_t>(ty_offset);
1186 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1187 uintptr_t block_start = w->position();
1188 w->Write<uint8_t>(DW_OP_fbreg);
1192 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1196 w->WriteULEB128(current_abbreviation++);
1197 w->WriteString(
"__function");
1198 w->Write<uint32_t>(ty_offset);
1199 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1200 uintptr_t block_start = w->position();
1201 w->Write<uint8_t>(DW_OP_fbreg);
1203 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1207 w->WriteULEB128(current_abbreviation++);
1208 w->WriteString(
"__context");
1209 w->Write<uint32_t>(ty_offset);
1210 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1211 uintptr_t block_start = w->position();
1212 w->Write<uint8_t>(DW_OP_fbreg);
1214 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1218 size.set(static_cast<uint32_t>(w->position() - start));
1223 CodeDescription* desc_;
1227 class DebugAbbrevSection :
public DebugSection {
1229 explicit DebugAbbrevSection(CodeDescription* desc)
1231 : ELFSection(
".debug_abbrev", TYPE_PROGBITS, 1),
1233 : MachOSection(
"__debug_abbrev",
1236 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1242 DW_TAG_FORMAL_PARAMETER = 0x05,
1243 DW_TAG_POINTER_TYPE = 0xf,
1244 DW_TAG_COMPILE_UNIT = 0x11,
1245 DW_TAG_STRUCTURE_TYPE = 0x13,
1246 DW_TAG_BASE_TYPE = 0x24,
1247 DW_TAG_SUBPROGRAM = 0x2e,
1248 DW_TAG_VARIABLE = 0x34
1252 enum DWARF2ChildrenDetermination {
1258 enum DWARF2Attribute {
1259 DW_AT_LOCATION = 0x2,
1261 DW_AT_BYTE_SIZE = 0xb,
1262 DW_AT_STMT_LIST = 0x10,
1263 DW_AT_LOW_PC = 0x11,
1264 DW_AT_HIGH_PC = 0x12,
1265 DW_AT_ENCODING = 0x3e,
1266 DW_AT_FRAME_BASE = 0x40,
1271 enum DWARF2AttributeForm {
1273 DW_FORM_BLOCK4 = 0x4,
1274 DW_FORM_STRING = 0x8,
1275 DW_FORM_DATA4 = 0x6,
1276 DW_FORM_BLOCK = 0x9,
1277 DW_FORM_DATA1 = 0xb,
1282 void WriteVariableAbbreviation(Writer* w,
1283 int abbreviation_code,
1285 bool is_parameter) {
1286 w->WriteULEB128(abbreviation_code);
1287 w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
1288 w->Write<uint8_t>(DW_CHILDREN_NO);
1289 w->WriteULEB128(DW_AT_NAME);
1290 w->WriteULEB128(DW_FORM_STRING);
1292 w->WriteULEB128(DW_AT_TYPE);
1293 w->WriteULEB128(DW_FORM_REF4);
1294 w->WriteULEB128(DW_AT_LOCATION);
1295 w->WriteULEB128(DW_FORM_BLOCK4);
1301 bool WriteBodyInternal(Writer* w) {
1302 int current_abbreviation = 1;
1303 bool extra_info = desc_->IsInfoAvailable();
1304 ASSERT(desc_->IsLineInfoAvailable());
1305 w->WriteULEB128(current_abbreviation++);
1306 w->WriteULEB128(DW_TAG_COMPILE_UNIT);
1307 w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1308 w->WriteULEB128(DW_AT_NAME);
1309 w->WriteULEB128(DW_FORM_STRING);
1310 w->WriteULEB128(DW_AT_LOW_PC);
1311 w->WriteULEB128(DW_FORM_ADDR);
1312 w->WriteULEB128(DW_AT_HIGH_PC);
1313 w->WriteULEB128(DW_FORM_ADDR);
1314 w->WriteULEB128(DW_AT_STMT_LIST);
1315 w->WriteULEB128(DW_FORM_DATA4);
1320 Scope* scope = desc_->info()->scope();
1321 int params = scope->num_parameters();
1322 int slots = scope->num_stack_slots();
1323 int context_slots = scope->ContextLocalCount();
1326 int locals = scope->StackLocalCount();
1327 int total_children =
1328 params + slots + context_slots + internal_slots + locals + 2;
1332 w->WriteULEB128(current_abbreviation++);
1333 w->WriteULEB128(DW_TAG_SUBPROGRAM);
1335 total_children != 0 ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1336 w->WriteULEB128(DW_AT_NAME);
1337 w->WriteULEB128(DW_FORM_STRING);
1338 w->WriteULEB128(DW_AT_LOW_PC);
1339 w->WriteULEB128(DW_FORM_ADDR);
1340 w->WriteULEB128(DW_AT_HIGH_PC);
1341 w->WriteULEB128(DW_FORM_ADDR);
1342 w->WriteULEB128(DW_AT_FRAME_BASE);
1343 w->WriteULEB128(DW_FORM_BLOCK4);
1347 w->WriteULEB128(current_abbreviation++);
1348 w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
1349 w->Write<uint8_t>(DW_CHILDREN_NO);
1350 w->WriteULEB128(DW_AT_BYTE_SIZE);
1351 w->WriteULEB128(DW_FORM_DATA1);
1352 w->WriteULEB128(DW_AT_NAME);
1353 w->WriteULEB128(DW_FORM_STRING);
1357 for (
int param = 0; param < params; ++param) {
1358 WriteVariableAbbreviation(w, current_abbreviation++,
true,
true);
1361 for (
int slot = 0; slot < slots; ++slot) {
1362 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1365 for (
int internal_slot = 0;
1366 internal_slot < internal_slots;
1368 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1371 for (
int context_slot = 0;
1372 context_slot < context_slots;
1374 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1377 for (
int local = 0; local < locals; ++local) {
1378 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1382 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1385 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1387 if (total_children != 0) {
1397 CodeDescription* desc_;
1401 class DebugLineSection :
public DebugSection {
1403 explicit DebugLineSection(CodeDescription* desc)
1405 : ELFSection(
".debug_line", TYPE_PROGBITS, 1),
1407 : MachOSection(
"__debug_line",
1410 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1415 enum DWARF2Opcodes {
1417 DW_LNS_ADVANCE_PC = 2,
1418 DW_LNS_ADVANCE_LINE = 3,
1419 DW_LNS_SET_FILE = 4,
1420 DW_LNS_SET_COLUMN = 5,
1421 DW_LNS_NEGATE_STMT = 6
1425 enum DWARF2ExtendedOpcode {
1426 DW_LNE_END_SEQUENCE = 1,
1427 DW_LNE_SET_ADDRESS = 2,
1428 DW_LNE_DEFINE_FILE = 3
1431 bool WriteBodyInternal(Writer* w) {
1433 Writer::Slot<uint32_t> total_length = w->CreateSlotHere<uint32_t>();
1434 uintptr_t start = w->position();
1437 const int8_t line_base = 1;
1438 const uint8_t line_range = 7;
1439 const int8_t max_line_incr = (line_base + line_range - 1);
1440 const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
1443 Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<uint32_t>();
1444 uintptr_t prologue_start = w->position();
1445 w->Write<uint8_t>(1);
1446 w->Write<uint8_t>(1);
1447 w->Write<int8_t>(line_base);
1448 w->Write<uint8_t>(line_range);
1449 w->Write<uint8_t>(opcode_base);
1450 w->Write<uint8_t>(0);
1451 w->Write<uint8_t>(1);
1452 w->Write<uint8_t>(1);
1453 w->Write<uint8_t>(1);
1454 w->Write<uint8_t>(1);
1455 w->Write<uint8_t>(0);
1456 w->Write<uint8_t>(0);
1457 w->WriteString(*desc_->GetFilename());
1461 w->Write<uint8_t>(0);
1462 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
1464 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS,
sizeof(intptr_t));
1465 w->Write<intptr_t>(desc_->CodeStart());
1466 w->Write<uint8_t>(DW_LNS_COPY);
1470 bool is_statement =
true;
1472 List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
1473 pc_info->Sort(&ComparePCInfo);
1475 int pc_info_length = pc_info->length();
1476 for (
int i = 0; i < pc_info_length; i++) {
1477 GDBJITLineInfo::PCInfo* info = &pc_info->at(i);
1482 intptr_t new_line = desc_->GetScriptLineNumber(info->pos_);
1483 if (new_line == line) {
1491 if ((i+1) == pc_info_length) {
1492 if (!is_statement) {
1493 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1495 }
else if (is_statement != info->is_statement_) {
1496 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1497 is_statement = !is_statement;
1503 uintptr_t pc_diff = info->pc_ -
pc;
1504 intptr_t line_diff = new_line - line;
1507 intptr_t special_opcode = (line_diff - line_base) +
1508 (line_range * pc_diff) + opcode_base;
1515 if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
1516 (line_diff <= max_line_incr) && (line_diff >= line_base)) {
1517 w->Write<uint8_t>(special_opcode);
1519 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1520 w->WriteSLEB128(pc_diff);
1521 w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
1522 w->WriteSLEB128(line_diff);
1523 w->Write<uint8_t>(DW_LNS_COPY);
1532 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1533 w->WriteSLEB128(desc_->CodeSize() -
pc);
1534 WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
1535 total_length.set(static_cast<uint32_t>(w->position() - start));
1540 void WriteExtendedOpcode(Writer* w,
1541 DWARF2ExtendedOpcode op,
1542 size_t operands_size) {
1543 w->Write<uint8_t>(0);
1544 w->WriteULEB128(operands_size + 1);
1545 w->Write<uint8_t>(op);
1548 static int ComparePCInfo(
const GDBJITLineInfo::PCInfo* a,
1549 const GDBJITLineInfo::PCInfo* b) {
1550 if (a->pc_ == b->pc_) {
1551 if (a->is_statement_ != b->is_statement_) {
1552 return b->is_statement_ ? +1 : -1;
1555 }
else if (a->pc_ > b->pc_) {
1562 CodeDescription* desc_;
1566 #ifdef V8_TARGET_ARCH_X64
1568 class UnwindInfoSection :
public DebugSection {
1570 explicit UnwindInfoSection(CodeDescription* desc);
1571 virtual bool WriteBodyInternal(Writer* w);
1573 int WriteCIE(Writer* w);
1574 void WriteFDE(Writer* w,
int);
1576 void WriteFDEStateOnEntry(Writer* w);
1577 void WriteFDEStateAfterRBPPush(Writer* w);
1578 void WriteFDEStateAfterRBPSet(Writer* w);
1579 void WriteFDEStateAfterRBPPop(Writer* w);
1581 void WriteLength(Writer* w,
1582 Writer::Slot<uint32_t>* length_slot,
1583 int initial_position);
1586 CodeDescription* desc_;
1589 enum CFIInstructions {
1590 DW_CFA_ADVANCE_LOC = 0x40,
1591 DW_CFA_OFFSET = 0x80,
1592 DW_CFA_RESTORE = 0xC0,
1594 DW_CFA_SET_LOC = 0x01,
1595 DW_CFA_ADVANCE_LOC1 = 0x02,
1596 DW_CFA_ADVANCE_LOC2 = 0x03,
1597 DW_CFA_ADVANCE_LOC4 = 0x04,
1598 DW_CFA_OFFSET_EXTENDED = 0x05,
1599 DW_CFA_RESTORE_EXTENDED = 0x06,
1600 DW_CFA_UNDEFINED = 0x07,
1601 DW_CFA_SAME_VALUE = 0x08,
1602 DW_CFA_REGISTER = 0x09,
1603 DW_CFA_REMEMBER_STATE = 0x0A,
1604 DW_CFA_RESTORE_STATE = 0x0B,
1605 DW_CFA_DEF_CFA = 0x0C,
1606 DW_CFA_DEF_CFA_REGISTER = 0x0D,
1607 DW_CFA_DEF_CFA_OFFSET = 0x0E,
1609 DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
1610 DW_CFA_EXPRESSION = 0x10,
1611 DW_CFA_OFFSET_EXTENDED_SF = 0x11,
1612 DW_CFA_DEF_CFA_SF = 0x12,
1613 DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
1614 DW_CFA_VAL_OFFSET = 0x14,
1615 DW_CFA_VAL_OFFSET_SF = 0x15,
1616 DW_CFA_VAL_EXPRESSION = 0x16
1620 enum RegisterMapping {
1630 CODE_ALIGN_FACTOR = 1,
1631 DATA_ALIGN_FACTOR = 1,
1632 RETURN_ADDRESS_REGISTER = AMD64_RA
1637 void UnwindInfoSection::WriteLength(Writer* w,
1638 Writer::Slot<uint32_t>* length_slot,
1639 int initial_position) {
1640 uint32_t align = (w->position() - initial_position) %
kPointerSize;
1643 for (uint32_t i = 0; i < (
kPointerSize - align); i++) {
1644 w->Write<uint8_t>(DW_CFA_NOP);
1649 length_slot->set(w->position() - initial_position);
1653 UnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
1655 : ELFSection(
".eh_frame", TYPE_X86_64_UNWIND, 1),
1657 : MachOSection(
"__eh_frame",
"__TEXT",
sizeof(uintptr_t),
1658 MachOSection::S_REGULAR),
1662 int UnwindInfoSection::WriteCIE(Writer* w) {
1663 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
1664 uint32_t cie_position = w->position();
1669 w->Write<uint32_t>(CIE_ID);
1670 w->Write<uint8_t>(CIE_VERSION);
1671 w->Write<uint8_t>(0);
1672 w->WriteSLEB128(CODE_ALIGN_FACTOR);
1673 w->WriteSLEB128(DATA_ALIGN_FACTOR);
1674 w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
1676 WriteLength(w, &cie_length_slot, cie_position);
1678 return cie_position;
1682 void UnwindInfoSection::WriteFDE(Writer* w,
int cie_position) {
1684 Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
1685 int fde_position = w->position();
1686 w->Write<
int32_t>(fde_position - cie_position + 4);
1688 w->Write<uintptr_t>(desc_->CodeStart());
1689 w->Write<uintptr_t>(desc_->CodeSize());
1691 WriteFDEStateOnEntry(w);
1692 WriteFDEStateAfterRBPPush(w);
1693 WriteFDEStateAfterRBPSet(w);
1694 WriteFDEStateAfterRBPPop(w);
1696 WriteLength(w, &fde_length_slot, fde_position);
1700 void UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
1706 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1707 w->WriteULEB128(AMD64_RSP);
1712 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1713 w->WriteULEB128(AMD64_RA);
1717 w->Write<uint8_t>(DW_CFA_SAME_VALUE);
1718 w->WriteULEB128(AMD64_RBP);
1721 w->Write<uint8_t>(DW_CFA_SET_LOC);
1723 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
1727 void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
1732 w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
1737 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1738 w->WriteULEB128(AMD64_RBP);
1742 w->Write<uint8_t>(DW_CFA_SET_LOC);
1744 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
1748 void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
1752 w->Write<uint8_t>(DW_CFA_DEF_CFA);
1753 w->WriteULEB128(AMD64_RBP);
1757 w->Write<uint8_t>(DW_CFA_SET_LOC);
1759 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
1763 void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
1768 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1769 w->WriteULEB128(AMD64_RSP);
1773 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1774 w->WriteULEB128(AMD64_RBP);
1778 w->Write<uint8_t>(DW_CFA_SET_LOC);
1779 w->Write<uint64_t>(desc_->CodeEnd());
1783 bool UnwindInfoSection::WriteBodyInternal(Writer* w) {
1784 uint32_t cie_position = WriteCIE(w);
1785 WriteFDE(w, cie_position);
1790 #endif // V8_TARGET_ARCH_X64
1792 static void CreateDWARFSections(CodeDescription* desc, DebugObject* obj) {
1793 Zone* zone = desc->info()->zone();
1794 if (desc->IsLineInfoAvailable()) {
1795 obj->AddSection(
new(zone) DebugInfoSection(desc), zone);
1796 obj->AddSection(
new(zone) DebugAbbrevSection(desc), zone);
1797 obj->AddSection(
new(zone) DebugLineSection(desc), zone);
1799 #ifdef V8_TARGET_ARCH_X64
1800 obj->AddSection(
new(zone) UnwindInfoSection(desc), zone);
1815 struct JITCodeEntry {
1816 JITCodeEntry* next_;
1817 JITCodeEntry* prev_;
1819 uint64_t symfile_size_;
1822 struct JITDescriptor {
1824 uint32_t action_flag_;
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(MaybeObject*
object) {
1844 fprintf(stdout,
"\n");
1850 static JITCodeEntry* CreateCodeEntry(
Address symfile_addr,
1851 uintptr_t symfile_size) {
1852 JITCodeEntry* entry =
static_cast<JITCodeEntry*
>(
1853 malloc(
sizeof(JITCodeEntry) + symfile_size));
1855 entry->symfile_addr_ =
reinterpret_cast<Address>(entry + 1);
1856 entry->symfile_size_ = symfile_size;
1857 memcpy(entry->symfile_addr_, symfile_addr, symfile_size);
1859 entry->prev_ = entry->next_ =
NULL;
1865 static void DestroyCodeEntry(JITCodeEntry* entry) {
1870 static void RegisterCodeEntry(JITCodeEntry* entry,
1871 bool dump_if_enabled,
1872 const char* name_hint) {
1873 #if defined(DEBUG) && !defined(WIN32)
1874 static int file_num = 0;
1875 if (FLAG_gdbjit_dump && dump_if_enabled) {
1876 static const int kMaxFileNameSize = 64;
1877 static const char* kElfFilePrefix =
"/tmp/elfdump";
1878 static const char* kObjFileExt =
".o";
1881 OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize),
1884 (name_hint !=
NULL) ? name_hint :
"",
1887 WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
1891 entry->next_ = __jit_debug_descriptor.first_entry_;
1892 if (entry->next_ !=
NULL) entry->next_->prev_ = entry;
1893 __jit_debug_descriptor.first_entry_ =
1894 __jit_debug_descriptor.relevant_entry_ = entry;
1896 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
1897 __jit_debug_register_code();
1901 static void UnregisterCodeEntry(JITCodeEntry* entry) {
1902 if (entry->prev_ !=
NULL) {
1903 entry->prev_->next_ = entry->next_;
1905 __jit_debug_descriptor.first_entry_ = entry->next_;
1908 if (entry->next_ !=
NULL) {
1909 entry->next_->prev_ = entry->prev_;
1912 __jit_debug_descriptor.relevant_entry_ = entry;
1913 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
1914 __jit_debug_register_code();
1918 static JITCodeEntry* CreateELFObject(CodeDescription* desc) {
1919 Zone* zone = desc->info()->zone();
1929 CreateDWARFSections(desc, &mach_o);
1931 mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
1936 int text_section_index = elf.AddSection(
1937 new(zone) FullHeaderELFSection(
1939 ELFSection::TYPE_NOBITS,
1944 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC),
1947 CreateSymbolsTable(desc, &elf, text_section_index);
1949 CreateDWARFSections(desc, &elf);
1954 return CreateCodeEntry(w.buffer(), w.position());
1958 static bool SameCodeObjects(
void* key1,
void* key2) {
1959 return key1 == key2;
1963 static HashMap* GetEntries() {
1965 if (entries ==
NULL) {
1966 entries =
new HashMap(&SameCodeObjects);
1972 static uint32_t HashForCodeObject(Code*
code) {
1973 static const uintptr_t kGoldenRatio = 2654435761u;
1974 uintptr_t hash =
reinterpret_cast<uintptr_t
>(code->address());
1979 static const intptr_t kLineInfoTag = 0x1;
1982 static bool IsLineInfoTagged(
void* ptr) {
1983 return 0 != (
reinterpret_cast<intptr_t
>(ptr) & kLineInfoTag);
1987 static void* TagLineInfo(GDBJITLineInfo* ptr) {
1988 return reinterpret_cast<void*
>(
1989 reinterpret_cast<intptr_t
>(ptr) | kLineInfoTag);
1993 static GDBJITLineInfo* UntagLineInfo(
void* ptr) {
1994 return reinterpret_cast<GDBJITLineInfo*
>(
1995 reinterpret_cast<intptr_t
>(ptr) & ~kLineInfoTag);
1999 void GDBJITInterface::AddCode(Handle<String> name,
2000 Handle<Script> script,
2002 CompilationInfo* info) {
2003 if (!FLAG_gdbjit)
return;
2008 if (!name.is_null()) {
2009 SmartArrayPointer<char> name_cstring = name->ToCString(
DISALLOW_NULLS);
2010 AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script, info);
2012 AddCode(
"", *code, GDBJITInterface::FUNCTION, *script, info);
2016 static void AddUnwindInfo(CodeDescription* desc) {
2017 #ifdef V8_TARGET_ARCH_X64
2018 if (desc->tag() == GDBJITInterface::FUNCTION) {
2022 static const int kFramePointerPushOffset = 1;
2023 static const int kFramePointerSetOffset = 4;
2024 static const int kFramePointerPopOffset = -3;
2026 uintptr_t frame_pointer_push_address =
2027 desc->CodeStart() + kFramePointerPushOffset;
2029 uintptr_t frame_pointer_set_address =
2030 desc->CodeStart() + kFramePointerSetOffset;
2032 uintptr_t frame_pointer_pop_address =
2033 desc->CodeEnd() + kFramePointerPopOffset;
2035 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2036 frame_pointer_push_address);
2037 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2038 frame_pointer_set_address);
2039 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2040 frame_pointer_pop_address);
2042 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2044 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2046 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2049 #endif // V8_TARGET_ARCH_X64
2056 void GDBJITInterface::AddCode(
const char* name,
2058 GDBJITInterface::CodeTag tag,
2060 CompilationInfo* info) {
2061 if (!FLAG_gdbjit)
return;
2063 ScopedLock lock(mutex.Pointer());
2064 AssertNoAllocation no_gc;
2066 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code),
true);
2067 if (e->value !=
NULL && !IsLineInfoTagged(e->value))
return;
2069 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value);
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 JITCodeEntry* entry = CreateELFObject(&code_desc);
2086 ASSERT(!IsLineInfoTagged(entry));
2091 const char* name_hint =
NULL;
2092 bool should_dump =
false;
2093 if (FLAG_gdbjit_dump) {
2094 if (strlen(FLAG_gdbjit_dump_filter) == 0) {
2097 }
else if (name !=
NULL) {
2098 name_hint = strstr(name, FLAG_gdbjit_dump_filter);
2099 should_dump = (name_hint !=
NULL);
2102 RegisterCodeEntry(entry, should_dump, name_hint);
2106 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
2109 if (!FLAG_gdbjit)
return;
2111 EmbeddedVector<char, 256> buffer;
2112 StringBuilder builder(buffer.start(), buffer.length());
2114 builder.AddString(Tag2String(tag));
2115 if ((name !=
NULL) && (*name !=
'\0')) {
2116 builder.AddString(
": ");
2117 builder.AddString(name);
2119 builder.AddFormatted(
": code object %p", static_cast<void*>(code));
2126 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
2129 if (!FLAG_gdbjit)
return;
2134 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, Code* code) {
2135 if (!FLAG_gdbjit)
return;
2137 AddCode(tag,
"", code);
2141 void GDBJITInterface::RemoveCode(Code* code) {
2142 if (!FLAG_gdbjit)
return;
2144 ScopedLock lock(mutex.Pointer());
2145 HashMap::Entry* e = GetEntries()->Lookup(code,
2146 HashForCodeObject(code),
2148 if (e ==
NULL)
return;
2150 if (IsLineInfoTagged(e->value)) {
2151 delete UntagLineInfo(e->value);
2153 JITCodeEntry* entry =
static_cast<JITCodeEntry*
>(e->value);
2154 UnregisterCodeEntry(entry);
2155 DestroyCodeEntry(entry);
2158 GetEntries()->Remove(code, HashForCodeObject(code));
2162 void GDBJITInterface::RegisterDetailedLineInfo(Code* code,
2163 GDBJITLineInfo* line_info) {
2164 ScopedLock lock(mutex.Pointer());
2165 ASSERT(!IsLineInfoTagged(line_info));
2166 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code),
true);
2168 e->value = TagLineInfo(line_info);
static const int kCallerFPOffset
static const int kLastParameterOffset
const char * ToCString(const v8::String::Utf8Value &value)
static String * cast(Object *obj)
#define ASSERT(condition)
LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak))
const intptr_t kCodeAlignment
StringInputBuffer *const buffer_
int WhichPowerOf2(uint32_t x)
int GetScriptLineNumberSafe(Handle< Script > script, int code_pos)
LazyDynamicInstance< Mutex, CreateMutexTrait, ThreadSafeInitOnceTrait >::type LazyMutex
#define T(name, string, precedence)
static int SNPrintF(Vector< char > str, const char *format,...)
int GetScriptLineNumber(Handle< Script > script, int code_pos)
static const int kContextOffset
static const int kFunctionOffset
const int kCodeAlignmentBits
static const int kCallerPCOffset
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if NULL
int WriteBytes(const char *filename, const byte *bytes, int size, bool verbose)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting 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 more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage including flags
static const int kLocal0Offset