v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
gdb-jit.cc
Go to the documentation of this file.
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifdef ENABLE_GDB_JIT_INTERFACE
29 #include "v8.h"
30 #include "gdb-jit.h"
31 
32 #include "bootstrapper.h"
33 #include "compiler.h"
34 #include "global-handles.h"
35 #include "messages.h"
36 #include "platform.h"
37 #include "natives.h"
38 #include "scopeinfo.h"
39 
40 namespace v8 {
41 namespace internal {
42 
43 #ifdef __APPLE__
44 #define __MACH_O
45 class MachO;
46 class MachOSection;
47 typedef MachO DebugObject;
48 typedef MachOSection DebugSection;
49 #else
50 #define __ELF
51 class ELF;
52 class ELFSection;
53 typedef ELF DebugObject;
54 typedef ELFSection DebugSection;
55 #endif
56 
57 class Writer BASE_EMBEDDED {
58  public:
59  explicit Writer(DebugObject* debug_object)
60  : debug_object_(debug_object),
61  position_(0),
62  capacity_(1024),
63  buffer_(reinterpret_cast<byte*>(malloc(capacity_))) {
64  }
65 
66  ~Writer() {
67  free(buffer_);
68  }
69 
70  uintptr_t position() const {
71  return position_;
72  }
73 
74  template<typename T>
75  class Slot {
76  public:
77  Slot(Writer* w, uintptr_t offset) : w_(w), offset_(offset) { }
78 
79  T* operator-> () {
80  return w_->RawSlotAt<T>(offset_);
81  }
82 
83  void set(const T& value) {
84  *w_->RawSlotAt<T>(offset_) = value;
85  }
86 
87  Slot<T> at(int i) {
88  return Slot<T>(w_, offset_ + sizeof(T) * i);
89  }
90 
91  private:
92  Writer* w_;
93  uintptr_t offset_;
94  };
95 
96  template<typename T>
97  void Write(const T& val) {
98  Ensure(position_ + sizeof(T));
99  *RawSlotAt<T>(position_) = val;
100  position_ += sizeof(T);
101  }
102 
103  template<typename T>
104  Slot<T> SlotAt(uintptr_t offset) {
105  Ensure(offset + sizeof(T));
106  return Slot<T>(this, offset);
107  }
108 
109  template<typename T>
110  Slot<T> CreateSlotHere() {
111  return CreateSlotsHere<T>(1);
112  }
113 
114  template<typename T>
115  Slot<T> CreateSlotsHere(uint32_t count) {
116  uintptr_t slot_position = position_;
117  position_ += sizeof(T) * count;
118  Ensure(position_);
119  return SlotAt<T>(slot_position);
120  }
121 
122  void Ensure(uintptr_t pos) {
123  if (capacity_ < pos) {
124  while (capacity_ < pos) capacity_ *= 2;
125  buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_));
126  }
127  }
128 
129  DebugObject* debug_object() { return debug_object_; }
130 
131  byte* buffer() { return buffer_; }
132 
133  void Align(uintptr_t align) {
134  uintptr_t delta = position_ % align;
135  if (delta == 0) return;
136  uintptr_t padding = align - delta;
137  Ensure(position_ += padding);
138  ASSERT((position_ % align) == 0);
139  }
140 
141  void WriteULEB128(uintptr_t value) {
142  do {
143  uint8_t byte = value & 0x7F;
144  value >>= 7;
145  if (value != 0) byte |= 0x80;
146  Write<uint8_t>(byte);
147  } while (value != 0);
148  }
149 
150  void WriteSLEB128(intptr_t value) {
151  bool more = true;
152  while (more) {
153  int8_t byte = value & 0x7F;
154  bool byte_sign = byte & 0x40;
155  value >>= 7;
156 
157  if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) {
158  more = false;
159  } else {
160  byte |= 0x80;
161  }
162 
163  Write<int8_t>(byte);
164  }
165  }
166 
167  void WriteString(const char* str) {
168  do {
169  Write<char>(*str);
170  } while (*str++);
171  }
172 
173  private:
174  template<typename T> friend class Slot;
175 
176  template<typename T>
177  T* RawSlotAt(uintptr_t offset) {
178  ASSERT(offset < capacity_ && offset + sizeof(T) <= capacity_);
179  return reinterpret_cast<T*>(&buffer_[offset]);
180  }
181 
182  DebugObject* debug_object_;
183  uintptr_t position_;
184  uintptr_t capacity_;
185  byte* buffer_;
186 };
187 
188 class StringTable;
189 
190 template<typename THeader>
191 class DebugSectionBase : public ZoneObject {
192  public:
193  virtual ~DebugSectionBase() { }
194 
195  virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) {
196  uintptr_t start = writer->position();
197  if (WriteBody(writer)) {
198  uintptr_t end = writer->position();
199  header->offset = start;
200 #if defined(__MACH_O)
201  header->addr = 0;
202 #endif
203  header->size = end - start;
204  }
205  }
206 
207  virtual bool WriteBody(Writer* writer) {
208  return false;
209  }
210 
211  typedef THeader Header;
212 };
213 
214 
215 struct MachOSectionHeader {
216  char sectname[16];
217  char segname[16];
218 #if defined(V8_TARGET_ARCH_IA32)
219  uint32_t addr;
220  uint32_t size;
221 #else
222  uint64_t addr;
223  uint64_t size;
224 #endif
225  uint32_t offset;
226  uint32_t align;
227  uint32_t reloff;
228  uint32_t nreloc;
229  uint32_t flags;
230  uint32_t reserved1;
231  uint32_t reserved2;
232 };
233 
234 
235 class MachOSection : public DebugSectionBase<MachOSectionHeader> {
236  public:
237  enum Type {
238  S_REGULAR = 0x0u,
239  S_ATTR_COALESCED = 0xbu,
240  S_ATTR_SOME_INSTRUCTIONS = 0x400u,
241  S_ATTR_DEBUG = 0x02000000u,
242  S_ATTR_PURE_INSTRUCTIONS = 0x80000000u
243  };
244 
245  MachOSection(const char* name,
246  const char* segment,
247  uintptr_t align,
248  uint32_t flags)
249  : name_(name),
250  segment_(segment),
251  align_(align),
252  flags_(flags) {
253  ASSERT(IsPowerOf2(align));
254  if (align_ != 0) {
255  align_ = WhichPowerOf2(align_);
256  }
257  }
258 
259  virtual ~MachOSection() { }
260 
261  virtual void PopulateHeader(Writer::Slot<Header> header) {
262  header->addr = 0;
263  header->size = 0;
264  header->offset = 0;
265  header->align = align_;
266  header->reloff = 0;
267  header->nreloc = 0;
268  header->flags = flags_;
269  header->reserved1 = 0;
270  header->reserved2 = 0;
271  memset(header->sectname, 0, sizeof(header->sectname));
272  memset(header->segname, 0, sizeof(header->segname));
273  ASSERT(strlen(name_) < sizeof(header->sectname));
274  ASSERT(strlen(segment_) < sizeof(header->segname));
275  strncpy(header->sectname, name_, sizeof(header->sectname));
276  strncpy(header->segname, segment_, sizeof(header->segname));
277  }
278 
279  private:
280  const char* name_;
281  const char* segment_;
282  uintptr_t align_;
283  uint32_t flags_;
284 };
285 
286 
287 struct ELFSectionHeader {
288  uint32_t name;
289  uint32_t type;
290  uintptr_t flags;
291  uintptr_t address;
292  uintptr_t offset;
293  uintptr_t size;
294  uint32_t link;
295  uint32_t info;
296  uintptr_t alignment;
297  uintptr_t entry_size;
298 };
299 
300 
301 #if defined(__ELF)
302 class ELFSection : public DebugSectionBase<ELFSectionHeader> {
303  public:
304  enum Type {
305  TYPE_NULL = 0,
306  TYPE_PROGBITS = 1,
307  TYPE_SYMTAB = 2,
308  TYPE_STRTAB = 3,
309  TYPE_RELA = 4,
310  TYPE_HASH = 5,
311  TYPE_DYNAMIC = 6,
312  TYPE_NOTE = 7,
313  TYPE_NOBITS = 8,
314  TYPE_REL = 9,
315  TYPE_SHLIB = 10,
316  TYPE_DYNSYM = 11,
317  TYPE_LOPROC = 0x70000000,
318  TYPE_X86_64_UNWIND = 0x70000001,
319  TYPE_HIPROC = 0x7fffffff,
320  TYPE_LOUSER = 0x80000000,
321  TYPE_HIUSER = 0xffffffff
322  };
323 
324  enum Flags {
325  FLAG_WRITE = 1,
326  FLAG_ALLOC = 2,
327  FLAG_EXEC = 4
328  };
329 
330  enum SpecialIndexes {
331  INDEX_ABSOLUTE = 0xfff1
332  };
333 
334  ELFSection(const char* name, Type type, uintptr_t align)
335  : name_(name), type_(type), align_(align) { }
336 
337  virtual ~ELFSection() { }
338 
339  void PopulateHeader(Writer::Slot<Header> header, StringTable* strtab);
340 
341  virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
342  uintptr_t start = w->position();
343  if (WriteBody(w)) {
344  uintptr_t end = w->position();
345  header->offset = start;
346  header->size = end - start;
347  }
348  }
349 
350  virtual bool WriteBody(Writer* w) {
351  return false;
352  }
353 
354  uint16_t index() const { return index_; }
355  void set_index(uint16_t index) { index_ = index; }
356 
357  protected:
358  virtual void PopulateHeader(Writer::Slot<Header> header) {
359  header->flags = 0;
360  header->address = 0;
361  header->offset = 0;
362  header->size = 0;
363  header->link = 0;
364  header->info = 0;
365  header->entry_size = 0;
366  }
367 
368  private:
369  const char* name_;
370  Type type_;
371  uintptr_t align_;
372  uint16_t index_;
373 };
374 #endif // defined(__ELF)
375 
376 
377 #if defined(__MACH_O)
378 class MachOTextSection : public MachOSection {
379  public:
380  MachOTextSection(uintptr_t align,
381  uintptr_t addr,
382  uintptr_t size)
383  : MachOSection("__text",
384  "__TEXT",
385  align,
386  MachOSection::S_REGULAR |
387  MachOSection::S_ATTR_SOME_INSTRUCTIONS |
388  MachOSection::S_ATTR_PURE_INSTRUCTIONS),
389  addr_(addr),
390  size_(size) { }
391 
392  protected:
393  virtual void PopulateHeader(Writer::Slot<Header> header) {
394  MachOSection::PopulateHeader(header);
395  header->addr = addr_;
396  header->size = size_;
397  }
398 
399  private:
400  uintptr_t addr_;
401  uintptr_t size_;
402 };
403 #endif // defined(__MACH_O)
404 
405 
406 #if defined(__ELF)
407 class FullHeaderELFSection : public ELFSection {
408  public:
409  FullHeaderELFSection(const char* name,
410  Type type,
411  uintptr_t align,
412  uintptr_t addr,
413  uintptr_t offset,
414  uintptr_t size,
415  uintptr_t flags)
416  : ELFSection(name, type, align),
417  addr_(addr),
418  offset_(offset),
419  size_(size),
420  flags_(flags) { }
421 
422  protected:
423  virtual void PopulateHeader(Writer::Slot<Header> header) {
424  ELFSection::PopulateHeader(header);
425  header->address = addr_;
426  header->offset = offset_;
427  header->size = size_;
428  header->flags = flags_;
429  }
430 
431  private:
432  uintptr_t addr_;
433  uintptr_t offset_;
434  uintptr_t size_;
435  uintptr_t flags_;
436 };
437 
438 
439 class StringTable : public ELFSection {
440  public:
441  explicit StringTable(const char* name)
442  : ELFSection(name, TYPE_STRTAB, 1), writer_(NULL), offset_(0), size_(0) {
443  }
444 
445  uintptr_t Add(const char* str) {
446  if (*str == '\0') return 0;
447 
448  uintptr_t offset = size_;
449  WriteString(str);
450  return offset;
451  }
452 
453  void AttachWriter(Writer* w) {
454  writer_ = w;
455  offset_ = writer_->position();
456 
457  // First entry in the string table should be an empty string.
458  WriteString("");
459  }
460 
461  void DetachWriter() {
462  writer_ = NULL;
463  }
464 
465  virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
466  ASSERT(writer_ == NULL);
467  header->offset = offset_;
468  header->size = size_;
469  }
470 
471  private:
472  void WriteString(const char* str) {
473  uintptr_t written = 0;
474  do {
475  writer_->Write(*str);
476  written++;
477  } while (*str++);
478  size_ += written;
479  }
480 
481  Writer* writer_;
482 
483  uintptr_t offset_;
484  uintptr_t size_;
485 };
486 
487 
488 void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
489  StringTable* strtab) {
490  header->name = strtab->Add(name_);
491  header->type = type_;
492  header->alignment = align_;
493  PopulateHeader(header);
494 }
495 #endif // defined(__ELF)
496 
497 
498 #if defined(__MACH_O)
499 class MachO BASE_EMBEDDED {
500  public:
501  MachO() : sections_(6) { }
502 
503  uint32_t AddSection(MachOSection* section) {
504  sections_.Add(section);
505  return sections_.length() - 1;
506  }
507 
508  void Write(Writer* w, uintptr_t code_start, uintptr_t code_size) {
509  Writer::Slot<MachOHeader> header = WriteHeader(w);
510  uintptr_t load_command_start = w->position();
511  Writer::Slot<MachOSegmentCommand> cmd = WriteSegmentCommand(w,
512  code_start,
513  code_size);
514  WriteSections(w, cmd, header, load_command_start);
515  }
516 
517  private:
518  struct MachOHeader {
519  uint32_t magic;
520  uint32_t cputype;
521  uint32_t cpusubtype;
522  uint32_t filetype;
523  uint32_t ncmds;
524  uint32_t sizeofcmds;
525  uint32_t flags;
526 #if defined(V8_TARGET_ARCH_X64)
527  uint32_t reserved;
528 #endif
529  };
530 
531  struct MachOSegmentCommand {
532  uint32_t cmd;
533  uint32_t cmdsize;
534  char segname[16];
535 #if defined(V8_TARGET_ARCH_IA32)
536  uint32_t vmaddr;
537  uint32_t vmsize;
538  uint32_t fileoff;
539  uint32_t filesize;
540 #else
541  uint64_t vmaddr;
542  uint64_t vmsize;
543  uint64_t fileoff;
544  uint64_t filesize;
545 #endif
546  uint32_t maxprot;
547  uint32_t initprot;
548  uint32_t nsects;
549  uint32_t flags;
550  };
551 
552  enum MachOLoadCommandCmd {
553  LC_SEGMENT_32 = 0x00000001u,
554  LC_SEGMENT_64 = 0x00000019u
555  };
556 
557 
558  Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
559  ASSERT(w->position() == 0);
560  Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
561 #if defined(V8_TARGET_ARCH_IA32)
562  header->magic = 0xFEEDFACEu;
563  header->cputype = 7; // i386
564  header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
565 #elif defined(V8_TARGET_ARCH_X64)
566  header->magic = 0xFEEDFACFu;
567  header->cputype = 7 | 0x01000000; // i386 | 64-bit ABI
568  header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
569  header->reserved = 0;
570 #else
571 #error Unsupported target architecture.
572 #endif
573  header->filetype = 0x1; // MH_OBJECT
574  header->ncmds = 1;
575  header->sizeofcmds = 0;
576  header->flags = 0;
577  return header;
578  }
579 
580 
581  Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w,
582  uintptr_t code_start,
583  uintptr_t code_size) {
584  Writer::Slot<MachOSegmentCommand> cmd =
585  w->CreateSlotHere<MachOSegmentCommand>();
586 #if defined(V8_TARGET_ARCH_IA32)
587  cmd->cmd = LC_SEGMENT_32;
588 #else
589  cmd->cmd = LC_SEGMENT_64;
590 #endif
591  cmd->vmaddr = code_start;
592  cmd->vmsize = code_size;
593  cmd->fileoff = 0;
594  cmd->filesize = 0;
595  cmd->maxprot = 7;
596  cmd->initprot = 7;
597  cmd->flags = 0;
598  cmd->nsects = sections_.length();
599  memset(cmd->segname, 0, 16);
600  cmd->cmdsize = sizeof(MachOSegmentCommand) + sizeof(MachOSection::Header) *
601  cmd->nsects;
602  return cmd;
603  }
604 
605 
606  void WriteSections(Writer* w,
607  Writer::Slot<MachOSegmentCommand> cmd,
608  Writer::Slot<MachOHeader> header,
609  uintptr_t load_command_start) {
610  Writer::Slot<MachOSection::Header> headers =
611  w->CreateSlotsHere<MachOSection::Header>(sections_.length());
612  cmd->fileoff = w->position();
613  header->sizeofcmds = w->position() - load_command_start;
614  for (int section = 0; section < sections_.length(); ++section) {
615  sections_[section]->PopulateHeader(headers.at(section));
616  sections_[section]->WriteBody(headers.at(section), w);
617  }
618  cmd->filesize = w->position() - (uintptr_t)cmd->fileoff;
619  }
620 
621 
622  ZoneList<MachOSection*> sections_;
623 };
624 #endif // defined(__MACH_O)
625 
626 
627 #if defined(__ELF)
628 class ELF BASE_EMBEDDED {
629  public:
630  ELF() : sections_(6) {
631  sections_.Add(new ELFSection("", ELFSection::TYPE_NULL, 0));
632  sections_.Add(new StringTable(".shstrtab"));
633  }
634 
635  void Write(Writer* w) {
636  WriteHeader(w);
637  WriteSectionTable(w);
638  WriteSections(w);
639  }
640 
641  ELFSection* SectionAt(uint32_t index) {
642  return sections_[index];
643  }
644 
645  uint32_t AddSection(ELFSection* section) {
646  sections_.Add(section);
647  section->set_index(sections_.length() - 1);
648  return sections_.length() - 1;
649  }
650 
651  private:
652  struct ELFHeader {
653  uint8_t ident[16];
654  uint16_t type;
655  uint16_t machine;
656  uint32_t version;
657  uintptr_t entry;
658  uintptr_t pht_offset;
659  uintptr_t sht_offset;
660  uint32_t flags;
661  uint16_t header_size;
662  uint16_t pht_entry_size;
663  uint16_t pht_entry_num;
664  uint16_t sht_entry_size;
665  uint16_t sht_entry_num;
666  uint16_t sht_strtab_index;
667  };
668 
669 
670  void WriteHeader(Writer* w) {
671  ASSERT(w->position() == 0);
672  Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
673 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_ARM)
674  const uint8_t ident[16] =
675  { 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
676 #elif defined(V8_TARGET_ARCH_X64)
677  const uint8_t ident[16] =
678  { 0x7f, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0 , 0, 0, 0, 0, 0, 0};
679 #else
680 #error Unsupported target architecture.
681 #endif
682  memcpy(header->ident, ident, 16);
683  header->type = 1;
684 #if defined(V8_TARGET_ARCH_IA32)
685  header->machine = 3;
686 #elif defined(V8_TARGET_ARCH_X64)
687  // Processor identification value for x64 is 62 as defined in
688  // System V ABI, AMD64 Supplement
689  // http://www.x86-64.org/documentation/abi.pdf
690  header->machine = 62;
691 #elif defined(V8_TARGET_ARCH_ARM)
692  // Set to EM_ARM, defined as 40, in "ARM ELF File Format" at
693  // infocenter.arm.com/help/topic/com.arm.doc.dui0101a/DUI0101A_Elf.pdf
694  header->machine = 40;
695 #else
696 #error Unsupported target architecture.
697 #endif
698  header->version = 1;
699  header->entry = 0;
700  header->pht_offset = 0;
701  header->sht_offset = sizeof(ELFHeader); // Section table follows header.
702  header->flags = 0;
703  header->header_size = sizeof(ELFHeader);
704  header->pht_entry_size = 0;
705  header->pht_entry_num = 0;
706  header->sht_entry_size = sizeof(ELFSection::Header);
707  header->sht_entry_num = sections_.length();
708  header->sht_strtab_index = 1;
709  }
710 
711  void WriteSectionTable(Writer* w) {
712  // Section headers table immediately follows file header.
713  ASSERT(w->position() == sizeof(ELFHeader));
714 
715  Writer::Slot<ELFSection::Header> headers =
716  w->CreateSlotsHere<ELFSection::Header>(sections_.length());
717 
718  // String table for section table is the first section.
719  StringTable* strtab = static_cast<StringTable*>(SectionAt(1));
720  strtab->AttachWriter(w);
721  for (int i = 0, length = sections_.length();
722  i < length;
723  i++) {
724  sections_[i]->PopulateHeader(headers.at(i), strtab);
725  }
726  strtab->DetachWriter();
727  }
728 
729  int SectionHeaderPosition(uint32_t section_index) {
730  return sizeof(ELFHeader) + sizeof(ELFSection::Header) * section_index;
731  }
732 
733  void WriteSections(Writer* w) {
734  Writer::Slot<ELFSection::Header> headers =
735  w->SlotAt<ELFSection::Header>(sizeof(ELFHeader));
736 
737  for (int i = 0, length = sections_.length();
738  i < length;
739  i++) {
740  sections_[i]->WriteBody(headers.at(i), w);
741  }
742  }
743 
744  ZoneList<ELFSection*> sections_;
745 };
746 
747 
748 class ELFSymbol BASE_EMBEDDED {
749  public:
750  enum Type {
751  TYPE_NOTYPE = 0,
752  TYPE_OBJECT = 1,
753  TYPE_FUNC = 2,
754  TYPE_SECTION = 3,
755  TYPE_FILE = 4,
756  TYPE_LOPROC = 13,
757  TYPE_HIPROC = 15
758  };
759 
760  enum Binding {
761  BIND_LOCAL = 0,
762  BIND_GLOBAL = 1,
763  BIND_WEAK = 2,
764  BIND_LOPROC = 13,
765  BIND_HIPROC = 15
766  };
767 
768  ELFSymbol(const char* name,
769  uintptr_t value,
770  uintptr_t size,
771  Binding binding,
772  Type type,
773  uint16_t section)
774  : name(name),
775  value(value),
776  size(size),
777  info((binding << 4) | type),
778  other(0),
779  section(section) {
780  }
781 
782  Binding binding() const {
783  return static_cast<Binding>(info >> 4);
784  }
785 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_ARM)
786  struct SerializedLayout {
787  SerializedLayout(uint32_t name,
788  uintptr_t value,
789  uintptr_t size,
790  Binding binding,
791  Type type,
792  uint16_t section)
793  : name(name),
794  value(value),
795  size(size),
796  info((binding << 4) | type),
797  other(0),
798  section(section) {
799  }
800 
801  uint32_t name;
802  uintptr_t value;
803  uintptr_t size;
804  uint8_t info;
805  uint8_t other;
806  uint16_t section;
807  };
808 #elif defined(V8_TARGET_ARCH_X64)
809  struct SerializedLayout {
810  SerializedLayout(uint32_t name,
811  uintptr_t value,
812  uintptr_t size,
813  Binding binding,
814  Type type,
815  uint16_t section)
816  : name(name),
817  info((binding << 4) | type),
818  other(0),
819  section(section),
820  value(value),
821  size(size) {
822  }
823 
824  uint32_t name;
825  uint8_t info;
826  uint8_t other;
827  uint16_t section;
828  uintptr_t value;
829  uintptr_t size;
830  };
831 #endif
832 
833  void Write(Writer::Slot<SerializedLayout> s, StringTable* t) {
834  // Convert symbol names from strings to indexes in the string table.
835  s->name = t->Add(name);
836  s->value = value;
837  s->size = size;
838  s->info = info;
839  s->other = other;
840  s->section = section;
841  }
842 
843  private:
844  const char* name;
845  uintptr_t value;
846  uintptr_t size;
847  uint8_t info;
848  uint8_t other;
849  uint16_t section;
850 };
851 
852 
853 class ELFSymbolTable : public ELFSection {
854  public:
855  explicit ELFSymbolTable(const char* name)
856  : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
857  locals_(1),
858  globals_(1) {
859  }
860 
861  virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
862  w->Align(header->alignment);
863  int total_symbols = locals_.length() + globals_.length() + 1;
864  header->offset = w->position();
865 
866  Writer::Slot<ELFSymbol::SerializedLayout> symbols =
867  w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols);
868 
869  header->size = w->position() - header->offset;
870 
871  // String table for this symbol table should follow it in the section table.
872  StringTable* strtab =
873  static_cast<StringTable*>(w->debug_object()->SectionAt(index() + 1));
874  strtab->AttachWriter(w);
875  symbols.at(0).set(ELFSymbol::SerializedLayout(0,
876  0,
877  0,
878  ELFSymbol::BIND_LOCAL,
879  ELFSymbol::TYPE_NOTYPE,
880  0));
881  WriteSymbolsList(&locals_, symbols.at(1), strtab);
882  WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab);
883  strtab->DetachWriter();
884  }
885 
886  void Add(const ELFSymbol& symbol) {
887  if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
888  locals_.Add(symbol);
889  } else {
890  globals_.Add(symbol);
891  }
892  }
893 
894  protected:
895  virtual void PopulateHeader(Writer::Slot<Header> header) {
896  ELFSection::PopulateHeader(header);
897  // We are assuming that string table will follow symbol table.
898  header->link = index() + 1;
899  header->info = locals_.length() + 1;
900  header->entry_size = sizeof(ELFSymbol::SerializedLayout);
901  }
902 
903  private:
904  void WriteSymbolsList(const ZoneList<ELFSymbol>* src,
905  Writer::Slot<ELFSymbol::SerializedLayout> dst,
906  StringTable* strtab) {
907  for (int i = 0, len = src->length();
908  i < len;
909  i++) {
910  src->at(i).Write(dst.at(i), strtab);
911  }
912  }
913 
914  ZoneList<ELFSymbol> locals_;
915  ZoneList<ELFSymbol> globals_;
916 };
917 #endif // defined(__ELF)
918 
919 
920 class CodeDescription BASE_EMBEDDED {
921  public:
922 #ifdef V8_TARGET_ARCH_X64
923  enum StackState {
924  POST_RBP_PUSH,
925  POST_RBP_SET,
926  POST_RBP_POP,
927  STACK_STATE_MAX
928  };
929 #endif
930 
931  CodeDescription(const char* name,
932  Code* code,
933  Handle<Script> script,
934  GDBJITLineInfo* lineinfo,
935  GDBJITInterface::CodeTag tag,
936  CompilationInfo* info)
937  : name_(name),
938  code_(code),
939  script_(script),
940  lineinfo_(lineinfo),
941  tag_(tag),
942  info_(info) {
943  }
944 
945  const char* name() const {
946  return name_;
947  }
948 
949  GDBJITLineInfo* lineinfo() const {
950  return lineinfo_;
951  }
952 
953  GDBJITInterface::CodeTag tag() const {
954  return tag_;
955  }
956 
957  CompilationInfo* info() const {
958  return info_;
959  }
960 
961  bool IsInfoAvailable() const {
962  return info_ != NULL;
963  }
964 
965  uintptr_t CodeStart() const {
966  return reinterpret_cast<uintptr_t>(code_->instruction_start());
967  }
968 
969  uintptr_t CodeEnd() const {
970  return reinterpret_cast<uintptr_t>(code_->instruction_end());
971  }
972 
973  uintptr_t CodeSize() const {
974  return CodeEnd() - CodeStart();
975  }
976 
977  bool IsLineInfoAvailable() {
978  return !script_.is_null() &&
979  script_->source()->IsString() &&
980  script_->HasValidSource() &&
981  script_->name()->IsString() &&
982  lineinfo_ != NULL;
983  }
984 
985 #ifdef V8_TARGET_ARCH_X64
986  uintptr_t GetStackStateStartAddress(StackState state) const {
987  ASSERT(state < STACK_STATE_MAX);
988  return stack_state_start_addresses_[state];
989  }
990 
991  void SetStackStateStartAddress(StackState state, uintptr_t addr) {
992  ASSERT(state < STACK_STATE_MAX);
993  stack_state_start_addresses_[state] = addr;
994  }
995 #endif
996 
997  SmartArrayPointer<char> GetFilename() {
998  return String::cast(script_->name())->ToCString();
999  }
1000 
1001  int GetScriptLineNumber(int pos) {
1002  return GetScriptLineNumberSafe(script_, pos) + 1;
1003  }
1004 
1005 
1006  private:
1007  const char* name_;
1008  Code* code_;
1009  Handle<Script> script_;
1010  GDBJITLineInfo* lineinfo_;
1011  GDBJITInterface::CodeTag tag_;
1012  CompilationInfo* info_;
1013 #ifdef V8_TARGET_ARCH_X64
1014  uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
1015 #endif
1016 };
1017 
1018 #if defined(__ELF)
1019 static void CreateSymbolsTable(CodeDescription* desc,
1020  ELF* elf,
1021  int text_section_index) {
1022  ELFSymbolTable* symtab = new ELFSymbolTable(".symtab");
1023  StringTable* strtab = new StringTable(".strtab");
1024 
1025  // Symbol table should be followed by the linked string table.
1026  elf->AddSection(symtab);
1027  elf->AddSection(strtab);
1028 
1029  symtab->Add(ELFSymbol("V8 Code",
1030  0,
1031  0,
1032  ELFSymbol::BIND_LOCAL,
1033  ELFSymbol::TYPE_FILE,
1034  ELFSection::INDEX_ABSOLUTE));
1035 
1036  symtab->Add(ELFSymbol(desc->name(),
1037  0,
1038  desc->CodeSize(),
1039  ELFSymbol::BIND_GLOBAL,
1040  ELFSymbol::TYPE_FUNC,
1041  text_section_index));
1042 }
1043 #endif // defined(__ELF)
1044 
1045 
1046 class DebugInfoSection : public DebugSection {
1047  public:
1048  explicit DebugInfoSection(CodeDescription* desc)
1049 #if defined(__ELF)
1050  : ELFSection(".debug_info", TYPE_PROGBITS, 1),
1051 #else
1052  : MachOSection("__debug_info",
1053  "__DWARF",
1054  1,
1055  MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1056 #endif
1057  desc_(desc) { }
1058 
1059  // DWARF2 standard
1060  enum DWARF2LocationOp {
1061  DW_OP_reg0 = 0x50,
1062  DW_OP_reg1 = 0x51,
1063  DW_OP_reg2 = 0x52,
1064  DW_OP_reg3 = 0x53,
1065  DW_OP_reg4 = 0x54,
1066  DW_OP_reg5 = 0x55,
1067  DW_OP_reg6 = 0x56,
1068  DW_OP_reg7 = 0x57,
1069  DW_OP_fbreg = 0x91 // 1 param: SLEB128 offset
1070  };
1071 
1072  enum DWARF2Encoding {
1073  DW_ATE_ADDRESS = 0x1,
1074  DW_ATE_SIGNED = 0x5
1075  };
1076 
1077  bool WriteBody(Writer* w) {
1078  uintptr_t cu_start = w->position();
1079  Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>();
1080  uintptr_t start = w->position();
1081  w->Write<uint16_t>(2); // DWARF version.
1082  w->Write<uint32_t>(0); // Abbreviation table offset.
1083  w->Write<uint8_t>(sizeof(intptr_t));
1084 
1085  w->WriteULEB128(1); // Abbreviation code.
1086  w->WriteString(*desc_->GetFilename());
1087  w->Write<intptr_t>(desc_->CodeStart());
1088  w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1089  w->Write<uint32_t>(0);
1090 
1091  uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start);
1092  w->WriteULEB128(3);
1093  w->Write<uint8_t>(kPointerSize);
1094  w->WriteString("v8value");
1095 
1096  if (desc_->IsInfoAvailable()) {
1097  CompilationInfo* info = desc_->info();
1098  ScopeInfo<FreeStoreAllocationPolicy> scope_info(info->scope());
1099  w->WriteULEB128(2);
1100  w->WriteString(desc_->name());
1101  w->Write<intptr_t>(desc_->CodeStart());
1102  w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1103  Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
1104  uintptr_t fb_block_start = w->position();
1105 #if defined(V8_TARGET_ARCH_IA32)
1106  w->Write<uint8_t>(DW_OP_reg5); // The frame pointer's here on ia32
1107 #elif defined(V8_TARGET_ARCH_X64)
1108  w->Write<uint8_t>(DW_OP_reg6); // and here on x64.
1109 #else
1110 #error Unsupported target architecture.
1111 #endif
1112  fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
1113 
1114  int params = scope_info.number_of_parameters();
1115  int slots = scope_info.number_of_stack_slots();
1116  int context_slots = scope_info.number_of_context_slots();
1117  // The real slot ID is internal_slots + context_slot_id.
1118  int internal_slots = Context::MIN_CONTEXT_SLOTS;
1119  int locals = scope_info.LocalCount();
1120  int current_abbreviation = 4;
1121 
1122  for (int param = 0; param < params; ++param) {
1123  w->WriteULEB128(current_abbreviation++);
1124  w->WriteString(
1125  *scope_info.ParameterName(param)->ToCString(DISALLOW_NULLS));
1126  w->Write<uint32_t>(ty_offset);
1127  Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1128  uintptr_t block_start = w->position();
1129  w->Write<uint8_t>(DW_OP_fbreg);
1130  w->WriteSLEB128(
1132  kPointerSize * (params - param - 1));
1133  block_size.set(static_cast<uint32_t>(w->position() - block_start));
1134  }
1135 
1136  EmbeddedVector<char, 256> buffer;
1137  StringBuilder builder(buffer.start(), buffer.length());
1138 
1139  for (int slot = 0; slot < slots; ++slot) {
1140  w->WriteULEB128(current_abbreviation++);
1141  builder.Reset();
1142  builder.AddFormatted("slot%d", slot);
1143  w->WriteString(builder.Finalize());
1144  }
1145 
1146  // See contexts.h for more information.
1152  w->WriteULEB128(current_abbreviation++);
1153  w->WriteString(".closure");
1154  w->WriteULEB128(current_abbreviation++);
1155  w->WriteString(".previous");
1156  w->WriteULEB128(current_abbreviation++);
1157  w->WriteString(".extension");
1158  w->WriteULEB128(current_abbreviation++);
1159  w->WriteString(".global");
1160 
1161  for (int context_slot = 0;
1162  context_slot < context_slots;
1163  ++context_slot) {
1164  w->WriteULEB128(current_abbreviation++);
1165  builder.Reset();
1166  builder.AddFormatted("context_slot%d", context_slot + internal_slots);
1167  w->WriteString(builder.Finalize());
1168  }
1169 
1170  for (int local = 0; local < locals; ++local) {
1171  w->WriteULEB128(current_abbreviation++);
1172  w->WriteString(
1173  *scope_info.LocalName(local)->ToCString(DISALLOW_NULLS));
1174  w->Write<uint32_t>(ty_offset);
1175  Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1176  uintptr_t block_start = w->position();
1177  w->Write<uint8_t>(DW_OP_fbreg);
1178  w->WriteSLEB128(
1180  kPointerSize * local);
1181  block_size.set(static_cast<uint32_t>(w->position() - block_start));
1182  }
1183 
1184  {
1185  w->WriteULEB128(current_abbreviation++);
1186  w->WriteString("__function");
1187  w->Write<uint32_t>(ty_offset);
1188  Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1189  uintptr_t block_start = w->position();
1190  w->Write<uint8_t>(DW_OP_fbreg);
1192  block_size.set(static_cast<uint32_t>(w->position() - block_start));
1193  }
1194 
1195  {
1196  w->WriteULEB128(current_abbreviation++);
1197  w->WriteString("__context");
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);
1202  w->WriteSLEB128(StandardFrameConstants::kContextOffset);
1203  block_size.set(static_cast<uint32_t>(w->position() - block_start));
1204  }
1205  }
1206 
1207  size.set(static_cast<uint32_t>(w->position() - start));
1208  return true;
1209  }
1210 
1211  private:
1212  CodeDescription* desc_;
1213 };
1214 
1215 
1216 class DebugAbbrevSection : public DebugSection {
1217  public:
1218  explicit DebugAbbrevSection(CodeDescription* desc)
1219 #ifdef __ELF
1220  : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1),
1221 #else
1222  : MachOSection("__debug_abbrev",
1223  "__DWARF",
1224  1,
1225  MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1226 #endif
1227  desc_(desc) { }
1228 
1229  // DWARF2 standard, figure 14.
1230  enum DWARF2Tags {
1231  DW_TAG_FORMAL_PARAMETER = 0x05,
1232  DW_TAG_POINTER_TYPE = 0xf,
1233  DW_TAG_COMPILE_UNIT = 0x11,
1234  DW_TAG_STRUCTURE_TYPE = 0x13,
1235  DW_TAG_BASE_TYPE = 0x24,
1236  DW_TAG_SUBPROGRAM = 0x2e,
1237  DW_TAG_VARIABLE = 0x34
1238  };
1239 
1240  // DWARF2 standard, figure 16.
1241  enum DWARF2ChildrenDetermination {
1242  DW_CHILDREN_NO = 0,
1243  DW_CHILDREN_YES = 1
1244  };
1245 
1246  // DWARF standard, figure 17.
1247  enum DWARF2Attribute {
1248  DW_AT_LOCATION = 0x2,
1249  DW_AT_NAME = 0x3,
1250  DW_AT_BYTE_SIZE = 0xb,
1251  DW_AT_STMT_LIST = 0x10,
1252  DW_AT_LOW_PC = 0x11,
1253  DW_AT_HIGH_PC = 0x12,
1254  DW_AT_ENCODING = 0x3e,
1255  DW_AT_FRAME_BASE = 0x40,
1256  DW_AT_TYPE = 0x49
1257  };
1258 
1259  // DWARF2 standard, figure 19.
1260  enum DWARF2AttributeForm {
1261  DW_FORM_ADDR = 0x1,
1262  DW_FORM_BLOCK4 = 0x4,
1263  DW_FORM_STRING = 0x8,
1264  DW_FORM_DATA4 = 0x6,
1265  DW_FORM_BLOCK = 0x9,
1266  DW_FORM_DATA1 = 0xb,
1267  DW_FORM_FLAG = 0xc,
1268  DW_FORM_REF4 = 0x13
1269  };
1270 
1271  void WriteVariableAbbreviation(Writer* w,
1272  int abbreviation_code,
1273  bool has_value,
1274  bool is_parameter) {
1275  w->WriteULEB128(abbreviation_code);
1276  w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
1277  w->Write<uint8_t>(DW_CHILDREN_NO);
1278  w->WriteULEB128(DW_AT_NAME);
1279  w->WriteULEB128(DW_FORM_STRING);
1280  if (has_value) {
1281  w->WriteULEB128(DW_AT_TYPE);
1282  w->WriteULEB128(DW_FORM_REF4);
1283  w->WriteULEB128(DW_AT_LOCATION);
1284  w->WriteULEB128(DW_FORM_BLOCK4);
1285  }
1286  w->WriteULEB128(0);
1287  w->WriteULEB128(0);
1288  }
1289 
1290  bool WriteBody(Writer* w) {
1291  int current_abbreviation = 1;
1292  bool extra_info = desc_->IsInfoAvailable();
1293  ASSERT(desc_->IsLineInfoAvailable());
1294  w->WriteULEB128(current_abbreviation++);
1295  w->WriteULEB128(DW_TAG_COMPILE_UNIT);
1296  w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1297  w->WriteULEB128(DW_AT_NAME);
1298  w->WriteULEB128(DW_FORM_STRING);
1299  w->WriteULEB128(DW_AT_LOW_PC);
1300  w->WriteULEB128(DW_FORM_ADDR);
1301  w->WriteULEB128(DW_AT_HIGH_PC);
1302  w->WriteULEB128(DW_FORM_ADDR);
1303  w->WriteULEB128(DW_AT_STMT_LIST);
1304  w->WriteULEB128(DW_FORM_DATA4);
1305  w->WriteULEB128(0);
1306  w->WriteULEB128(0);
1307 
1308  if (extra_info) {
1309  CompilationInfo* info = desc_->info();
1310  ScopeInfo<FreeStoreAllocationPolicy> scope_info(info->scope());
1311  int params = scope_info.number_of_parameters();
1312  int slots = scope_info.number_of_stack_slots();
1313  int context_slots = scope_info.number_of_context_slots();
1314  // The real slot ID is internal_slots + context_slot_id.
1315  int internal_slots = Context::MIN_CONTEXT_SLOTS;
1316  int locals = scope_info.LocalCount();
1317  int total_children =
1318  params + slots + context_slots + internal_slots + locals + 2;
1319 
1320  // The extra duplication below seems to be necessary to keep
1321  // gdb from getting upset on OSX.
1322  w->WriteULEB128(current_abbreviation++); // Abbreviation code.
1323  w->WriteULEB128(DW_TAG_SUBPROGRAM);
1324  w->Write<uint8_t>(
1325  total_children != 0 ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1326  w->WriteULEB128(DW_AT_NAME);
1327  w->WriteULEB128(DW_FORM_STRING);
1328  w->WriteULEB128(DW_AT_LOW_PC);
1329  w->WriteULEB128(DW_FORM_ADDR);
1330  w->WriteULEB128(DW_AT_HIGH_PC);
1331  w->WriteULEB128(DW_FORM_ADDR);
1332  w->WriteULEB128(DW_AT_FRAME_BASE);
1333  w->WriteULEB128(DW_FORM_BLOCK4);
1334  w->WriteULEB128(0);
1335  w->WriteULEB128(0);
1336 
1337  w->WriteULEB128(current_abbreviation++);
1338  w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
1339  w->Write<uint8_t>(DW_CHILDREN_NO);
1340  w->WriteULEB128(DW_AT_BYTE_SIZE);
1341  w->WriteULEB128(DW_FORM_DATA1);
1342  w->WriteULEB128(DW_AT_NAME);
1343  w->WriteULEB128(DW_FORM_STRING);
1344  w->WriteULEB128(0);
1345  w->WriteULEB128(0);
1346 
1347  for (int param = 0; param < params; ++param) {
1348  WriteVariableAbbreviation(w, current_abbreviation++, true, true);
1349  }
1350 
1351  for (int slot = 0; slot < slots; ++slot) {
1352  WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1353  }
1354 
1355  for (int internal_slot = 0;
1356  internal_slot < internal_slots;
1357  ++internal_slot) {
1358  WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1359  }
1360 
1361  for (int context_slot = 0;
1362  context_slot < context_slots;
1363  ++context_slot) {
1364  WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1365  }
1366 
1367  for (int local = 0; local < locals; ++local) {
1368  WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1369  }
1370 
1371  // The function.
1372  WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1373 
1374  // The context.
1375  WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1376 
1377  if (total_children != 0) {
1378  w->WriteULEB128(0); // Terminate the sibling list.
1379  }
1380  }
1381 
1382  w->WriteULEB128(0); // Terminate the table.
1383  return true;
1384  }
1385 
1386  private:
1387  CodeDescription* desc_;
1388 };
1389 
1390 
1391 class DebugLineSection : public DebugSection {
1392  public:
1393  explicit DebugLineSection(CodeDescription* desc)
1394 #ifdef __ELF
1395  : ELFSection(".debug_line", TYPE_PROGBITS, 1),
1396 #else
1397  : MachOSection("__debug_line",
1398  "__DWARF",
1399  1,
1400  MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1401 #endif
1402  desc_(desc) { }
1403 
1404  // DWARF2 standard, figure 34.
1405  enum DWARF2Opcodes {
1406  DW_LNS_COPY = 1,
1407  DW_LNS_ADVANCE_PC = 2,
1408  DW_LNS_ADVANCE_LINE = 3,
1409  DW_LNS_SET_FILE = 4,
1410  DW_LNS_SET_COLUMN = 5,
1411  DW_LNS_NEGATE_STMT = 6
1412  };
1413 
1414  // DWARF2 standard, figure 35.
1415  enum DWARF2ExtendedOpcode {
1416  DW_LNE_END_SEQUENCE = 1,
1417  DW_LNE_SET_ADDRESS = 2,
1418  DW_LNE_DEFINE_FILE = 3
1419  };
1420 
1421  bool WriteBody(Writer* w) {
1422  // Write prologue.
1423  Writer::Slot<uint32_t> total_length = w->CreateSlotHere<uint32_t>();
1424  uintptr_t start = w->position();
1425 
1426  // Used for special opcodes
1427  const int8_t line_base = 1;
1428  const uint8_t line_range = 7;
1429  const int8_t max_line_incr = (line_base + line_range - 1);
1430  const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
1431 
1432  w->Write<uint16_t>(2); // Field version.
1433  Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<uint32_t>();
1434  uintptr_t prologue_start = w->position();
1435  w->Write<uint8_t>(1); // Field minimum_instruction_length.
1436  w->Write<uint8_t>(1); // Field default_is_stmt.
1437  w->Write<int8_t>(line_base); // Field line_base.
1438  w->Write<uint8_t>(line_range); // Field line_range.
1439  w->Write<uint8_t>(opcode_base); // Field opcode_base.
1440  w->Write<uint8_t>(0); // DW_LNS_COPY operands count.
1441  w->Write<uint8_t>(1); // DW_LNS_ADVANCE_PC operands count.
1442  w->Write<uint8_t>(1); // DW_LNS_ADVANCE_LINE operands count.
1443  w->Write<uint8_t>(1); // DW_LNS_SET_FILE operands count.
1444  w->Write<uint8_t>(1); // DW_LNS_SET_COLUMN operands count.
1445  w->Write<uint8_t>(0); // DW_LNS_NEGATE_STMT operands count.
1446  w->Write<uint8_t>(0); // Empty include_directories sequence.
1447  w->WriteString(*desc_->GetFilename()); // File name.
1448  w->WriteULEB128(0); // Current directory.
1449  w->WriteULEB128(0); // Unknown modification time.
1450  w->WriteULEB128(0); // Unknown file size.
1451  w->Write<uint8_t>(0);
1452  prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
1453 
1454  WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t));
1455  w->Write<intptr_t>(desc_->CodeStart());
1456  w->Write<uint8_t>(DW_LNS_COPY);
1457 
1458  intptr_t pc = 0;
1459  intptr_t line = 1;
1460  bool is_statement = true;
1461 
1462  List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
1463  pc_info->Sort(&ComparePCInfo);
1464 
1465  int pc_info_length = pc_info->length();
1466  for (int i = 0; i < pc_info_length; i++) {
1467  GDBJITLineInfo::PCInfo* info = &pc_info->at(i);
1468  ASSERT(info->pc_ >= pc);
1469 
1470  // Reduce bloating in the debug line table by removing duplicate line
1471  // entries (per DWARF2 standard).
1472  intptr_t new_line = desc_->GetScriptLineNumber(info->pos_);
1473  if (new_line == line) {
1474  continue;
1475  }
1476 
1477  // Mark statement boundaries. For a better debugging experience, mark
1478  // the last pc address in the function as a statement (e.g. "}"), so that
1479  // a user can see the result of the last line executed in the function,
1480  // should control reach the end.
1481  if ((i+1) == pc_info_length) {
1482  if (!is_statement) {
1483  w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1484  }
1485  } else if (is_statement != info->is_statement_) {
1486  w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1487  is_statement = !is_statement;
1488  }
1489 
1490  // Generate special opcodes, if possible. This results in more compact
1491  // debug line tables. See the DWARF 2.0 standard to learn more about
1492  // special opcodes.
1493  uintptr_t pc_diff = info->pc_ - pc;
1494  intptr_t line_diff = new_line - line;
1495 
1496  // Compute special opcode (see DWARF 2.0 standard)
1497  intptr_t special_opcode = (line_diff - line_base) +
1498  (line_range * pc_diff) + opcode_base;
1499 
1500  // If special_opcode is less than or equal to 255, it can be used as a
1501  // special opcode. If line_diff is larger than the max line increment
1502  // allowed for a special opcode, or if line_diff is less than the minimum
1503  // line that can be added to the line register (i.e. line_base), then
1504  // special_opcode can't be used.
1505  if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
1506  (line_diff <= max_line_incr) && (line_diff >= line_base)) {
1507  w->Write<uint8_t>(special_opcode);
1508  } else {
1509  w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1510  w->WriteSLEB128(pc_diff);
1511  w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
1512  w->WriteSLEB128(line_diff);
1513  w->Write<uint8_t>(DW_LNS_COPY);
1514  }
1515 
1516  // Increment the pc and line operands.
1517  pc += pc_diff;
1518  line += line_diff;
1519  }
1520  // Advance the pc to the end of the routine, since the end sequence opcode
1521  // requires this.
1522  w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1523  w->WriteSLEB128(desc_->CodeSize() - pc);
1524  WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
1525  total_length.set(static_cast<uint32_t>(w->position() - start));
1526  return true;
1527  }
1528 
1529  private:
1530  void WriteExtendedOpcode(Writer* w,
1531  DWARF2ExtendedOpcode op,
1532  size_t operands_size) {
1533  w->Write<uint8_t>(0);
1534  w->WriteULEB128(operands_size + 1);
1535  w->Write<uint8_t>(op);
1536  }
1537 
1538  static int ComparePCInfo(const GDBJITLineInfo::PCInfo* a,
1539  const GDBJITLineInfo::PCInfo* b) {
1540  if (a->pc_ == b->pc_) {
1541  if (a->is_statement_ != b->is_statement_) {
1542  return b->is_statement_ ? +1 : -1;
1543  }
1544  return 0;
1545  } else if (a->pc_ > b->pc_) {
1546  return +1;
1547  } else {
1548  return -1;
1549  }
1550  }
1551 
1552  CodeDescription* desc_;
1553 };
1554 
1555 
1556 #ifdef V8_TARGET_ARCH_X64
1557 
1558 class UnwindInfoSection : public DebugSection {
1559  public:
1560  explicit UnwindInfoSection(CodeDescription* desc);
1561  virtual bool WriteBody(Writer* w);
1562 
1563  int WriteCIE(Writer* w);
1564  void WriteFDE(Writer* w, int);
1565 
1566  void WriteFDEStateOnEntry(Writer* w);
1567  void WriteFDEStateAfterRBPPush(Writer* w);
1568  void WriteFDEStateAfterRBPSet(Writer* w);
1569  void WriteFDEStateAfterRBPPop(Writer* w);
1570 
1571  void WriteLength(Writer* w,
1572  Writer::Slot<uint32_t>* length_slot,
1573  int initial_position);
1574 
1575  private:
1576  CodeDescription* desc_;
1577 
1578  // DWARF3 Specification, Table 7.23
1579  enum CFIInstructions {
1580  DW_CFA_ADVANCE_LOC = 0x40,
1581  DW_CFA_OFFSET = 0x80,
1582  DW_CFA_RESTORE = 0xC0,
1583  DW_CFA_NOP = 0x00,
1584  DW_CFA_SET_LOC = 0x01,
1585  DW_CFA_ADVANCE_LOC1 = 0x02,
1586  DW_CFA_ADVANCE_LOC2 = 0x03,
1587  DW_CFA_ADVANCE_LOC4 = 0x04,
1588  DW_CFA_OFFSET_EXTENDED = 0x05,
1589  DW_CFA_RESTORE_EXTENDED = 0x06,
1590  DW_CFA_UNDEFINED = 0x07,
1591  DW_CFA_SAME_VALUE = 0x08,
1592  DW_CFA_REGISTER = 0x09,
1593  DW_CFA_REMEMBER_STATE = 0x0A,
1594  DW_CFA_RESTORE_STATE = 0x0B,
1595  DW_CFA_DEF_CFA = 0x0C,
1596  DW_CFA_DEF_CFA_REGISTER = 0x0D,
1597  DW_CFA_DEF_CFA_OFFSET = 0x0E,
1598 
1599  DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
1600  DW_CFA_EXPRESSION = 0x10,
1601  DW_CFA_OFFSET_EXTENDED_SF = 0x11,
1602  DW_CFA_DEF_CFA_SF = 0x12,
1603  DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
1604  DW_CFA_VAL_OFFSET = 0x14,
1605  DW_CFA_VAL_OFFSET_SF = 0x15,
1606  DW_CFA_VAL_EXPRESSION = 0x16
1607  };
1608 
1609  // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36
1610  enum RegisterMapping {
1611  // Only the relevant ones have been added to reduce clutter.
1612  AMD64_RBP = 6,
1613  AMD64_RSP = 7,
1614  AMD64_RA = 16
1615  };
1616 
1617  enum CFIConstants {
1618  CIE_ID = 0,
1619  CIE_VERSION = 1,
1620  CODE_ALIGN_FACTOR = 1,
1621  DATA_ALIGN_FACTOR = 1,
1622  RETURN_ADDRESS_REGISTER = AMD64_RA
1623  };
1624 };
1625 
1626 
1627 void UnwindInfoSection::WriteLength(Writer* w,
1628  Writer::Slot<uint32_t>* length_slot,
1629  int initial_position) {
1630  uint32_t align = (w->position() - initial_position) % kPointerSize;
1631 
1632  if (align != 0) {
1633  for (uint32_t i = 0; i < (kPointerSize - align); i++) {
1634  w->Write<uint8_t>(DW_CFA_NOP);
1635  }
1636  }
1637 
1638  ASSERT((w->position() - initial_position) % kPointerSize == 0);
1639  length_slot->set(w->position() - initial_position);
1640 }
1641 
1642 
1643 UnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
1644 #ifdef __ELF
1645  : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1),
1646 #else
1647  : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t),
1648  MachOSection::S_REGULAR),
1649 #endif
1650  desc_(desc) { }
1651 
1652 int UnwindInfoSection::WriteCIE(Writer* w) {
1653  Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
1654  uint32_t cie_position = w->position();
1655 
1656  // Write out the CIE header. Currently no 'common instructions' are
1657  // emitted onto the CIE; every FDE has its own set of instructions.
1658 
1659  w->Write<uint32_t>(CIE_ID);
1660  w->Write<uint8_t>(CIE_VERSION);
1661  w->Write<uint8_t>(0); // Null augmentation string.
1662  w->WriteSLEB128(CODE_ALIGN_FACTOR);
1663  w->WriteSLEB128(DATA_ALIGN_FACTOR);
1664  w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
1665 
1666  WriteLength(w, &cie_length_slot, cie_position);
1667 
1668  return cie_position;
1669 }
1670 
1671 
1672 void UnwindInfoSection::WriteFDE(Writer* w, int cie_position) {
1673  // The only FDE for this function. The CFA is the current RBP.
1674  Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
1675  int fde_position = w->position();
1676  w->Write<int32_t>(fde_position - cie_position + 4);
1677 
1678  w->Write<uintptr_t>(desc_->CodeStart());
1679  w->Write<uintptr_t>(desc_->CodeSize());
1680 
1681  WriteFDEStateOnEntry(w);
1682  WriteFDEStateAfterRBPPush(w);
1683  WriteFDEStateAfterRBPSet(w);
1684  WriteFDEStateAfterRBPPop(w);
1685 
1686  WriteLength(w, &fde_length_slot, fde_position);
1687 }
1688 
1689 
1690 void UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
1691  // The first state, just after the control has been transferred to the the
1692  // function.
1693 
1694  // RBP for this function will be the value of RSP after pushing the RBP
1695  // for the previous function. The previous RBP has not been pushed yet.
1696  w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1697  w->WriteULEB128(AMD64_RSP);
1698  w->WriteSLEB128(-kPointerSize);
1699 
1700  // The RA is stored at location CFA + kCallerPCOffset. This is an invariant,
1701  // and hence omitted from the next states.
1702  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1703  w->WriteULEB128(AMD64_RA);
1704  w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
1705 
1706  // The RBP of the previous function is still in RBP.
1707  w->Write<uint8_t>(DW_CFA_SAME_VALUE);
1708  w->WriteULEB128(AMD64_RBP);
1709 
1710  // Last location described by this entry.
1711  w->Write<uint8_t>(DW_CFA_SET_LOC);
1712  w->Write<uint64_t>(
1713  desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
1714 }
1715 
1716 
1717 void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
1718  // The second state, just after RBP has been pushed.
1719 
1720  // RBP / CFA for this function is now the current RSP, so just set the
1721  // offset from the previous rule (from -8) to 0.
1722  w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
1723  w->WriteULEB128(0);
1724 
1725  // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant
1726  // in this and the next state, and hence omitted in the next state.
1727  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1728  w->WriteULEB128(AMD64_RBP);
1729  w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
1730 
1731  // Last location described by this entry.
1732  w->Write<uint8_t>(DW_CFA_SET_LOC);
1733  w->Write<uint64_t>(
1734  desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
1735 }
1736 
1737 
1738 void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
1739  // The third state, after the RBP has been set.
1740 
1741  // The CFA can now directly be set to RBP.
1742  w->Write<uint8_t>(DW_CFA_DEF_CFA);
1743  w->WriteULEB128(AMD64_RBP);
1744  w->WriteULEB128(0);
1745 
1746  // Last location described by this entry.
1747  w->Write<uint8_t>(DW_CFA_SET_LOC);
1748  w->Write<uint64_t>(
1749  desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
1750 }
1751 
1752 
1753 void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
1754  // The fourth (final) state. The RBP has been popped (just before issuing a
1755  // return).
1756 
1757  // The CFA can is now calculated in the same way as in the first state.
1758  w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1759  w->WriteULEB128(AMD64_RSP);
1760  w->WriteSLEB128(-kPointerSize);
1761 
1762  // The RBP
1763  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1764  w->WriteULEB128(AMD64_RBP);
1765  w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
1766 
1767  // Last location described by this entry.
1768  w->Write<uint8_t>(DW_CFA_SET_LOC);
1769  w->Write<uint64_t>(desc_->CodeEnd());
1770 }
1771 
1772 
1773 bool UnwindInfoSection::WriteBody(Writer* w) {
1774  uint32_t cie_position = WriteCIE(w);
1775  WriteFDE(w, cie_position);
1776  return true;
1777 }
1778 
1779 
1780 #endif // V8_TARGET_ARCH_X64
1781 
1782 static void CreateDWARFSections(CodeDescription* desc, DebugObject* obj) {
1783  if (desc->IsLineInfoAvailable()) {
1784  obj->AddSection(new DebugInfoSection(desc));
1785  obj->AddSection(new DebugAbbrevSection(desc));
1786  obj->AddSection(new DebugLineSection(desc));
1787  }
1788 #ifdef V8_TARGET_ARCH_X64
1789  obj->AddSection(new UnwindInfoSection(desc));
1790 #endif
1791 }
1792 
1793 
1794 // -------------------------------------------------------------------
1795 // Binary GDB JIT Interface as described in
1796 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
1797 extern "C" {
1798  typedef enum {
1799  JIT_NOACTION = 0,
1800  JIT_REGISTER_FN,
1801  JIT_UNREGISTER_FN
1802  } JITAction;
1803 
1804  struct JITCodeEntry {
1805  JITCodeEntry* next_;
1806  JITCodeEntry* prev_;
1807  Address symfile_addr_;
1808  uint64_t symfile_size_;
1809  };
1810 
1811  struct JITDescriptor {
1812  uint32_t version_;
1813  uint32_t action_flag_;
1814  JITCodeEntry* relevant_entry_;
1815  JITCodeEntry* first_entry_;
1816  };
1817 
1818  // GDB will place breakpoint into this function.
1819  // To prevent GCC from inlining or removing it we place noinline attribute
1820  // and inline assembler statement inside.
1821  void __attribute__((noinline)) __jit_debug_register_code() {
1822  __asm__("");
1823  }
1824 
1825  // GDB will inspect contents of this descriptor.
1826  // Static initialization is necessary to prevent GDB from seeing
1827  // uninitialized descriptor.
1828  JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
1829 
1830 #ifdef OBJECT_PRINT
1831  void __gdb_print_v8_object(MaybeObject* object) {
1832  object->Print();
1833  fprintf(stdout, "\n");
1834  }
1835 #endif
1836 }
1837 
1838 
1839 static JITCodeEntry* CreateCodeEntry(Address symfile_addr,
1840  uintptr_t symfile_size) {
1841  JITCodeEntry* entry = static_cast<JITCodeEntry*>(
1842  malloc(sizeof(JITCodeEntry) + symfile_size));
1843 
1844  entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1);
1845  entry->symfile_size_ = symfile_size;
1846  memcpy(entry->symfile_addr_, symfile_addr, symfile_size);
1847 
1848  entry->prev_ = entry->next_ = NULL;
1849 
1850  return entry;
1851 }
1852 
1853 
1854 static void DestroyCodeEntry(JITCodeEntry* entry) {
1855  free(entry);
1856 }
1857 
1858 
1859 static void RegisterCodeEntry(JITCodeEntry* entry,
1860  bool dump_if_enabled,
1861  const char* name_hint) {
1862 #if defined(DEBUG) && !defined(WIN32)
1863  static int file_num = 0;
1864  if (FLAG_gdbjit_dump && dump_if_enabled) {
1865  static const int kMaxFileNameSize = 64;
1866  static const char* kElfFilePrefix = "/tmp/elfdump";
1867  static const char* kObjFileExt = ".o";
1868  char file_name[64];
1869 
1870  OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize),
1871  "%s%s%d%s",
1872  kElfFilePrefix,
1873  (name_hint != NULL) ? name_hint : "",
1874  file_num++,
1875  kObjFileExt);
1876  WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
1877  }
1878 #endif
1879 
1880  entry->next_ = __jit_debug_descriptor.first_entry_;
1881  if (entry->next_ != NULL) entry->next_->prev_ = entry;
1882  __jit_debug_descriptor.first_entry_ =
1883  __jit_debug_descriptor.relevant_entry_ = entry;
1884 
1885  __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
1886  __jit_debug_register_code();
1887 }
1888 
1889 
1890 static void UnregisterCodeEntry(JITCodeEntry* entry) {
1891  if (entry->prev_ != NULL) {
1892  entry->prev_->next_ = entry->next_;
1893  } else {
1894  __jit_debug_descriptor.first_entry_ = entry->next_;
1895  }
1896 
1897  if (entry->next_ != NULL) {
1898  entry->next_->prev_ = entry->prev_;
1899  }
1900 
1901  __jit_debug_descriptor.relevant_entry_ = entry;
1902  __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
1903  __jit_debug_register_code();
1904 }
1905 
1906 
1907 static JITCodeEntry* CreateELFObject(CodeDescription* desc) {
1908  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
1909 #ifdef __MACH_O
1910  MachO mach_o;
1911  Writer w(&mach_o);
1912 
1913  mach_o.AddSection(new MachOTextSection(kCodeAlignment,
1914  desc->CodeStart(),
1915  desc->CodeSize()));
1916 
1917  CreateDWARFSections(desc, &mach_o);
1918 
1919  mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
1920 #else
1921  ELF elf;
1922  Writer w(&elf);
1923 
1924  int text_section_index = elf.AddSection(
1925  new FullHeaderELFSection(".text",
1926  ELFSection::TYPE_NOBITS,
1928  desc->CodeStart(),
1929  0,
1930  desc->CodeSize(),
1931  ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
1932 
1933  CreateSymbolsTable(desc, &elf, text_section_index);
1934 
1935  CreateDWARFSections(desc, &elf);
1936 
1937  elf.Write(&w);
1938 #endif
1939 
1940  return CreateCodeEntry(w.buffer(), w.position());
1941 }
1942 
1943 
1944 static bool SameCodeObjects(void* key1, void* key2) {
1945  return key1 == key2;
1946 }
1947 
1948 
1949 static HashMap* GetEntries() {
1950  static HashMap* entries = NULL;
1951  if (entries == NULL) {
1952  entries = new HashMap(&SameCodeObjects);
1953  }
1954  return entries;
1955 }
1956 
1957 
1958 static uint32_t HashForCodeObject(Code* code) {
1959  static const uintptr_t kGoldenRatio = 2654435761u;
1960  uintptr_t hash = reinterpret_cast<uintptr_t>(code->address());
1961  return static_cast<uint32_t>((hash >> kCodeAlignmentBits) * kGoldenRatio);
1962 }
1963 
1964 
1965 static const intptr_t kLineInfoTag = 0x1;
1966 
1967 
1968 static bool IsLineInfoTagged(void* ptr) {
1969  return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag);
1970 }
1971 
1972 
1973 static void* TagLineInfo(GDBJITLineInfo* ptr) {
1974  return reinterpret_cast<void*>(
1975  reinterpret_cast<intptr_t>(ptr) | kLineInfoTag);
1976 }
1977 
1978 
1979 static GDBJITLineInfo* UntagLineInfo(void* ptr) {
1980  return reinterpret_cast<GDBJITLineInfo*>(
1981  reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag);
1982 }
1983 
1984 
1985 void GDBJITInterface::AddCode(Handle<String> name,
1986  Handle<Script> script,
1987  Handle<Code> code,
1988  CompilationInfo* info) {
1989  if (!FLAG_gdbjit) return;
1990 
1991  // Force initialization of line_ends array.
1992  GetScriptLineNumber(script, 0);
1993 
1994  if (!name.is_null()) {
1995  SmartArrayPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS);
1996  AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script, info);
1997  } else {
1998  AddCode("", *code, GDBJITInterface::FUNCTION, *script, info);
1999  }
2000 }
2001 
2002 static void AddUnwindInfo(CodeDescription* desc) {
2003 #ifdef V8_TARGET_ARCH_X64
2004  if (desc->tag() == GDBJITInterface::FUNCTION) {
2005  // To avoid propagating unwinding information through
2006  // compilation pipeline we use an approximation.
2007  // For most use cases this should not affect usability.
2008  static const int kFramePointerPushOffset = 1;
2009  static const int kFramePointerSetOffset = 4;
2010  static const int kFramePointerPopOffset = -3;
2011 
2012  uintptr_t frame_pointer_push_address =
2013  desc->CodeStart() + kFramePointerPushOffset;
2014 
2015  uintptr_t frame_pointer_set_address =
2016  desc->CodeStart() + kFramePointerSetOffset;
2017 
2018  uintptr_t frame_pointer_pop_address =
2019  desc->CodeEnd() + kFramePointerPopOffset;
2020 
2021  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2022  frame_pointer_push_address);
2023  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2024  frame_pointer_set_address);
2025  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2026  frame_pointer_pop_address);
2027  } else {
2028  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2029  desc->CodeStart());
2030  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2031  desc->CodeStart());
2032  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2033  desc->CodeEnd());
2034  }
2035 #endif // V8_TARGET_ARCH_X64
2036 }
2037 
2038 
2039 static LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
2040 
2041 
2042 void GDBJITInterface::AddCode(const char* name,
2043  Code* code,
2044  GDBJITInterface::CodeTag tag,
2045  Script* script,
2046  CompilationInfo* info) {
2047  if (!FLAG_gdbjit) return;
2048 
2049  ScopedLock lock(mutex.Pointer());
2050  AssertNoAllocation no_gc;
2051 
2052  HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
2053  if (e->value != NULL && !IsLineInfoTagged(e->value)) return;
2054 
2055  GDBJITLineInfo* lineinfo = UntagLineInfo(e->value);
2056  CodeDescription code_desc(name,
2057  code,
2058  script != NULL ? Handle<Script>(script)
2059  : Handle<Script>(),
2060  lineinfo,
2061  tag,
2062  info);
2063 
2064  if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
2065  delete lineinfo;
2066  GetEntries()->Remove(code, HashForCodeObject(code));
2067  return;
2068  }
2069 
2070  AddUnwindInfo(&code_desc);
2071  JITCodeEntry* entry = CreateELFObject(&code_desc);
2072  ASSERT(!IsLineInfoTagged(entry));
2073 
2074  delete lineinfo;
2075  e->value = entry;
2076 
2077  const char* name_hint = NULL;
2078  bool should_dump = false;
2079  if (FLAG_gdbjit_dump) {
2080  if (strlen(FLAG_gdbjit_dump_filter) == 0) {
2081  name_hint = name;
2082  should_dump = true;
2083  } else if (name != NULL) {
2084  name_hint = strstr(name, FLAG_gdbjit_dump_filter);
2085  should_dump = (name_hint != NULL);
2086  }
2087  }
2088  RegisterCodeEntry(entry, should_dump, name_hint);
2089 }
2090 
2091 
2092 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
2093  const char* name,
2094  Code* code) {
2095  if (!FLAG_gdbjit) return;
2096 
2097  EmbeddedVector<char, 256> buffer;
2098  StringBuilder builder(buffer.start(), buffer.length());
2099 
2100  builder.AddString(Tag2String(tag));
2101  if ((name != NULL) && (*name != '\0')) {
2102  builder.AddString(": ");
2103  builder.AddString(name);
2104  } else {
2105  builder.AddFormatted(": code object %p", static_cast<void*>(code));
2106  }
2107 
2108  AddCode(builder.Finalize(), code, tag, NULL, NULL);
2109 }
2110 
2111 
2112 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
2113  String* name,
2114  Code* code) {
2115  if (!FLAG_gdbjit) return;
2116  AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code);
2117 }
2118 
2119 
2120 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, Code* code) {
2121  if (!FLAG_gdbjit) return;
2122 
2123  AddCode(tag, "", code);
2124 }
2125 
2126 
2127 void GDBJITInterface::RemoveCode(Code* code) {
2128  if (!FLAG_gdbjit) return;
2129 
2130  ScopedLock lock(mutex.Pointer());
2131  HashMap::Entry* e = GetEntries()->Lookup(code,
2132  HashForCodeObject(code),
2133  false);
2134  if (e == NULL) return;
2135 
2136  if (IsLineInfoTagged(e->value)) {
2137  delete UntagLineInfo(e->value);
2138  } else {
2139  JITCodeEntry* entry = static_cast<JITCodeEntry*>(e->value);
2140  UnregisterCodeEntry(entry);
2141  DestroyCodeEntry(entry);
2142  }
2143  e->value = NULL;
2144  GetEntries()->Remove(code, HashForCodeObject(code));
2145 }
2146 
2147 
2148 void GDBJITInterface::RegisterDetailedLineInfo(Code* code,
2149  GDBJITLineInfo* line_info) {
2150  ScopedLock lock(mutex.Pointer());
2151  ASSERT(!IsLineInfoTagged(line_info));
2152  HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
2153  ASSERT(e->value == NULL);
2154  e->value = TagLineInfo(line_info);
2155 }
2156 
2157 
2158 } } // namespace v8::internal
2159 #endif
byte * Address
Definition: globals.h:172
const char * ToCString(const v8::String::Utf8Value &value)
static String * cast(Object *obj)
value format" "after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, "report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true, "garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true, "flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true, "use incremental marking") DEFINE_bool(incremental_marking_steps, true, "do incremental marking steps") DEFINE_bool(trace_incremental_marking, false, "trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true, "Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false, "Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true, "use inline caching") DEFINE_bool(native_code_counters, false, "generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false, "Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true, "Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false, "Never perform compaction on full GC-testing only") DEFINE_bool(compact_code_space, true, "Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true, "Flush inline caches prior to mark compact collection and" "flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0, "Default seed for initializing random generator" "(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true, "allows verbose printing") DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") DEFINE_bool(trace_sim, false, "Trace simulator execution") DEFINE_bool(check_icache, false, "Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8, "Stack alingment in bytes in simulator(4 or 8, 8 is default)") DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true, "randomize hashes to avoid predictable hash collisions" "(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0, "Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false, "activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true, "generate optimized regexp code") DEFINE_bool(testing_bool_flag, true, "testing_bool_flag") DEFINE_int(testing_int_flag, 13, "testing_int_flag") DEFINE_float(testing_float_flag, 2.5, "float-flag") DEFINE_string(testing_string_flag, "Hello, world!", "string-flag") DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness") DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") DEFINE_bool(help, false, "Print usage message, including flags, on console") DEFINE_bool(dump_counters, false, "Dump counters on exit") DEFINE_string(map_counters, "", "Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT, "Pass all remaining arguments to the script.Alias for\"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#43"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2#define FLAG_MODE_DEFINE_DEFAULTS#1"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flag-definitions.h"1#define FLAG_FULL(ftype, ctype, nam, def, cmt)#define FLAG_READONLY(ftype, ctype, nam, def, cmt)#define DEFINE_implication(whenflag, thenflag)#define DEFINE_bool(nam, def, cmt)#define DEFINE_int(nam, def, cmt)#define DEFINE_float(nam, def, cmt)#define DEFINE_string(nam, def, cmt)#define DEFINE_args(nam, def, cmt)#define FLAG DEFINE_bool(use_strict, false,"enforce strict mode") DEFINE_bool(es5_readonly, false,"activate correct semantics for inheriting readonliness") DEFINE_bool(es52_globals, false,"activate new semantics for global var declarations") DEFINE_bool(harmony_typeof, false,"enable harmony semantics for typeof") DEFINE_bool(harmony_scoping, false,"enable harmony block scoping") DEFINE_bool(harmony_modules, false,"enable harmony modules (implies block scoping)") DEFINE_bool(harmony_proxies, false,"enable harmony proxies") DEFINE_bool(harmony_collections, false,"enable harmony collections (sets, maps, and weak maps)") DEFINE_bool(harmony, false,"enable all harmony features (except typeof)") DEFINE_implication(harmony, harmony_scoping) DEFINE_implication(harmony, harmony_modules) DEFINE_implication(harmony, harmony_proxies) DEFINE_implication(harmony, harmony_collections) DEFINE_implication(harmony_modules, harmony_scoping) DEFINE_bool(packed_arrays, false,"optimizes arrays that have no holes") DEFINE_bool(smi_only_arrays, true,"tracks arrays with only smi values") DEFINE_bool(clever_optimizations, true,"Optimize object size, Array shift, DOM strings and string +") DEFINE_bool(unbox_double_arrays, true,"automatically unbox arrays of doubles") DEFINE_bool(string_slices, true,"use string slices") DEFINE_bool(crankshaft, true,"use crankshaft") DEFINE_string(hydrogen_filter,"","optimization filter") DEFINE_bool(use_range, true,"use hydrogen range analysis") DEFINE_bool(eliminate_dead_phis, true,"eliminate dead phis") DEFINE_bool(use_gvn, true,"use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true,"use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true,"use function inlining") DEFINE_int(max_inlined_source_size, 600,"maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196,"maximum number of AST nodes considered for a single inlining") DEFINE_int(max_inlined_nodes_cumulative, 196,"maximum cumulative number of AST nodes considered for inlining") DEFINE_bool(loop_invariant_code_motion, true,"loop invariant code motion") DEFINE_bool(collect_megamorphic_maps_from_stub_cache, true,"crankshaft harvests type feedback from stub cache") DEFINE_bool(hydrogen_stats, false,"print statistics for hydrogen") DEFINE_bool(trace_hydrogen, false,"trace generated hydrogen to file") DEFINE_string(trace_phase,"Z","trace generated IR for specified phases") DEFINE_bool(trace_inlining, false,"trace inlining decisions") DEFINE_bool(trace_alloc, false,"trace register allocator") DEFINE_bool(trace_all_uses, false,"trace all use positions") DEFINE_bool(trace_range, false,"trace range analysis") DEFINE_bool(trace_gvn, false,"trace global value numbering") DEFINE_bool(trace_representation, false,"trace representation types") DEFINE_bool(stress_pointer_maps, false,"pointer map for every instruction") DEFINE_bool(stress_environments, false,"environment for every instruction") DEFINE_int(deopt_every_n_times, 0,"deoptimize every n times a deopt point is passed") DEFINE_bool(trap_on_deopt, false,"put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true,"deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true,"polymorphic inlining") DEFINE_bool(use_osr, true,"use on-stack replacement") DEFINE_bool(array_bounds_checks_elimination, false,"perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, false,"perform array index dehoisting") DEFINE_bool(trace_osr, false,"trace on-stack replacement") DEFINE_int(stress_runs, 0,"number of stress runs") DEFINE_bool(optimize_closures, true,"optimize closures") DEFINE_bool(inline_construct, true,"inline constructor calls") DEFINE_bool(inline_arguments, true,"inline functions with arguments object") DEFINE_int(loop_weight, 1,"loop weight for representation inference") DEFINE_bool(optimize_for_in, true,"optimize functions containing for-in loops") DEFINE_bool(experimental_profiler, true,"enable all profiler experiments") DEFINE_bool(watch_ic_patching, false,"profiler considers IC stability") DEFINE_int(frame_count, 1,"number of stack frames inspected by the profiler") DEFINE_bool(self_optimization, false,"primitive functions trigger their own optimization") DEFINE_bool(direct_self_opt, false,"call recompile stub directly when self-optimizing") DEFINE_bool(retry_self_opt, false,"re-try self-optimization if it failed") DEFINE_bool(count_based_interrupts, false,"trigger profiler ticks based on counting instead of timing") DEFINE_bool(interrupt_at_exit, false,"insert an interrupt check at function exit") DEFINE_bool(weighted_back_edges, false,"weight back edges by jump distance for interrupt triggering") DEFINE_int(interrupt_budget, 5900,"execution budget before interrupt is triggered") DEFINE_int(type_info_threshold, 15,"percentage of ICs that must have type info to allow optimization") DEFINE_int(self_opt_count, 130,"call count before self-optimization") DEFINE_implication(experimental_profiler, watch_ic_patching) DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, retry_self_opt) DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, interrupt_at_exit) DEFINE_implication(experimental_profiler, weighted_back_edges) DEFINE_bool(trace_opt_verbose, false,"extra verbose compilation tracing") DEFINE_implication(trace_opt_verbose, trace_opt) DEFINE_bool(debug_code, false,"generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false,"emit comments in code disassembly") DEFINE_bool(enable_sse2, true,"enable use of SSE2 instructions if available") DEFINE_bool(enable_sse3, true,"enable use of SSE3 instructions if available") DEFINE_bool(enable_sse4_1, true,"enable use of SSE4.1 instructions if available") DEFINE_bool(enable_cmov, true,"enable use of CMOV instruction if available") DEFINE_bool(enable_rdtsc, true,"enable use of RDTSC instruction if available") DEFINE_bool(enable_sahf, true,"enable use of SAHF instruction if available (X64 only)") DEFINE_bool(enable_vfp3, true,"enable use of VFP3 instructions if available - this implies ""enabling ARMv7 instructions (ARM only)") DEFINE_bool(enable_armv7, true,"enable use of ARMv7 instructions if available (ARM only)") DEFINE_bool(enable_fpu, true,"enable use of MIPS FPU instructions if available (MIPS only)") DEFINE_string(expose_natives_as, NULL,"expose natives in global object") DEFINE_string(expose_debug_as, NULL,"expose debug in global object") DEFINE_bool(expose_gc, false,"expose gc extension") DEFINE_bool(expose_externalize_string, false,"expose externalize string extension") DEFINE_int(stack_trace_limit, 10,"number of stack frames to capture") DEFINE_bool(builtins_in_stack_traces, false,"show built-in functions in stack traces") DEFINE_bool(disable_native_files, false,"disable builtin natives files") DEFINE_bool(inline_new, true,"use fast inline allocation") DEFINE_bool(stack_trace_on_abort, true,"print a stack trace if an assertion failure occurs") DEFINE_bool(trace, false,"trace function calls") DEFINE_bool(mask_constants_with_cookie, true,"use random jit cookie to mask large constants") DEFINE_bool(lazy, true,"use lazy compilation") DEFINE_bool(trace_opt, false,"trace lazy optimization") DEFINE_bool(trace_opt_stats, false,"trace lazy optimization statistics") DEFINE_bool(opt, true,"use adaptive optimizations") DEFINE_bool(always_opt, false,"always try to optimize functions") DEFINE_bool(prepare_always_opt, false,"prepare for turning on always opt") DEFINE_bool(trace_deopt, false,"trace deoptimization") DEFINE_int(min_preparse_length, 1024,"minimum length for automatic enable preparsing") DEFINE_bool(always_full_compiler, false,"try to use the dedicated run-once backend for all code") DEFINE_bool(trace_bailout, false,"print reasons for falling back to using the classic V8 backend") DEFINE_bool(compilation_cache, true,"enable compilation cache") DEFINE_bool(cache_prototype_transitions, true,"cache prototype transitions") DEFINE_bool(trace_debug_json, false,"trace debugging JSON request/response") DEFINE_bool(debugger_auto_break, true,"automatically set the debug break flag when debugger commands are ""in the queue") DEFINE_bool(enable_liveedit, true,"enable liveedit experimental feature") DEFINE_bool(break_on_abort, true,"always cause a debug break before aborting") DEFINE_int(stack_size, kPointerSize *123,"default size of stack region v8 is allowed to use (in kBytes)") DEFINE_int(max_stack_trace_source_length, 300,"maximum length of function source code printed in a stack trace.") DEFINE_bool(always_inline_smi_code, false,"always inline smi code in non-opt code") DEFINE_int(max_new_space_size, 0,"max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0,"max size of the old generation (in Mbytes)") DEFINE_int(max_executable_size, 0,"max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false,"always perform global GCs") DEFINE_int(gc_interval,-1,"garbage collect after <n> allocations") DEFINE_bool(trace_gc, false,"print one trace line following each garbage collection") DEFINE_bool(trace_gc_nvp, false,"print one detailed trace line in name=value format ""after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false,"print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false,"print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false,"report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true,"garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true,"flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true,"use incremental marking") DEFINE_bool(incremental_marking_steps, true,"do incremental marking steps") DEFINE_bool(trace_incremental_marking, false,"trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true,"Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false,"Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true,"use inline caching") DEFINE_bool(native_code_counters, false,"generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false,"Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true,"Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false,"Never perform compaction on full GC - testing only") DEFINE_bool(compact_code_space, true,"Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true,"Flush inline caches prior to mark compact collection and ""flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0,"Default seed for initializing random generator ""(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true,"allows verbose printing") DEFINE_bool(allow_natives_syntax, false,"allow natives syntax") DEFINE_bool(trace_sim, false,"Trace simulator execution") DEFINE_bool(check_icache, false,"Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0,"Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8,"Stack alingment in bytes in simulator (4 or 8, 8 is default)") DEFINE_bool(trace_exception, false,"print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false,"preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true,"randomize hashes to avoid predictable hash collisions ""(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0,"Fixed seed to use to hash property keys (0 means random)""(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false,"activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true,"generate optimized regexp code") DEFINE_bool(testing_bool_flag, true,"testing_bool_flag") DEFINE_int(testing_int_flag, 13,"testing_int_flag") DEFINE_float(testing_float_flag, 2.5,"float-flag") DEFINE_string(testing_string_flag,"Hello, world!","string-flag") DEFINE_int(testing_prng_seed, 42,"Seed used for threading test randomness") DEFINE_string(testing_serialization_file,"/tmp/serdes","file in which to serialize heap") DEFINE_bool(help, false,"Print usage message, including flags, on console") DEFINE_bool(dump_counters, false,"Dump counters on exit") DEFINE_string(map_counters,"","Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT,"Pass all remaining arguments to the script. Alias for \"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#47"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2 namespace{struct Flag{enum FlagType{TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS} name
Definition: flags.cc:1349
Flag flags[]
Definition: flags.cc:1467
int int32_t
Definition: unicode.cc:47
FlagType type_
Definition: flags.cc:1351
#define ASSERT(condition)
Definition: checks.h:270
LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak))
unsigned short uint16_t
Definition: unicode.cc:46
const intptr_t kCodeAlignment
Definition: v8globals.h:67
StringInputBuffer *const buffer_
int WhichPowerOf2(uint32_t x)
Definition: utils.h:56
uint8_t byte
Definition: globals.h:171
const int kPointerSize
Definition: globals.h:234
const Register pc
int GetScriptLineNumberSafe(Handle< Script > script, int code_pos)
Definition: handles.cc:517
bool IsPowerOf2(T x)
Definition: utils.h:50
#define BASE_EMBEDDED
Definition: allocation.h:68
LazyDynamicInstance< Mutex, CreateMutexTrait, ThreadSafeInitOnceTrait >::type LazyMutex
Definition: platform.h:556
#define T(name, string, precedence)
Definition: token.cc:48
static int SNPrintF(Vector< char > str, const char *format,...)
int GetScriptLineNumber(Handle< Script > script, int code_pos)
Definition: handles.cc:479
const int kCodeAlignmentBits
Definition: v8globals.h:66
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
Definition: hashmap.h:112
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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
const char * name_
Definition: flags.cc:1352
int WriteBytes(const char *filename, const byte *bytes, int size, bool verbose)
Definition: v8utils.cc:239
FlagType type() const
Definition: flags.cc:1358
#define LAZY_MUTEX_INITIALIZER
Definition: platform.h:558