OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 16 matching lines...) Expand all Loading... | |
27 | 27 |
28 #ifdef ENABLE_GDB_JIT_INTERFACE | 28 #ifdef ENABLE_GDB_JIT_INTERFACE |
29 #include "v8.h" | 29 #include "v8.h" |
30 #include "gdb-jit.h" | 30 #include "gdb-jit.h" |
31 | 31 |
32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
33 #include "compiler.h" | 33 #include "compiler.h" |
34 #include "global-handles.h" | 34 #include "global-handles.h" |
35 #include "messages.h" | 35 #include "messages.h" |
36 #include "natives.h" | 36 #include "natives.h" |
37 #include "scopeinfo.h" | |
38 | |
39 #ifdef __APPLE__ | |
40 #define __MACH_O | |
41 #define SECTION_BASE MachOSection | |
42 #define OBJ_FORMAT MachO | |
43 #else | |
44 #define __ELF | |
45 #define SECTION_BASE ELFSection | |
46 #define OBJ_FORMAT ELF | |
47 #endif | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
I don't think we are using macros for anything lik
zarko
2011/06/27 22:24:29
Done (though I have kept the __MACH_O/__ELF define
| |
37 | 48 |
38 namespace v8 { | 49 namespace v8 { |
39 namespace internal { | 50 namespace internal { |
40 | 51 |
41 class ELF; | 52 class ELF; |
53 class MachO; | |
42 | 54 |
43 class Writer BASE_EMBEDDED { | 55 class Writer BASE_EMBEDDED { |
44 public: | 56 public: |
45 explicit Writer(ELF* elf) | 57 explicit Writer(ELF* elf) |
46 : elf_(elf), | 58 : elf_(elf), |
59 mach_o_(0), | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Instead of duplicating code and members replace el
zarko
2011/06/27 22:24:29
Done.
| |
47 position_(0), | 60 position_(0), |
48 capacity_(1024), | 61 capacity_(1024), |
49 buffer_(reinterpret_cast<byte*>(malloc(capacity_))) { | 62 buffer_(reinterpret_cast<byte*>(malloc(capacity_))) { |
63 } | |
64 | |
65 explicit Writer(MachO* mach_o) | |
66 : elf_(0), | |
67 mach_o_(mach_o), | |
68 position_(0), | |
69 capacity_(1024), | |
70 buffer_(reinterpret_cast<byte*>(malloc(capacity_))) { | |
50 } | 71 } |
51 | 72 |
52 ~Writer() { | 73 ~Writer() { |
53 free(buffer_); | 74 free(buffer_); |
54 } | 75 } |
55 | 76 |
56 uintptr_t position() const { | 77 uintptr_t position() const { |
57 return position_; | 78 return position_; |
58 } | 79 } |
59 | 80 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 return SlotAt<T>(slot_position); | 126 return SlotAt<T>(slot_position); |
106 } | 127 } |
107 | 128 |
108 void Ensure(uintptr_t pos) { | 129 void Ensure(uintptr_t pos) { |
109 if (capacity_ < pos) { | 130 if (capacity_ < pos) { |
110 while (capacity_ < pos) capacity_ *= 2; | 131 while (capacity_ < pos) capacity_ *= 2; |
111 buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_)); | 132 buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_)); |
112 } | 133 } |
113 } | 134 } |
114 | 135 |
115 ELF* elf() { return elf_; } | 136 ELF* elf() { ASSERT(elf_ != 0); return elf_; } |
137 | |
138 MachO* mach_o() { ASSERT(mach_o_ != 0); return mach_o_; } | |
116 | 139 |
117 byte* buffer() { return buffer_; } | 140 byte* buffer() { return buffer_; } |
118 | 141 |
119 void Align(uintptr_t align) { | 142 void Align(uintptr_t align) { |
120 uintptr_t delta = position_ % align; | 143 uintptr_t delta = position_ % align; |
121 if (delta == 0) return; | 144 if (delta == 0) return; |
122 uintptr_t padding = align - delta; | 145 uintptr_t padding = align - delta; |
123 Ensure(position_ += padding); | 146 Ensure(position_ += padding); |
124 ASSERT((position_ % align) == 0); | 147 ASSERT((position_ % align) == 0); |
125 } | 148 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
159 private: | 182 private: |
160 template<typename T> friend class Slot; | 183 template<typename T> friend class Slot; |
161 | 184 |
162 template<typename T> | 185 template<typename T> |
163 T* RawSlotAt(uintptr_t offset) { | 186 T* RawSlotAt(uintptr_t offset) { |
164 ASSERT(offset < capacity_ && offset + sizeof(T) <= capacity_); | 187 ASSERT(offset < capacity_ && offset + sizeof(T) <= capacity_); |
165 return reinterpret_cast<T*>(&buffer_[offset]); | 188 return reinterpret_cast<T*>(&buffer_[offset]); |
166 } | 189 } |
167 | 190 |
168 ELF* elf_; | 191 ELF* elf_; |
192 MachO* mach_o_; | |
169 uintptr_t position_; | 193 uintptr_t position_; |
170 uintptr_t capacity_; | 194 uintptr_t capacity_; |
171 byte* buffer_; | 195 byte* buffer_; |
172 }; | 196 }; |
173 | 197 |
174 class StringTable; | 198 class StringTable; |
175 | 199 |
200 class MachOSection : public ZoneObject { | |
201 public: | |
202 struct Header { | |
203 char sectname[16]; | |
204 char segname[16]; | |
205 #if defined(V8_TARGET_ARCH_IA32) | |
206 uint32_t addr; | |
207 uint32_t size; | |
208 #else | |
209 uint64_t addr; | |
210 uint64_t size; | |
211 #endif | |
212 uint32_t offset; | |
213 uint32_t align; | |
214 uint32_t reloff; | |
215 uint32_t nreloc; | |
216 uint32_t flags; | |
217 uint32_t reserved1; | |
218 uint32_t reserved2; | |
219 }; | |
220 | |
221 enum Type { | |
222 S_REGULAR = 0x0u, | |
223 S_ATTR_COALESCED = 0xbu, | |
224 S_ATTR_SOME_INSTRUCTIONS = 0x400u, | |
225 S_ATTR_DEBUG = 0x02000000u, | |
226 S_ATTR_PURE_INSTRUCTIONS = 0x80000000u | |
227 }; | |
228 | |
229 MachOSection(const char* name, | |
230 const char* segment, | |
231 uintptr_t align, | |
232 uint32_t flags) | |
233 : name_(name), | |
234 segment_(segment), | |
235 align_(align), | |
236 flags_(flags) { | |
237 ASSERT(IsPowerOf2(align)); | |
238 if (align_ != 0) { | |
239 align_ = WhichPowerOf2(align_); | |
240 } | |
241 } | |
242 | |
243 virtual ~MachOSection() { } | |
244 | |
245 virtual void PopulateHeader(Writer::Slot<Header> header) { | |
246 header->addr = 0; | |
247 header->size = 0; | |
248 header->offset = 0; | |
249 header->align = align_; | |
250 header->reloff = 0; | |
251 header->nreloc = 0; | |
252 header->flags = flags_; | |
253 header->reserved1 = 0; | |
254 header->reserved2 = 0; | |
255 memset(header->sectname, 0, 16); | |
256 memset(header->segname, 0, 16); | |
257 ASSERT(strlen(name_) < 16); | |
258 ASSERT(strlen(segment_) < 16); | |
259 strcpy(header->sectname, name_); | |
260 strcpy(header->segname, segment_); | |
261 } | |
262 | |
263 virtual void WriteBody(Writer::Slot<Header> header, Writer* writer) { | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Seems to be shared between ELFSection and MachOSec
zarko
2011/06/27 22:24:29
Done.
| |
264 uintptr_t start = writer->position(); | |
265 if (WriteBody(writer)) { | |
266 uintptr_t end = writer->position(); | |
267 header->offset = start; | |
268 header->addr = 0; | |
269 header->size = end - start; | |
270 } | |
271 } | |
272 | |
273 virtual bool WriteBody(Writer* writer) { | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Ditto.
zarko
2011/06/27 22:24:29
Done.
| |
274 return false; | |
275 } | |
276 | |
277 private: | |
278 const char* name_; | |
279 const char* segment_; | |
280 uintptr_t align_; | |
281 uint32_t flags_; | |
282 }; | |
283 | |
284 | |
176 class ELFSection : public ZoneObject { | 285 class ELFSection : public ZoneObject { |
177 public: | 286 public: |
178 struct Header { | 287 struct Header { |
179 uint32_t name; | 288 uint32_t name; |
180 uint32_t type; | 289 uint32_t type; |
181 uintptr_t flags; | 290 uintptr_t flags; |
182 uintptr_t address; | 291 uintptr_t address; |
183 uintptr_t offset; | 292 uintptr_t offset; |
184 uintptr_t size; | 293 uintptr_t size; |
185 uint32_t link; | 294 uint32_t link; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 virtual void PopulateHeader(Writer::Slot<Header> header) { | 354 virtual void PopulateHeader(Writer::Slot<Header> header) { |
246 header->flags = 0; | 355 header->flags = 0; |
247 header->address = 0; | 356 header->address = 0; |
248 header->offset = 0; | 357 header->offset = 0; |
249 header->size = 0; | 358 header->size = 0; |
250 header->link = 0; | 359 header->link = 0; |
251 header->info = 0; | 360 header->info = 0; |
252 header->entry_size = 0; | 361 header->entry_size = 0; |
253 } | 362 } |
254 | 363 |
255 | |
256 private: | 364 private: |
257 const char* name_; | 365 const char* name_; |
258 Type type_; | 366 Type type_; |
259 uintptr_t align_; | 367 uintptr_t align_; |
260 uint16_t index_; | 368 uint16_t index_; |
261 }; | 369 }; |
262 | 370 |
263 | 371 |
372 class MachOTextSection : public MachOSection { | |
373 public: | |
374 MachOTextSection(uintptr_t align, | |
375 uintptr_t addr, | |
376 uintptr_t size) | |
377 : MachOSection("__text", | |
378 "__TEXT", | |
379 align, | |
380 MachOSection::S_REGULAR | | |
381 MachOSection::S_ATTR_SOME_INSTRUCTIONS | | |
382 MachOSection::S_ATTR_PURE_INSTRUCTIONS), | |
383 addr_(addr), | |
384 size_(size) { } | |
385 | |
386 protected: | |
387 virtual void PopulateHeader(Writer::Slot<Header> header) { | |
388 MachOSection::PopulateHeader(header); | |
389 header->addr = addr_; | |
390 header->size = size_; | |
391 } | |
392 | |
393 private: | |
394 uintptr_t addr_; | |
395 uintptr_t size_; | |
396 }; | |
397 | |
398 | |
264 class FullHeaderELFSection : public ELFSection { | 399 class FullHeaderELFSection : public ELFSection { |
265 public: | 400 public: |
266 FullHeaderELFSection(const char* name, | 401 FullHeaderELFSection(const char* name, |
267 Type type, | 402 Type type, |
268 uintptr_t align, | 403 uintptr_t align, |
269 uintptr_t addr, | 404 uintptr_t addr, |
270 uintptr_t offset, | 405 uintptr_t offset, |
271 uintptr_t size, | 406 uintptr_t size, |
272 uintptr_t flags) | 407 uintptr_t flags) |
273 : ELFSection(name, type, align), | 408 : ELFSection(name, type, align), |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
344 | 479 |
345 void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header, | 480 void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header, |
346 StringTable* strtab) { | 481 StringTable* strtab) { |
347 header->name = strtab->Add(name_); | 482 header->name = strtab->Add(name_); |
348 header->type = type_; | 483 header->type = type_; |
349 header->alignment = align_; | 484 header->alignment = align_; |
350 PopulateHeader(header); | 485 PopulateHeader(header); |
351 } | 486 } |
352 | 487 |
353 | 488 |
489 class MachO BASE_EMBEDDED { | |
490 public: | |
491 MachO() : sections_(6) { } | |
492 | |
493 uint32_t AddSection(MachOSection* section) { | |
494 sections_.Add(section); | |
495 return sections_.length() - 1; | |
496 } | |
497 | |
498 void Write(Writer* w, uintptr_t code_start, uintptr_t code_size); | |
499 | |
500 private: | |
501 struct MachOHeader { | |
502 uint32_t magic; | |
503 uint32_t cputype; | |
504 uint32_t cpusubtype; | |
505 uint32_t filetype; | |
506 uint32_t ncmds; | |
507 uint32_t sizeofcmds; | |
508 uint32_t flags; | |
509 #if defined(V8_TARGET_ARCH_X64) | |
510 uint32_t reserved; | |
511 #endif | |
512 }; | |
513 | |
514 struct MachOSegmentCommand { | |
515 uint32_t cmd; | |
516 uint32_t cmdsize; | |
517 char segname[16]; | |
518 #if defined(V8_TARGET_ARCH_IA32) | |
519 uint32_t vmaddr; | |
520 uint32_t vmsize; | |
521 uint32_t fileoff; | |
522 uint32_t filesize; | |
523 #else | |
524 uint64_t vmaddr; | |
525 uint64_t vmsize; | |
526 uint64_t fileoff; | |
527 uint64_t filesize; | |
528 #endif | |
529 uint32_t maxprot; | |
530 uint32_t initprot; | |
531 uint32_t nsects; | |
532 uint32_t flags; | |
533 }; | |
534 | |
535 enum MachOLoadCommandCmd { | |
536 LC_SEGMENT_32 = 0x00000001u, | |
537 LC_SEGMENT_64 = 0x00000019u | |
538 }; | |
539 | |
540 ZoneList<MachOSection*> sections_; | |
541 }; | |
542 | |
543 | |
544 void MachO::Write(Writer* w, | |
545 uintptr_t code_start, | |
546 uintptr_t code_size) { | |
547 ASSERT(w->position() == 0); | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Can you split this method into several like it is
zarko
2011/06/27 22:24:29
Done.
| |
548 Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>(); | |
549 #if defined(V8_TARGET_ARCH_IA32) | |
550 header->magic = 0xFEEDFACEu; | |
551 header->cputype = 7; // i386 | |
552 header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL | |
553 #elif defined(V8_TARGET_ARCH_X64) | |
554 header->magic = 0xFEEDFACFu; | |
555 header->cputype = 7 | 0x01000000; // i386 | 64-bit ABI | |
556 header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL | |
557 header->reserved = 0; | |
558 #else | |
559 #error Unsupported target architecture. | |
560 #endif | |
561 header->filetype = 0x1; // MH_OBJECT | |
562 header->ncmds = 1; | |
563 header->sizeofcmds = 0; | |
564 header->flags = 0; | |
565 uintptr_t load_command_start = w->position(); | |
566 Writer::Slot<MachOSegmentCommand> cmd = | |
567 w->CreateSlotHere<MachOSegmentCommand>(); | |
568 #if defined(V8_TARGET_ARCH_IA32) | |
569 cmd->cmd = LC_SEGMENT_32; | |
570 #else | |
571 cmd->cmd = LC_SEGMENT_64; | |
572 #endif | |
573 cmd->vmaddr = code_start; | |
574 cmd->vmsize = code_size; | |
575 cmd->fileoff = 0; | |
576 cmd->filesize = 0; | |
577 cmd->maxprot = 7; | |
578 cmd->initprot = 7; | |
579 cmd->flags = 0; | |
580 cmd->nsects = sections_.length(); | |
581 memset(cmd->segname, 0, 16); | |
582 cmd->cmdsize = sizeof(MachOSegmentCommand) + sizeof(MachOSection::Header) * | |
583 cmd->nsects; | |
584 Writer::Slot<MachOSection::Header> headers = | |
585 w->CreateSlotsHere<MachOSection::Header>(sections_.length()); | |
586 cmd->fileoff = w->position(); | |
587 header->sizeofcmds = w->position() - load_command_start; | |
588 for (int section = 0; section < sections_.length(); ++section) { | |
589 sections_[section]->PopulateHeader(headers.at(section)); | |
590 sections_[section]->WriteBody(headers.at(section), w); | |
591 } | |
592 cmd->filesize = w->position() - (uintptr_t)cmd->fileoff; | |
593 } | |
594 | |
595 | |
354 class ELF BASE_EMBEDDED { | 596 class ELF BASE_EMBEDDED { |
355 public: | 597 public: |
356 ELF() : sections_(6) { | 598 ELF() : sections_(6) { |
357 sections_.Add(new ELFSection("", ELFSection::TYPE_NULL, 0)); | 599 sections_.Add(new ELFSection("", ELFSection::TYPE_NULL, 0)); |
358 sections_.Add(new StringTable(".shstrtab")); | 600 sections_.Add(new StringTable(".shstrtab")); |
359 } | 601 } |
360 | 602 |
361 void Write(Writer* w) { | 603 void Write(Writer* w) { |
362 WriteHeader(w); | 604 WriteHeader(w); |
363 WriteSectionTable(w); | 605 WriteSectionTable(w); |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
650 POST_RBP_SET, | 892 POST_RBP_SET, |
651 POST_RBP_POP, | 893 POST_RBP_POP, |
652 STACK_STATE_MAX | 894 STACK_STATE_MAX |
653 }; | 895 }; |
654 #endif | 896 #endif |
655 | 897 |
656 CodeDescription(const char* name, | 898 CodeDescription(const char* name, |
657 Code* code, | 899 Code* code, |
658 Handle<Script> script, | 900 Handle<Script> script, |
659 GDBJITLineInfo* lineinfo, | 901 GDBJITLineInfo* lineinfo, |
660 GDBJITInterface::CodeTag tag) | 902 GDBJITInterface::CodeTag tag, |
903 CompilationInfo* info) | |
661 : name_(name), | 904 : name_(name), |
662 code_(code), | 905 code_(code), |
663 script_(script), | 906 script_(script), |
664 lineinfo_(lineinfo), | 907 lineinfo_(lineinfo), |
665 tag_(tag) { | 908 tag_(tag), |
909 info_(info) { | |
666 } | 910 } |
667 | 911 |
668 const char* name() const { | 912 const char* name() const { |
669 return name_; | 913 return name_; |
670 } | 914 } |
671 | 915 |
672 GDBJITLineInfo* lineinfo() const { | 916 GDBJITLineInfo* lineinfo() const { |
673 return lineinfo_; | 917 return lineinfo_; |
674 } | 918 } |
675 | 919 |
676 GDBJITInterface::CodeTag tag() const { | 920 GDBJITInterface::CodeTag tag() const { |
677 return tag_; | 921 return tag_; |
678 } | 922 } |
679 | 923 |
924 CompilationInfo* info() const { | |
925 return info_; | |
926 } | |
927 | |
928 bool IsInfoAvailable() const { | |
929 return info_ != NULL; | |
930 } | |
931 | |
680 uintptr_t CodeStart() const { | 932 uintptr_t CodeStart() const { |
681 return reinterpret_cast<uintptr_t>(code_->instruction_start()); | 933 return reinterpret_cast<uintptr_t>(code_->instruction_start()); |
682 } | 934 } |
683 | 935 |
684 uintptr_t CodeEnd() const { | 936 uintptr_t CodeEnd() const { |
685 return reinterpret_cast<uintptr_t>(code_->instruction_end()); | 937 return reinterpret_cast<uintptr_t>(code_->instruction_end()); |
686 } | 938 } |
687 | 939 |
688 uintptr_t CodeSize() const { | 940 uintptr_t CodeSize() const { |
689 return CodeEnd() - CodeStart(); | 941 return CodeEnd() - CodeStart(); |
(...skipping 27 matching lines...) Expand all Loading... | |
717 return GetScriptLineNumberSafe(script_, pos) + 1; | 969 return GetScriptLineNumberSafe(script_, pos) + 1; |
718 } | 970 } |
719 | 971 |
720 | 972 |
721 private: | 973 private: |
722 const char* name_; | 974 const char* name_; |
723 Code* code_; | 975 Code* code_; |
724 Handle<Script> script_; | 976 Handle<Script> script_; |
725 GDBJITLineInfo* lineinfo_; | 977 GDBJITLineInfo* lineinfo_; |
726 GDBJITInterface::CodeTag tag_; | 978 GDBJITInterface::CodeTag tag_; |
979 CompilationInfo* info_; | |
727 #ifdef V8_TARGET_ARCH_X64 | 980 #ifdef V8_TARGET_ARCH_X64 |
728 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX]; | 981 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX]; |
729 #endif | 982 #endif |
730 }; | 983 }; |
731 | 984 |
732 | 985 #ifdef __ELF |
733 static void CreateSymbolsTable(CodeDescription* desc, | 986 static void CreateSymbolsTable(CodeDescription* desc, |
734 ELF* elf, | 987 ELF* elf, |
735 int text_section_index) { | 988 int text_section_index) { |
736 ELFSymbolTable* symtab = new ELFSymbolTable(".symtab"); | 989 ELFSymbolTable* symtab = new ELFSymbolTable(".symtab"); |
737 StringTable* strtab = new StringTable(".strtab"); | 990 StringTable* strtab = new StringTable(".strtab"); |
738 | 991 |
739 // Symbol table should be followed by the linked string table. | 992 // Symbol table should be followed by the linked string table. |
740 elf->AddSection(symtab); | 993 elf->AddSection(symtab); |
741 elf->AddSection(strtab); | 994 elf->AddSection(strtab); |
742 | 995 |
743 symtab->Add(ELFSymbol("V8 Code", | 996 symtab->Add(ELFSymbol("V8 Code", |
744 0, | 997 0, |
745 0, | 998 0, |
746 ELFSymbol::BIND_LOCAL, | 999 ELFSymbol::BIND_LOCAL, |
747 ELFSymbol::TYPE_FILE, | 1000 ELFSymbol::TYPE_FILE, |
748 ELFSection::INDEX_ABSOLUTE)); | 1001 ELFSection::INDEX_ABSOLUTE)); |
749 | 1002 |
750 symtab->Add(ELFSymbol(desc->name(), | 1003 symtab->Add(ELFSymbol(desc->name(), |
751 0, | 1004 0, |
752 desc->CodeSize(), | 1005 desc->CodeSize(), |
753 ELFSymbol::BIND_GLOBAL, | 1006 ELFSymbol::BIND_GLOBAL, |
754 ELFSymbol::TYPE_FUNC, | 1007 ELFSymbol::TYPE_FUNC, |
755 text_section_index)); | 1008 text_section_index)); |
756 } | 1009 } |
1010 #endif | |
757 | 1011 |
758 | 1012 |
759 class DebugInfoSection : public ELFSection { | 1013 class DebugInfoSection : public SECTION_BASE { |
760 public: | 1014 public: |
761 explicit DebugInfoSection(CodeDescription* desc) | 1015 explicit DebugInfoSection(CodeDescription* desc) |
762 : ELFSection(".debug_info", TYPE_PROGBITS, 1), desc_(desc) { } | 1016 #ifdef __ELF |
1017 : ELFSection(".debug_info", TYPE_PROGBITS, 1), | |
1018 #else | |
1019 : MachOSection("__debug_info", "__DWARF", 1, | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
one argument per line.
zarko
2011/06/27 22:24:29
Done.
| |
1020 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG), | |
1021 #endif | |
1022 desc_(desc) { } | |
1023 | |
1024 // DWARF2 standard | |
1025 enum DWARF2LocationOp { | |
1026 DW_OP_reg0 = 0x50, | |
1027 DW_OP_reg1 = 0x51, | |
1028 DW_OP_reg2 = 0x52, | |
1029 DW_OP_reg3 = 0x53, | |
1030 DW_OP_reg4 = 0x54, | |
1031 DW_OP_reg5 = 0x55, | |
1032 DW_OP_reg6 = 0x56, | |
1033 DW_OP_reg7 = 0x57, | |
1034 DW_OP_fbreg = 0x91 // 1 param: SLEB128 offset | |
1035 }; | |
1036 | |
1037 enum DWARF2Encoding { | |
1038 DW_ATE_ADDRESS = 0x1, | |
1039 DW_ATE_SIGNED = 0x5 | |
1040 }; | |
763 | 1041 |
764 bool WriteBody(Writer* w) { | 1042 bool WriteBody(Writer* w) { |
1043 uintptr_t cu_start = w->position(); | |
765 Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>(); | 1044 Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>(); |
766 uintptr_t start = w->position(); | 1045 uintptr_t start = w->position(); |
767 w->Write<uint16_t>(2); // DWARF version. | 1046 w->Write<uint16_t>(2); // DWARF version. |
768 w->Write<uint32_t>(0); // Abbreviation table offset. | 1047 w->Write<uint32_t>(0); // Abbreviation table offset. |
769 w->Write<uint8_t>(sizeof(intptr_t)); | 1048 w->Write<uint8_t>(sizeof(intptr_t)); |
770 | 1049 |
771 w->WriteULEB128(1); // Abbreviation code. | 1050 w->WriteULEB128(1); // Abbreviation code. |
772 w->WriteString(*desc_->GetFilename()); | 1051 w->WriteString(*desc_->GetFilename()); |
773 w->Write<intptr_t>(desc_->CodeStart()); | 1052 w->Write<intptr_t>(desc_->CodeStart()); |
774 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); | 1053 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); |
775 w->Write<uint32_t>(0); | 1054 w->Write<uint32_t>(0); |
1055 | |
1056 uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start); | |
1057 w->WriteULEB128(3); | |
1058 w->Write<uint8_t>(kPointerSize); | |
1059 w->WriteString("v8value"); | |
1060 | |
1061 if (desc_->IsInfoAvailable()) { | |
1062 CompilationInfo* info = desc_->info(); | |
1063 ScopeInfo<FreeStoreAllocationPolicy> scope_info(info->scope()); | |
1064 w->WriteULEB128(2); | |
1065 w->WriteString(desc_->name()); | |
1066 w->Write<intptr_t>(desc_->CodeStart()); | |
1067 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); | |
1068 Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>(); | |
1069 uintptr_t fb_block_start = w->position(); | |
1070 #if defined(V8_TARGET_ARCH_IA32) | |
1071 w->Write<uint8_t>(DW_OP_reg5); // The frame pointer's here on ia32 | |
1072 #elif defined(V8_TARGET_ARCH_X64) | |
1073 w->Write<uint8_t>(DW_OP_reg6); // and here on x64. | |
1074 #else | |
1075 #error Unsupported target architecture. | |
1076 #endif | |
1077 fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start)); | |
1078 | |
1079 int params = scope_info.number_of_parameters(); | |
1080 int slots = scope_info.number_of_stack_slots(); | |
1081 int context_slots = scope_info.number_of_context_slots(); | |
1082 // The real slot ID is internal_slots + context_slot_id. | |
1083 int internal_slots = Context::MIN_CONTEXT_SLOTS; | |
1084 int locals = scope_info.NumberOfLocals(); | |
1085 int current_abbreviation = 4; | |
1086 | |
1087 for (int param = 0; param < params; ++param) { | |
1088 w->WriteULEB128(current_abbreviation++); | |
1089 w->WriteString( | |
1090 *scope_info.parameter_name(param)->ToCString(DISALLOW_NULLS)); | |
1091 w->Write<uint32_t>(ty_offset); | |
1092 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); | |
1093 uintptr_t block_start = w->position(); | |
1094 w->Write<uint8_t>(DW_OP_fbreg); | |
1095 w->WriteSLEB128( | |
1096 JavaScriptFrameConstants::kLastParameterOffset + | |
1097 kPointerSize * (params - param - 1)); | |
1098 block_size.set(static_cast<uint32_t>(w->position() - block_start)); | |
1099 } | |
1100 | |
1101 EmbeddedVector<char, 256> buffer; | |
1102 StringBuilder builder(buffer.start(), buffer.length()); | |
1103 | |
1104 for (int slot = 0; slot < slots; ++slot) { | |
1105 w->WriteULEB128(current_abbreviation++); | |
1106 builder.Reset(); | |
1107 builder.AddFormatted("slot%d", slot); | |
1108 w->WriteString(builder.Finalize()); | |
1109 } | |
1110 | |
1111 // See contexts.h for more information. | |
1112 ASSERT(Context::MIN_CONTEXT_SLOTS == 5); | |
1113 ASSERT(Context::CLOSURE_INDEX == 0); | |
1114 ASSERT(Context::FCONTEXT_INDEX == 1); | |
1115 ASSERT(Context::PREVIOUS_INDEX == 2); | |
1116 ASSERT(Context::EXTENSION_INDEX == 3); | |
1117 ASSERT(Context::GLOBAL_INDEX == 4); | |
1118 w->WriteULEB128(current_abbreviation++); | |
1119 w->WriteString(".closure"); | |
1120 w->WriteULEB128(current_abbreviation++); | |
1121 w->WriteString(".fcontext"); | |
1122 w->WriteULEB128(current_abbreviation++); | |
1123 w->WriteString(".previous"); | |
1124 w->WriteULEB128(current_abbreviation++); | |
1125 w->WriteString(".extension"); | |
1126 w->WriteULEB128(current_abbreviation++); | |
1127 w->WriteString(".global"); | |
1128 | |
1129 for (int context_slot = 0; context_slot < context_slots; | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
for(x;
y;
z)
zarko
2011/06/27 22:24:29
Done.
| |
1130 ++context_slot) { | |
1131 w->WriteULEB128(current_abbreviation++); | |
1132 builder.Reset(); | |
1133 builder.AddFormatted("context_slot%d", context_slot + internal_slots); | |
1134 w->WriteString(builder.Finalize()); | |
1135 } | |
1136 | |
1137 for (int local = 0; local < locals; ++local) { | |
1138 w->WriteULEB128(current_abbreviation++); | |
1139 w->WriteString( | |
1140 *scope_info.LocalName(local)->ToCString(DISALLOW_NULLS)); | |
1141 w->Write<uint32_t>(ty_offset); | |
1142 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); | |
1143 uintptr_t block_start = w->position(); | |
1144 w->Write<uint8_t>(DW_OP_fbreg); | |
1145 w->WriteSLEB128( | |
1146 JavaScriptFrameConstants::kLocal0Offset - | |
1147 kPointerSize * local); | |
1148 block_size.set(static_cast<uint32_t>(w->position() - block_start)); | |
1149 } | |
1150 | |
1151 { | |
1152 w->WriteULEB128(current_abbreviation++); | |
1153 w->WriteString("__function"); | |
1154 w->Write<uint32_t>(ty_offset); | |
1155 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); | |
1156 uintptr_t block_start = w->position(); | |
1157 w->Write<uint8_t>(DW_OP_fbreg); | |
1158 w->WriteSLEB128(JavaScriptFrameConstants::kFunctionOffset); | |
1159 block_size.set(static_cast<uint32_t>(w->position() - block_start)); | |
1160 } | |
1161 | |
1162 { | |
1163 w->WriteULEB128(current_abbreviation++); | |
1164 w->WriteString("__context"); | |
1165 w->Write<uint32_t>(ty_offset); | |
1166 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); | |
1167 uintptr_t block_start = w->position(); | |
1168 w->Write<uint8_t>(DW_OP_fbreg); | |
1169 w->WriteSLEB128(StandardFrameConstants::kContextOffset); | |
1170 block_size.set(static_cast<uint32_t>(w->position() - block_start)); | |
1171 } | |
1172 } | |
1173 | |
776 size.set(static_cast<uint32_t>(w->position() - start)); | 1174 size.set(static_cast<uint32_t>(w->position() - start)); |
777 return true; | 1175 return true; |
778 } | 1176 } |
779 | 1177 |
780 private: | 1178 private: |
781 CodeDescription* desc_; | 1179 CodeDescription* desc_; |
782 }; | 1180 }; |
783 | 1181 |
784 | 1182 |
785 class DebugAbbrevSection : public ELFSection { | 1183 class DebugAbbrevSection : public SECTION_BASE { |
786 public: | 1184 public: |
787 DebugAbbrevSection() : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1) { } | 1185 explicit DebugAbbrevSection(CodeDescription* desc) |
1186 #ifdef __ELF | |
1187 : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1), | |
1188 #else | |
1189 : MachOSection("__debug_abbrev", "__DWARF", 1, | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Argument per line
zarko
2011/06/27 22:24:29
Done.
| |
1190 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG), | |
1191 #endif | |
1192 desc_(desc) { } | |
788 | 1193 |
789 // DWARF2 standard, figure 14. | 1194 // DWARF2 standard, figure 14. |
790 enum DWARF2Tags { | 1195 enum DWARF2Tags { |
791 DW_TAG_COMPILE_UNIT = 0x11 | 1196 DW_TAG_FORMAL_PARAMETER = 0x05, |
1197 DW_TAG_POINTER_TYPE = 0xf, | |
1198 DW_TAG_COMPILE_UNIT = 0x11, | |
1199 DW_TAG_STRUCTURE_TYPE = 0x13, | |
1200 DW_TAG_BASE_TYPE = 0x24, | |
1201 DW_TAG_SUBPROGRAM = 0x2e, | |
1202 DW_TAG_VARIABLE = 0x34 | |
792 }; | 1203 }; |
793 | 1204 |
794 // DWARF2 standard, figure 16. | 1205 // DWARF2 standard, figure 16. |
795 enum DWARF2ChildrenDetermination { | 1206 enum DWARF2ChildrenDetermination { |
796 DW_CHILDREN_NO = 0, | 1207 DW_CHILDREN_NO = 0, |
797 DW_CHILDREN_YES = 1 | 1208 DW_CHILDREN_YES = 1 |
798 }; | 1209 }; |
799 | 1210 |
800 // DWARF standard, figure 17. | 1211 // DWARF standard, figure 17. |
801 enum DWARF2Attribute { | 1212 enum DWARF2Attribute { |
1213 DW_AT_LOCATION = 0x2, | |
802 DW_AT_NAME = 0x3, | 1214 DW_AT_NAME = 0x3, |
1215 DW_AT_BYTE_SIZE = 0xb, | |
803 DW_AT_STMT_LIST = 0x10, | 1216 DW_AT_STMT_LIST = 0x10, |
804 DW_AT_LOW_PC = 0x11, | 1217 DW_AT_LOW_PC = 0x11, |
805 DW_AT_HIGH_PC = 0x12 | 1218 DW_AT_HIGH_PC = 0x12, |
1219 DW_AT_ENCODING = 0x3e, | |
1220 DW_AT_FRAME_BASE = 0x40, | |
1221 DW_AT_TYPE = 0x49 | |
806 }; | 1222 }; |
807 | 1223 |
808 // DWARF2 standard, figure 19. | 1224 // DWARF2 standard, figure 19. |
809 enum DWARF2AttributeForm { | 1225 enum DWARF2AttributeForm { |
810 DW_FORM_ADDR = 0x1, | 1226 DW_FORM_ADDR = 0x1, |
1227 DW_FORM_BLOCK4 = 0x4, | |
811 DW_FORM_STRING = 0x8, | 1228 DW_FORM_STRING = 0x8, |
812 DW_FORM_DATA4 = 0x6 | 1229 DW_FORM_DATA4 = 0x6, |
1230 DW_FORM_BLOCK = 0x9, | |
1231 DW_FORM_DATA1 = 0xb, | |
1232 DW_FORM_FLAG = 0xc, | |
1233 DW_FORM_REF4 = 0x13 | |
813 }; | 1234 }; |
814 | 1235 |
815 bool WriteBody(Writer* w) { | 1236 bool WriteBody(Writer* w) { |
1237 bool extra_info = desc_->IsInfoAvailable(); | |
1238 ASSERT(desc_->IsLineInfoAvailable()); | |
816 w->WriteULEB128(1); | 1239 w->WriteULEB128(1); |
817 w->WriteULEB128(DW_TAG_COMPILE_UNIT); | 1240 w->WriteULEB128(DW_TAG_COMPILE_UNIT); |
818 w->Write<uint8_t>(DW_CHILDREN_NO); | 1241 w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO); |
819 w->WriteULEB128(DW_AT_NAME); | 1242 w->WriteULEB128(DW_AT_NAME); |
820 w->WriteULEB128(DW_FORM_STRING); | 1243 w->WriteULEB128(DW_FORM_STRING); |
821 w->WriteULEB128(DW_AT_LOW_PC); | 1244 w->WriteULEB128(DW_AT_LOW_PC); |
822 w->WriteULEB128(DW_FORM_ADDR); | 1245 w->WriteULEB128(DW_FORM_ADDR); |
823 w->WriteULEB128(DW_AT_HIGH_PC); | 1246 w->WriteULEB128(DW_AT_HIGH_PC); |
824 w->WriteULEB128(DW_FORM_ADDR); | 1247 w->WriteULEB128(DW_FORM_ADDR); |
825 w->WriteULEB128(DW_AT_STMT_LIST); | 1248 w->WriteULEB128(DW_AT_STMT_LIST); |
826 w->WriteULEB128(DW_FORM_DATA4); | 1249 w->WriteULEB128(DW_FORM_DATA4); |
827 w->WriteULEB128(0); | 1250 w->WriteULEB128(0); |
828 w->WriteULEB128(0); | 1251 w->WriteULEB128(0); |
829 w->WriteULEB128(0); | 1252 |
1253 if (extra_info) { | |
1254 CompilationInfo* info = desc_->info(); | |
1255 ScopeInfo<FreeStoreAllocationPolicy> scope_info(info->scope()); | |
1256 int params = scope_info.number_of_parameters(); | |
1257 int slots = scope_info.number_of_stack_slots(); | |
1258 int context_slots = scope_info.number_of_context_slots(); | |
1259 // The real slot ID is internal_slots + context_slot_id. | |
1260 int internal_slots = Context::MIN_CONTEXT_SLOTS; | |
1261 int locals = scope_info.NumberOfLocals(); | |
1262 int total_children = | |
1263 params + slots + context_slots + internal_slots + locals + 2; | |
1264 | |
1265 // The extra duplication below seems to be necessary to keep | |
1266 // gdb from getting upset on OSX. | |
1267 | |
1268 w->WriteULEB128(2); // Abbreviation code. | |
1269 w->WriteULEB128(DW_TAG_SUBPROGRAM); | |
1270 w->Write<uint8_t>( | |
1271 total_children != 0 ? DW_CHILDREN_YES : DW_CHILDREN_NO); | |
1272 w->WriteULEB128(DW_AT_NAME); | |
1273 w->WriteULEB128(DW_FORM_STRING); | |
1274 w->WriteULEB128(DW_AT_LOW_PC); | |
1275 w->WriteULEB128(DW_FORM_ADDR); | |
1276 w->WriteULEB128(DW_AT_HIGH_PC); | |
1277 w->WriteULEB128(DW_FORM_ADDR); | |
1278 w->WriteULEB128(DW_AT_FRAME_BASE); | |
1279 w->WriteULEB128(DW_FORM_BLOCK4); | |
1280 w->WriteULEB128(0); | |
1281 w->WriteULEB128(0); | |
1282 | |
1283 w->WriteULEB128(3); | |
1284 w->WriteULEB128(DW_TAG_STRUCTURE_TYPE); | |
1285 w->Write<uint8_t>(DW_CHILDREN_NO); | |
1286 w->WriteULEB128(DW_AT_BYTE_SIZE); | |
1287 w->WriteULEB128(DW_FORM_DATA1); | |
1288 w->WriteULEB128(DW_AT_NAME); | |
1289 w->WriteULEB128(DW_FORM_STRING); | |
1290 w->WriteULEB128(0); | |
1291 w->WriteULEB128(0); | |
1292 | |
1293 int current_abbreviation = 4; | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
Move it to the beginning of the function and use i
zarko
2011/06/27 22:24:29
Done.
| |
1294 for (int param = 0; param < params; ++param) { | |
1295 w->WriteULEB128(current_abbreviation++); | |
1296 w->WriteULEB128(DW_TAG_FORMAL_PARAMETER); | |
1297 w->Write<uint8_t>(DW_CHILDREN_NO); | |
1298 w->WriteULEB128(DW_AT_NAME); | |
1299 w->WriteULEB128(DW_FORM_STRING); | |
1300 w->WriteULEB128(DW_AT_TYPE); | |
1301 w->WriteULEB128(DW_FORM_REF4); | |
1302 w->WriteULEB128(DW_AT_LOCATION); | |
1303 w->WriteULEB128(DW_FORM_BLOCK4); | |
1304 w->WriteULEB128(0); | |
1305 w->WriteULEB128(0); | |
1306 } | |
1307 | |
1308 for (int slot = 0; slot < slots; ++slot) { | |
1309 w->WriteULEB128(current_abbreviation++); | |
1310 w->WriteULEB128(DW_TAG_VARIABLE); | |
1311 w->Write<uint8_t>(DW_CHILDREN_NO); | |
1312 w->WriteULEB128(DW_AT_NAME); | |
1313 w->WriteULEB128(DW_FORM_STRING); | |
1314 w->WriteULEB128(0); | |
1315 w->WriteULEB128(0); | |
1316 } | |
1317 | |
1318 for (int context_slot = 0; context_slot < context_slots; | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
for(x;
y;
z)
zarko
2011/06/27 22:24:29
Done.
| |
1319 ++context_slot) { | |
1320 w->WriteULEB128(current_abbreviation++); | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
Seems to be duplicated. Extract to a method?
| |
1321 w->WriteULEB128(DW_TAG_VARIABLE); | |
1322 w->Write<uint8_t>(DW_CHILDREN_NO); | |
1323 w->WriteULEB128(DW_AT_NAME); | |
1324 w->WriteULEB128(DW_FORM_STRING); | |
1325 w->WriteULEB128(0); | |
1326 w->WriteULEB128(0); | |
1327 } | |
1328 | |
1329 for (int internal_slot = 0; internal_slot < internal_slots; | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
for(x;
y;
z)
zarko
2011/06/27 22:24:29
Done.
| |
1330 ++internal_slot) { | |
1331 w->WriteULEB128(current_abbreviation++); | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
Seems to be duplicated. Extract to a method?
Mayb
| |
1332 w->WriteULEB128(DW_TAG_VARIABLE); | |
1333 w->Write<uint8_t>(DW_CHILDREN_NO); | |
1334 w->WriteULEB128(DW_AT_NAME); | |
1335 w->WriteULEB128(DW_FORM_STRING); | |
1336 w->WriteULEB128(0); | |
1337 w->WriteULEB128(0); | |
1338 } | |
1339 | |
1340 for (int local = 0; local < locals; ++local) { | |
1341 w->WriteULEB128(current_abbreviation++); | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
Partially duplicated. If possible try to unify wit
| |
1342 w->WriteULEB128(DW_TAG_VARIABLE); | |
1343 w->Write<uint8_t>(DW_CHILDREN_NO); | |
1344 w->WriteULEB128(DW_AT_NAME); | |
1345 w->WriteULEB128(DW_FORM_STRING); | |
1346 w->WriteULEB128(DW_AT_TYPE); | |
1347 w->WriteULEB128(DW_FORM_REF4); | |
1348 w->WriteULEB128(DW_AT_LOCATION); | |
1349 w->WriteULEB128(DW_FORM_BLOCK4); | |
1350 w->WriteULEB128(0); | |
1351 w->WriteULEB128(0); | |
1352 } | |
1353 | |
1354 // The function. | |
1355 w->WriteULEB128(current_abbreviation++); | |
1356 w->WriteULEB128(DW_TAG_VARIABLE); | |
1357 w->Write<uint8_t>(DW_CHILDREN_NO); | |
1358 w->WriteULEB128(DW_AT_NAME); | |
1359 w->WriteULEB128(DW_FORM_STRING); | |
1360 w->WriteULEB128(DW_AT_TYPE); | |
1361 w->WriteULEB128(DW_FORM_REF4); | |
1362 w->WriteULEB128(DW_AT_LOCATION); | |
1363 w->WriteULEB128(DW_FORM_BLOCK4); | |
1364 w->WriteULEB128(0); | |
1365 w->WriteULEB128(0); | |
1366 | |
1367 // The context. | |
1368 w->WriteULEB128(current_abbreviation++); | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
Duplicated?
| |
1369 w->WriteULEB128(DW_TAG_VARIABLE); | |
1370 w->Write<uint8_t>(DW_CHILDREN_NO); | |
1371 w->WriteULEB128(DW_AT_NAME); | |
1372 w->WriteULEB128(DW_FORM_STRING); | |
1373 w->WriteULEB128(DW_AT_TYPE); | |
1374 w->WriteULEB128(DW_FORM_REF4); | |
1375 w->WriteULEB128(DW_AT_LOCATION); | |
1376 w->WriteULEB128(DW_FORM_BLOCK4); | |
1377 w->WriteULEB128(0); | |
1378 w->WriteULEB128(0); | |
1379 | |
1380 if (total_children != 0) { | |
1381 w->WriteULEB128(0); // Terminate the sibling list. | |
1382 } | |
1383 } | |
1384 | |
1385 w->WriteULEB128(0); // Terminate the table. | |
830 return true; | 1386 return true; |
831 } | 1387 } |
1388 | |
1389 private: | |
1390 CodeDescription* desc_; | |
832 }; | 1391 }; |
833 | 1392 |
834 | 1393 |
835 class DebugLineSection : public ELFSection { | 1394 class DebugLineSection : public SECTION_BASE { |
836 public: | 1395 public: |
837 explicit DebugLineSection(CodeDescription* desc) | 1396 explicit DebugLineSection(CodeDescription* desc) |
1397 #ifdef __ELF | |
838 : ELFSection(".debug_line", TYPE_PROGBITS, 1), | 1398 : ELFSection(".debug_line", TYPE_PROGBITS, 1), |
1399 #else | |
1400 : MachOSection("__debug_line", "__DWARF", 1, | |
1401 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG), | |
1402 #endif | |
839 desc_(desc) { } | 1403 desc_(desc) { } |
840 | 1404 |
841 // DWARF2 standard, figure 34. | 1405 // DWARF2 standard, figure 34. |
842 enum DWARF2Opcodes { | 1406 enum DWARF2Opcodes { |
843 DW_LNS_COPY = 1, | 1407 DW_LNS_COPY = 1, |
844 DW_LNS_ADVANCE_PC = 2, | 1408 DW_LNS_ADVANCE_PC = 2, |
845 DW_LNS_ADVANCE_LINE = 3, | 1409 DW_LNS_ADVANCE_LINE = 3, |
846 DW_LNS_SET_FILE = 4, | 1410 DW_LNS_SET_FILE = 4, |
847 DW_LNS_SET_COLUMN = 5, | 1411 DW_LNS_SET_COLUMN = 5, |
848 DW_LNS_NEGATE_STMT = 6 | 1412 DW_LNS_NEGATE_STMT = 6 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
985 return -1; | 1549 return -1; |
986 } | 1550 } |
987 } | 1551 } |
988 | 1552 |
989 CodeDescription* desc_; | 1553 CodeDescription* desc_; |
990 }; | 1554 }; |
991 | 1555 |
992 | 1556 |
993 #ifdef V8_TARGET_ARCH_X64 | 1557 #ifdef V8_TARGET_ARCH_X64 |
994 | 1558 |
995 | 1559 class UnwindInfoSection : public SECTION_BASE { |
996 class UnwindInfoSection : public ELFSection { | |
997 public: | 1560 public: |
998 explicit UnwindInfoSection(CodeDescription *desc); | 1561 explicit UnwindInfoSection(CodeDescription *desc); |
999 virtual bool WriteBody(Writer *w); | 1562 virtual bool WriteBody(Writer *w); |
1000 | 1563 |
1001 int WriteCIE(Writer *w); | 1564 int WriteCIE(Writer *w); |
1002 void WriteFDE(Writer *w, int); | 1565 void WriteFDE(Writer *w, int); |
1003 | 1566 |
1004 void WriteFDEStateOnEntry(Writer *w); | 1567 void WriteFDEStateOnEntry(Writer *w); |
1005 void WriteFDEStateAfterRBPPush(Writer *w); | 1568 void WriteFDEStateAfterRBPPush(Writer *w); |
1006 void WriteFDEStateAfterRBPSet(Writer *w); | 1569 void WriteFDEStateAfterRBPSet(Writer *w); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1072 w->Write<uint8_t>(DW_CFA_NOP); | 1635 w->Write<uint8_t>(DW_CFA_NOP); |
1073 } | 1636 } |
1074 } | 1637 } |
1075 | 1638 |
1076 ASSERT((w->position() - initial_position) % kPointerSize == 0); | 1639 ASSERT((w->position() - initial_position) % kPointerSize == 0); |
1077 length_slot->set(w->position() - initial_position); | 1640 length_slot->set(w->position() - initial_position); |
1078 } | 1641 } |
1079 | 1642 |
1080 | 1643 |
1081 UnwindInfoSection::UnwindInfoSection(CodeDescription *desc) | 1644 UnwindInfoSection::UnwindInfoSection(CodeDescription *desc) |
1082 : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), desc_(desc) | 1645 #ifdef __ELF |
1083 { } | 1646 : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), |
1647 #else | |
1648 : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t), | |
1649 MachOSection::S_REGULAR), | |
1650 #endif | |
1651 desc_(desc) { } | |
1084 | 1652 |
1085 int UnwindInfoSection::WriteCIE(Writer *w) { | 1653 int UnwindInfoSection::WriteCIE(Writer *w) { |
1086 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>(); | 1654 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>(); |
1087 uint32_t cie_position = w->position(); | 1655 uint32_t cie_position = w->position(); |
1088 | 1656 |
1089 // Write out the CIE header. Currently no 'common instructions' are | 1657 // Write out the CIE header. Currently no 'common instructions' are |
1090 // emitted onto the CIE; every FDE has its own set of instructions. | 1658 // emitted onto the CIE; every FDE has its own set of instructions. |
1091 | 1659 |
1092 w->Write<uint32_t>(CIE_ID); | 1660 w->Write<uint32_t>(CIE_ID); |
1093 w->Write<uint8_t>(CIE_VERSION); | 1661 w->Write<uint8_t>(CIE_VERSION); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1205 | 1773 |
1206 bool UnwindInfoSection::WriteBody(Writer *w) { | 1774 bool UnwindInfoSection::WriteBody(Writer *w) { |
1207 uint32_t cie_position = WriteCIE(w); | 1775 uint32_t cie_position = WriteCIE(w); |
1208 WriteFDE(w, cie_position); | 1776 WriteFDE(w, cie_position); |
1209 return true; | 1777 return true; |
1210 } | 1778 } |
1211 | 1779 |
1212 | 1780 |
1213 #endif // V8_TARGET_ARCH_X64 | 1781 #endif // V8_TARGET_ARCH_X64 |
1214 | 1782 |
1215 | 1783 static void CreateDWARFSections(CodeDescription* desc, OBJ_FORMAT* obj) { |
1216 static void CreateDWARFSections(CodeDescription* desc, ELF* elf) { | |
1217 if (desc->IsLineInfoAvailable()) { | 1784 if (desc->IsLineInfoAvailable()) { |
1218 elf->AddSection(new DebugInfoSection(desc)); | 1785 obj->AddSection(new DebugInfoSection(desc)); |
1219 elf->AddSection(new DebugAbbrevSection); | 1786 obj->AddSection(new DebugAbbrevSection(desc)); |
1220 elf->AddSection(new DebugLineSection(desc)); | 1787 obj->AddSection(new DebugLineSection(desc)); |
1221 } | 1788 } |
1222 #ifdef V8_TARGET_ARCH_X64 | 1789 #ifdef V8_TARGET_ARCH_X64 |
1223 elf->AddSection(new UnwindInfoSection(desc)); | 1790 obj->AddSection(new UnwindInfoSection(desc)); |
1224 #endif | 1791 #endif |
1225 } | 1792 } |
1226 | 1793 |
1227 | 1794 |
1228 // ------------------------------------------------------------------- | 1795 // ------------------------------------------------------------------- |
1229 // Binary GDB JIT Interface as described in | 1796 // Binary GDB JIT Interface as described in |
1230 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html | 1797 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html |
1231 extern "C" { | 1798 extern "C" { |
1232 typedef enum { | 1799 typedef enum { |
1233 JIT_NOACTION = 0, | 1800 JIT_NOACTION = 0, |
(...skipping 19 matching lines...) Expand all Loading... | |
1253 // To prevent GCC from inlining or removing it we place noinline attribute | 1820 // To prevent GCC from inlining or removing it we place noinline attribute |
1254 // and inline assembler statement inside. | 1821 // and inline assembler statement inside. |
1255 void __attribute__((noinline)) __jit_debug_register_code() { | 1822 void __attribute__((noinline)) __jit_debug_register_code() { |
1256 __asm__(""); | 1823 __asm__(""); |
1257 } | 1824 } |
1258 | 1825 |
1259 // GDB will inspect contents of this descriptor. | 1826 // GDB will inspect contents of this descriptor. |
1260 // Static initialization is necessary to prevent GDB from seeing | 1827 // Static initialization is necessary to prevent GDB from seeing |
1261 // uninitialized descriptor. | 1828 // uninitialized descriptor. |
1262 JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; | 1829 JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; |
1830 | |
1831 #ifdef OBJECT_PRINT | |
1832 void __gdb_print_v8_object(MaybeObject* object) { | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Frankly speaking I don't see any reason to add thi
zarko
2011/06/27 22:24:29
gdb was having some trouble finding the symbol for
| |
1833 object->Print(); | |
1834 fprintf(stdout, "\n"); | |
1835 } | |
1836 #endif | |
1263 } | 1837 } |
1264 | 1838 |
1265 | 1839 |
1266 static JITCodeEntry* CreateCodeEntry(Address symfile_addr, | 1840 static JITCodeEntry* CreateCodeEntry(Address symfile_addr, |
1267 uintptr_t symfile_size) { | 1841 uintptr_t symfile_size) { |
1268 JITCodeEntry* entry = static_cast<JITCodeEntry*>( | 1842 JITCodeEntry* entry = static_cast<JITCodeEntry*>( |
1269 malloc(sizeof(JITCodeEntry) + symfile_size)); | 1843 malloc(sizeof(JITCodeEntry) + symfile_size)); |
1270 | 1844 |
1271 entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1); | 1845 entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1); |
1272 entry->symfile_size_ = symfile_size; | 1846 entry->symfile_size_ = symfile_size; |
1273 memcpy(entry->symfile_addr_, symfile_addr, symfile_size); | 1847 memcpy(entry->symfile_addr_, symfile_addr, symfile_size); |
1274 | 1848 |
1275 entry->prev_ = entry->next_ = NULL; | 1849 entry->prev_ = entry->next_ = NULL; |
1276 | 1850 |
1277 return entry; | 1851 return entry; |
1278 } | 1852 } |
1279 | 1853 |
1280 | 1854 |
1281 static void DestroyCodeEntry(JITCodeEntry* entry) { | 1855 static void DestroyCodeEntry(JITCodeEntry* entry) { |
1282 free(entry); | 1856 free(entry); |
1283 } | 1857 } |
1284 | 1858 |
1285 | 1859 |
1286 static void RegisterCodeEntry(JITCodeEntry* entry) { | 1860 static void RegisterCodeEntry(JITCodeEntry* entry, |
1861 bool dump_if_enabled, | |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
something with indentation.
zarko
2011/06/27 22:24:29
Done.
| |
1862 const char* name_hint) { | |
1287 #if defined(DEBUG) && !defined(WIN32) | 1863 #if defined(DEBUG) && !defined(WIN32) |
1288 static int file_num = 0; | 1864 static int file_num = 0; |
1289 if (FLAG_gdbjit_dump) { | 1865 if (FLAG_gdbjit_dump && dump_if_enabled) { |
1290 static const int kMaxFileNameSize = 64; | 1866 static const int kMaxFileNameSize = 64; |
1291 static const char* kElfFilePrefix = "/tmp/elfdump"; | 1867 static const char* kElfFilePrefix = "/tmp/elfdump"; |
1292 static const char* kObjFileExt = ".o"; | 1868 static const char* kObjFileExt = ".o"; |
1293 char file_name[64]; | 1869 char file_name[64]; |
1294 | 1870 |
1295 OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "%s%d%s", | 1871 OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "%s%s%d%s", |
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
One argument per line.
(somehow I missed this pla
zarko
2011/06/27 22:24:29
Done.
| |
1296 kElfFilePrefix, file_num++, kObjFileExt); | 1872 kElfFilePrefix, (name_hint != NULL) ? name_hint : "", |
1873 file_num++, kObjFileExt); | |
1297 WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_); | 1874 WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_); |
1298 } | 1875 } |
1299 #endif | 1876 #endif |
1300 | 1877 |
1301 entry->next_ = __jit_debug_descriptor.first_entry_; | 1878 entry->next_ = __jit_debug_descriptor.first_entry_; |
1302 if (entry->next_ != NULL) entry->next_->prev_ = entry; | 1879 if (entry->next_ != NULL) entry->next_->prev_ = entry; |
1303 __jit_debug_descriptor.first_entry_ = | 1880 __jit_debug_descriptor.first_entry_ = |
1304 __jit_debug_descriptor.relevant_entry_ = entry; | 1881 __jit_debug_descriptor.relevant_entry_ = entry; |
1305 | 1882 |
1306 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN; | 1883 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN; |
(...skipping 13 matching lines...) Expand all Loading... | |
1320 } | 1897 } |
1321 | 1898 |
1322 __jit_debug_descriptor.relevant_entry_ = entry; | 1899 __jit_debug_descriptor.relevant_entry_ = entry; |
1323 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN; | 1900 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN; |
1324 __jit_debug_register_code(); | 1901 __jit_debug_register_code(); |
1325 } | 1902 } |
1326 | 1903 |
1327 | 1904 |
1328 static JITCodeEntry* CreateELFObject(CodeDescription* desc) { | 1905 static JITCodeEntry* CreateELFObject(CodeDescription* desc) { |
1329 ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); | 1906 ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); |
1907 #ifdef __MACH_O | |
1908 MachO mach_o; | |
1909 Writer w(&mach_o); | |
1330 | 1910 |
1911 mach_o.AddSection(new MachOTextSection(kCodeAlignment, | |
1912 desc->CodeStart(), | |
1913 desc->CodeSize())); | |
1914 | |
1915 CreateDWARFSections(desc, &mach_o); | |
1916 | |
1917 mach_o.Write(&w, desc->CodeStart(), desc->CodeSize()); | |
1918 #else | |
1331 ELF elf; | 1919 ELF elf; |
1332 Writer w(&elf); | 1920 Writer w(&elf); |
1333 | 1921 |
1334 int text_section_index = elf.AddSection( | 1922 int text_section_index = elf.AddSection( |
1335 new FullHeaderELFSection(".text", | 1923 new FullHeaderELFSection(".text", |
1336 ELFSection::TYPE_NOBITS, | 1924 ELFSection::TYPE_NOBITS, |
1337 kCodeAlignment, | 1925 kCodeAlignment, |
1338 desc->CodeStart(), | 1926 desc->CodeStart(), |
1339 0, | 1927 0, |
1340 desc->CodeSize(), | 1928 desc->CodeSize(), |
1341 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC)); | 1929 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC)); |
1342 | 1930 |
1343 CreateSymbolsTable(desc, &elf, text_section_index); | 1931 CreateSymbolsTable(desc, &elf, text_section_index); |
1344 | 1932 |
1345 CreateDWARFSections(desc, &elf); | 1933 CreateDWARFSections(desc, &elf); |
1346 | 1934 |
1347 elf.Write(&w); | 1935 elf.Write(&w); |
1936 #endif | |
1348 | 1937 |
1349 return CreateCodeEntry(w.buffer(), w.position()); | 1938 return CreateCodeEntry(w.buffer(), w.position()); |
1350 } | 1939 } |
1351 | 1940 |
1352 | 1941 |
1353 static bool SameCodeObjects(void* key1, void* key2) { | 1942 static bool SameCodeObjects(void* key1, void* key2) { |
1354 return key1 == key2; | 1943 return key1 == key2; |
1355 } | 1944 } |
1356 | 1945 |
1357 | 1946 |
(...skipping 28 matching lines...) Expand all Loading... | |
1386 | 1975 |
1387 | 1976 |
1388 static GDBJITLineInfo* UntagLineInfo(void* ptr) { | 1977 static GDBJITLineInfo* UntagLineInfo(void* ptr) { |
1389 return reinterpret_cast<GDBJITLineInfo*>( | 1978 return reinterpret_cast<GDBJITLineInfo*>( |
1390 reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag); | 1979 reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag); |
1391 } | 1980 } |
1392 | 1981 |
1393 | 1982 |
1394 void GDBJITInterface::AddCode(Handle<String> name, | 1983 void GDBJITInterface::AddCode(Handle<String> name, |
1395 Handle<Script> script, | 1984 Handle<Script> script, |
1396 Handle<Code> code) { | 1985 Handle<Code> code, |
1986 CompilationInfo* info) { | |
1397 if (!FLAG_gdbjit) return; | 1987 if (!FLAG_gdbjit) return; |
1398 | 1988 |
1399 // Force initialization of line_ends array. | 1989 // Force initialization of line_ends array. |
1400 GetScriptLineNumber(script, 0); | 1990 GetScriptLineNumber(script, 0); |
1401 | 1991 |
1402 if (!name.is_null()) { | 1992 if (!name.is_null()) { |
1403 SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS); | 1993 SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS); |
1404 AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script); | 1994 AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script, info); |
1405 } else { | 1995 } else { |
1406 AddCode("", *code, GDBJITInterface::FUNCTION, *script); | 1996 AddCode("", *code, GDBJITInterface::FUNCTION, *script, info); |
1407 } | 1997 } |
1408 } | 1998 } |
1409 | 1999 |
1410 static void AddUnwindInfo(CodeDescription *desc) { | 2000 static void AddUnwindInfo(CodeDescription *desc) { |
1411 #ifdef V8_TARGET_ARCH_X64 | 2001 #ifdef V8_TARGET_ARCH_X64 |
1412 if (desc->tag() == GDBJITInterface::FUNCTION) { | 2002 if (desc->tag() == GDBJITInterface::FUNCTION) { |
1413 // To avoid propagating unwinding information through | 2003 // To avoid propagating unwinding information through |
1414 // compilation pipeline we use an approximation. | 2004 // compilation pipeline we use an approximation. |
1415 // For most use cases this should not affect usability. | 2005 // For most use cases this should not affect usability. |
1416 static const int kFramePointerPushOffset = 1; | 2006 static const int kFramePointerPushOffset = 1; |
(...skipping 26 matching lines...) Expand all Loading... | |
1443 #endif // V8_TARGET_ARCH_X64 | 2033 #endif // V8_TARGET_ARCH_X64 |
1444 } | 2034 } |
1445 | 2035 |
1446 | 2036 |
1447 Mutex* GDBJITInterface::mutex_ = OS::CreateMutex(); | 2037 Mutex* GDBJITInterface::mutex_ = OS::CreateMutex(); |
1448 | 2038 |
1449 | 2039 |
1450 void GDBJITInterface::AddCode(const char* name, | 2040 void GDBJITInterface::AddCode(const char* name, |
1451 Code* code, | 2041 Code* code, |
1452 GDBJITInterface::CodeTag tag, | 2042 GDBJITInterface::CodeTag tag, |
1453 Script* script) { | 2043 Script* script, |
2044 CompilationInfo* info) { | |
1454 if (!FLAG_gdbjit) return; | 2045 if (!FLAG_gdbjit) return; |
1455 | 2046 |
1456 ScopedLock lock(mutex_); | 2047 ScopedLock lock(mutex_); |
1457 AssertNoAllocation no_gc; | 2048 AssertNoAllocation no_gc; |
1458 | 2049 |
1459 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); | 2050 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); |
1460 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; | 2051 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; |
1461 | 2052 |
1462 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value); | 2053 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value); |
1463 CodeDescription code_desc(name, | 2054 CodeDescription code_desc(name, |
1464 code, | 2055 code, |
1465 script != NULL ? Handle<Script>(script) | 2056 script != NULL ? Handle<Script>(script) |
1466 : Handle<Script>(), | 2057 : Handle<Script>(), |
1467 lineinfo, | 2058 lineinfo, |
1468 tag); | 2059 tag, |
2060 info); | |
1469 | 2061 |
1470 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { | 2062 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { |
1471 delete lineinfo; | 2063 delete lineinfo; |
1472 GetEntries()->Remove(code, HashForCodeObject(code)); | 2064 GetEntries()->Remove(code, HashForCodeObject(code)); |
1473 return; | 2065 return; |
1474 } | 2066 } |
1475 | 2067 |
1476 AddUnwindInfo(&code_desc); | 2068 AddUnwindInfo(&code_desc); |
1477 JITCodeEntry* entry = CreateELFObject(&code_desc); | 2069 JITCodeEntry* entry = CreateELFObject(&code_desc); |
1478 ASSERT(!IsLineInfoTagged(entry)); | 2070 ASSERT(!IsLineInfoTagged(entry)); |
1479 | 2071 |
1480 delete lineinfo; | 2072 delete lineinfo; |
1481 e->value = entry; | 2073 e->value = entry; |
1482 | 2074 |
1483 RegisterCodeEntry(entry); | 2075 const char* name_hint = NULL; |
2076 bool should_dump = false; | |
2077 if (FLAG_gdbjit_dump) { | |
2078 if (strlen(FLAG_gdbjit_dump_filter) == 0) { | |
2079 name_hint = name; | |
2080 should_dump = true; | |
2081 } else if (name != NULL) { | |
2082 name_hint = strstr(name, FLAG_gdbjit_dump_filter); | |
2083 should_dump = (name_hint != NULL); | |
2084 } | |
2085 } | |
2086 RegisterCodeEntry(entry, should_dump, name_hint); | |
1484 } | 2087 } |
1485 | 2088 |
1486 | 2089 |
1487 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, | 2090 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, |
1488 const char* name, | 2091 const char* name, |
1489 Code* code) { | 2092 Code* code) { |
1490 if (!FLAG_gdbjit) return; | 2093 if (!FLAG_gdbjit) return; |
1491 | 2094 |
1492 EmbeddedVector<char, 256> buffer; | 2095 EmbeddedVector<char, 256> buffer; |
1493 StringBuilder builder(buffer.start(), buffer.length()); | 2096 StringBuilder builder(buffer.start(), buffer.length()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1545 ScopedLock lock(mutex_); | 2148 ScopedLock lock(mutex_); |
1546 ASSERT(!IsLineInfoTagged(line_info)); | 2149 ASSERT(!IsLineInfoTagged(line_info)); |
1547 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); | 2150 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); |
1548 ASSERT(e->value == NULL); | 2151 ASSERT(e->value == NULL); |
1549 e->value = TagLineInfo(line_info); | 2152 e->value = TagLineInfo(line_info); |
1550 } | 2153 } |
1551 | 2154 |
1552 | 2155 |
1553 } } // namespace v8::internal | 2156 } } // namespace v8::internal |
1554 #endif | 2157 #endif |
OLD | NEW |