Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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_GDBJIT_INTERFACE | |
| 29 #include "gdbjit.h" | |
| 30 | |
| 31 #include "bootstrapper.h" | |
| 32 #include "compiler.h" | |
| 33 #include "global-handles.h" | |
| 34 #include "messages.h" | |
| 35 #include "natives.h" | |
| 36 | |
| 37 namespace v8 { | |
| 38 namespace internal { | |
| 39 | |
| 40 class ELF; | |
| 41 | |
| 42 class Writer BASE_EMBEDDED { | |
| 43 public: | |
| 44 explicit Writer(ELF* elf) | |
| 45 : elf_(elf), | |
| 46 position_(0), | |
| 47 capacity_(1024), | |
| 48 buffer_(reinterpret_cast<byte*>(malloc(capacity_))) { | |
| 49 } | |
| 50 | |
| 51 ~Writer() { | |
| 52 free(buffer_); | |
| 53 } | |
| 54 | |
| 55 uintptr_t position() const { | |
| 56 return position_; | |
| 57 } | |
| 58 | |
| 59 template<typename T> | |
| 60 class Slot { | |
| 61 public: | |
| 62 Slot(Writer* w, uintptr_t offset) : w_(w), offset_(offset) { } | |
| 63 | |
| 64 T* operator-> () { | |
| 65 return w_->RawSlotAt<T>(offset_); | |
| 66 } | |
| 67 | |
| 68 void set(const T& value) { | |
| 69 *w_->RawSlotAt<T>(offset_) = value; | |
| 70 } | |
| 71 | |
| 72 Slot<T> at(int i) { | |
| 73 return Slot<T>(w_, offset_ + sizeof(T) * i); | |
| 74 } | |
| 75 | |
| 76 private: | |
| 77 Writer* w_; | |
| 78 uintptr_t offset_; | |
| 79 }; | |
| 80 | |
| 81 template<typename T> | |
| 82 void Write(const T& val) { | |
| 83 Ensure(position_ + sizeof(T)); | |
| 84 *RawSlotAt<T>(position_) = val; | |
| 85 position_ += sizeof(T); | |
| 86 } | |
| 87 | |
| 88 template<typename T> | |
| 89 Slot<T> SlotAt(uintptr_t offset) { | |
| 90 Ensure(offset + sizeof(T)); | |
| 91 return Slot<T>(this, offset); | |
| 92 } | |
| 93 | |
| 94 template<typename T> | |
| 95 Slot<T> SlotHere() { | |
|
Erik Corry
2011/01/04 14:21:48
The name should reflect the fact that this functio
Vyacheslav Egorov (Chromium)
2011/01/18 16:10:42
Done.
| |
| 96 return SlotsHere<T>(1); | |
| 97 } | |
| 98 | |
| 99 template<typename T> | |
| 100 Slot<T> SlotsHere(uint32_t count) { | |
| 101 uintptr_t slot_position = position_; | |
| 102 Ensure(position_ += sizeof(T) * count); | |
|
Erik Corry
2011/01/04 14:21:48
no no no no
Vyacheslav Egorov (Chromium)
2011/01/18 16:10:42
Done.
| |
| 103 return SlotAt<T>(slot_position); | |
| 104 } | |
| 105 | |
| 106 void Ensure(uintptr_t pos) { | |
| 107 if (capacity_ < pos) { | |
| 108 while (capacity_ < pos) capacity_ *= 2; | |
| 109 buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_)); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 ELF* elf() { return elf_; } | |
| 114 | |
| 115 byte* buffer() { return buffer_; } | |
| 116 | |
| 117 void Align(uintptr_t align) { | |
| 118 uintptr_t delta = position_ % align; | |
| 119 if (delta == 0) return; | |
| 120 uintptr_t padding = align - delta; | |
| 121 Ensure(position_ += padding); | |
| 122 ASSERT((position_ % align) == 0); | |
| 123 } | |
| 124 | |
| 125 void WriteULEB128(uintptr_t value) { | |
| 126 do { | |
| 127 uint8_t byte = value & 0x7F; | |
| 128 value >>= 7; | |
| 129 if (value != 0) byte |= 0x80; | |
| 130 Write<uint8_t>(byte); | |
| 131 } while (value != 0); | |
| 132 } | |
| 133 | |
| 134 void WriteSLEB128(intptr_t value) { | |
| 135 bool more = true; | |
| 136 while (more) { | |
| 137 int8_t byte = value & 0x7F; | |
| 138 bool byte_sign = byte & 0x40; | |
| 139 value >>= 7; | |
| 140 | |
| 141 if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) { | |
| 142 more = false; | |
| 143 } else { | |
| 144 byte |= 0x80; | |
| 145 } | |
| 146 | |
| 147 Write<int8_t>(byte); | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 void WriteString(const char* str) { | |
| 152 do { | |
| 153 Write<char>(*str); | |
| 154 } while (*str++); | |
| 155 } | |
| 156 | |
| 157 private: | |
| 158 template<typename T> friend class Slot; | |
| 159 | |
| 160 template<typename T> | |
| 161 T* RawSlotAt(uintptr_t offset) { | |
| 162 ASSERT(offset < capacity_ && offset + sizeof(T) <= capacity_); | |
| 163 return reinterpret_cast<T*>(&buffer_[offset]); | |
| 164 } | |
| 165 | |
| 166 ELF* elf_; | |
| 167 uintptr_t position_; | |
| 168 uintptr_t capacity_; | |
| 169 byte* buffer_; | |
| 170 }; | |
| 171 | |
| 172 class StringTable; | |
| 173 | |
| 174 class ELFSection : public ZoneObject { | |
| 175 public: | |
| 176 struct Header { | |
| 177 uint32_t name; | |
| 178 uint32_t type; | |
| 179 uintptr_t flags; | |
| 180 uintptr_t address; | |
| 181 uintptr_t offset; | |
| 182 uintptr_t size; | |
| 183 uint32_t link; | |
| 184 uint32_t info; | |
| 185 uintptr_t alignment; | |
| 186 uintptr_t entry_size; | |
| 187 }; | |
| 188 | |
| 189 enum Type { | |
| 190 TYPE_NULL = 0, | |
| 191 TYPE_PROGBITS = 1, | |
| 192 TYPE_SYMTAB = 2, | |
| 193 TYPE_STRTAB = 3, | |
| 194 TYPE_RELA = 4, | |
| 195 TYPE_HASH = 5, | |
| 196 TYPE_DYNAMIC = 6, | |
| 197 TYPE_NOTE = 7, | |
| 198 TYPE_NOBITS = 8, | |
| 199 TYPE_REL = 9, | |
| 200 TYPE_SHLIB = 10, | |
| 201 TYPE_DYNSYM = 11, | |
| 202 TYPE_LOPROC = 0x70000000, | |
| 203 TYPE_HIPROC = 0x7fffffff, | |
| 204 TYPE_LOUSER = 0x80000000, | |
| 205 TYPE_HIUSER = 0xffffffff | |
| 206 }; | |
| 207 | |
| 208 enum Flags { | |
| 209 FLAG_WRITE = 1, | |
| 210 FLAG_ALLOC = 2, | |
| 211 FLAG_EXEC = 4 | |
| 212 }; | |
| 213 | |
| 214 enum SpecialIndexes { | |
| 215 INDEX_ABSOLUTE = 0xfff1 | |
| 216 }; | |
| 217 | |
| 218 ELFSection(const char* name, Type type, uintptr_t align) | |
| 219 : name_(name), type_(type), align_(align) { } | |
| 220 | |
| 221 virtual ~ELFSection() { } | |
| 222 | |
| 223 void PopulateHeader(Writer::Slot<Header> header, StringTable* strtab); | |
| 224 | |
| 225 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) { | |
| 226 uintptr_t start = w->position(); | |
| 227 if (WriteBody(w)) { | |
| 228 uintptr_t end = w->position(); | |
| 229 header->offset = start; | |
| 230 header->size = end - start; | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 virtual bool WriteBody(Writer* w) { | |
| 235 return false; | |
| 236 } | |
| 237 | |
| 238 uint16_t index() const { return index_; } | |
| 239 void set_index(uint16_t index) { index_ = index; } | |
| 240 | |
| 241 protected: | |
| 242 virtual void PopulateHeader(Writer::Slot<Header> header) { | |
| 243 header->flags = 0; | |
| 244 header->address = 0; | |
| 245 header->offset = 0; | |
| 246 header->size = 0; | |
| 247 header->link = 0; | |
| 248 header->info = 0; | |
| 249 header->entry_size = 0; | |
| 250 } | |
| 251 | |
| 252 | |
| 253 private: | |
| 254 const char* name_; | |
| 255 Type type_; | |
| 256 uintptr_t align_; | |
| 257 uint16_t index_; | |
| 258 }; | |
| 259 | |
| 260 | |
| 261 class FullHeaderELFSection : public ELFSection { | |
| 262 public: | |
| 263 FullHeaderELFSection(const char* name, | |
| 264 Type type, | |
| 265 uintptr_t align, | |
| 266 uintptr_t addr, | |
| 267 uintptr_t offset, | |
| 268 uintptr_t size, | |
| 269 uintptr_t flags) | |
| 270 : ELFSection(name, type, align), | |
| 271 addr_(addr), | |
| 272 offset_(offset), | |
| 273 size_(size), | |
| 274 flags_(flags) { } | |
| 275 | |
| 276 protected: | |
| 277 virtual void PopulateHeader(Writer::Slot<Header> header) { | |
| 278 ELFSection::PopulateHeader(header); | |
| 279 header->address = addr_; | |
| 280 header->offset = offset_; | |
| 281 header->size = size_; | |
| 282 header->flags = flags_; | |
| 283 } | |
| 284 | |
| 285 private: | |
| 286 uintptr_t addr_; | |
| 287 uintptr_t offset_; | |
| 288 uintptr_t size_; | |
| 289 uintptr_t flags_; | |
| 290 }; | |
| 291 | |
| 292 | |
| 293 class StringTable : public ELFSection { | |
| 294 public: | |
| 295 explicit StringTable(const char* name) | |
| 296 : ELFSection(name, TYPE_STRTAB, 1), writer_(NULL), offset_(0), size_(0) { | |
| 297 } | |
| 298 | |
| 299 uintptr_t Add(const char* str) { | |
| 300 if (*str == '\0') return 0; | |
| 301 | |
| 302 uintptr_t offset = size_; | |
| 303 WriteString(str); | |
| 304 return offset; | |
| 305 } | |
| 306 | |
| 307 void AttachWriter(Writer* w) { | |
| 308 writer_ = w; | |
| 309 offset_ = writer_->position(); | |
| 310 | |
| 311 WriteString(""); | |
|
Erik Corry
2011/01/04 14:21:48
I'm sure there is a good reason why we do this whi
Vyacheslav Egorov (Chromium)
2011/01/18 16:10:42
Done.
| |
| 312 } | |
| 313 | |
| 314 void DetachWriter() { | |
| 315 writer_ = NULL; | |
| 316 } | |
| 317 | |
| 318 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) { | |
| 319 ASSERT(writer_ == NULL); | |
| 320 header->offset = offset_; | |
| 321 header->size = size_; | |
| 322 } | |
| 323 | |
| 324 private: | |
| 325 void WriteString(const char* str) { | |
| 326 uintptr_t written = 0; | |
| 327 do { | |
| 328 writer_->Write(*str); | |
| 329 written++; | |
| 330 } while (*str++); | |
| 331 size_ += written; | |
| 332 } | |
| 333 | |
| 334 Writer* writer_; | |
| 335 | |
| 336 uintptr_t offset_; | |
| 337 uintptr_t size_; | |
| 338 }; | |
| 339 | |
| 340 | |
| 341 void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header, | |
| 342 StringTable* strtab) { | |
| 343 header->name = strtab->Add(name_); | |
| 344 header->type = type_; | |
| 345 header->alignment = align_; | |
| 346 PopulateHeader(header); | |
| 347 } | |
| 348 | |
| 349 | |
| 350 class ELF BASE_EMBEDDED { | |
| 351 public: | |
| 352 ELF() : sections_(6) { | |
| 353 sections_.Add(new ELFSection("", ELFSection::TYPE_NULL, 0)); | |
| 354 sections_.Add(new StringTable(".shstrtab")); | |
| 355 } | |
| 356 | |
| 357 void Write(Writer* w) { | |
| 358 WriteHeader(w); | |
| 359 WriteSectionTable(w); | |
| 360 WriteSections(w); | |
| 361 } | |
| 362 | |
| 363 ELFSection* SectionAt(uint32_t index) { | |
| 364 return sections_[index]; | |
| 365 } | |
| 366 | |
| 367 uint32_t AddSection(ELFSection* section) { | |
| 368 sections_.Add(section); | |
| 369 section->set_index(sections_.length() - 1); | |
| 370 return sections_.length() - 1; | |
| 371 } | |
| 372 | |
| 373 private: | |
| 374 struct ELFHeader { | |
| 375 uint8_t ident[16]; | |
| 376 uint16_t type; | |
| 377 uint16_t machine; | |
| 378 uint32_t version; | |
| 379 uintptr_t entry; | |
| 380 uintptr_t pht_offset; | |
| 381 uintptr_t sht_offset; | |
| 382 uint32_t flags; | |
| 383 uint16_t header_size; | |
| 384 uint16_t pht_entry_size; | |
| 385 uint16_t pht_entry_num; | |
| 386 uint16_t sht_entry_size; | |
| 387 uint16_t sht_entry_num; | |
| 388 uint16_t sht_strtab_index; | |
| 389 }; | |
| 390 | |
| 391 | |
| 392 void WriteHeader(Writer* w) { | |
| 393 ASSERT(w->position() == 0); | |
| 394 Writer::Slot<ELFHeader> header = w->SlotHere<ELFHeader>(); | |
| 395 #if defined(V8_TARGET_ARCH_IA32) | |
| 396 const uint8_t ident[16] = | |
| 397 { 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | |
| 398 #elif defined(V8_TARGET_ARCH_X64) | |
| 399 const uint8_t ident[16] = | |
| 400 { 0x7f, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | |
| 401 #endif | |
|
Erik Corry
2011/01/04 14:21:48
At least one place in this file should have an els
Vyacheslav Egorov (Chromium)
2011/01/18 16:10:42
Done.
| |
| 402 memcpy(header->ident, ident, 16); | |
| 403 header->type = 1; | |
| 404 #if defined(V8_TARGET_ARCH_IA32) | |
| 405 header->machine = 3; | |
| 406 #elif defined(V8_TARGET_ARCH_X64) | |
| 407 // Processor identification value for x64 is 62 as defined in | |
| 408 // System V ABI, AMD64 Supplement | |
| 409 // http://www.x86-64.org/documentation/abi.pdf | |
| 410 header->machine = 62; | |
| 411 #endif | |
| 412 header->version = 1; | |
| 413 header->entry = 0; | |
| 414 header->pht_offset = 0; | |
| 415 header->sht_offset = sizeof(ELFHeader); // Section table follows header. | |
| 416 header->flags = 0; | |
| 417 header->header_size = sizeof(ELFHeader); | |
| 418 header->pht_entry_size = 0; | |
| 419 header->pht_entry_num = 0; | |
| 420 header->sht_entry_size = sizeof(ELFSection::Header); | |
| 421 header->sht_entry_num = sections_.length(); | |
| 422 header->sht_strtab_index = 1; | |
| 423 } | |
| 424 | |
| 425 void WriteSectionTable(Writer* w) { | |
| 426 // Section headers table immediately follows file header. | |
| 427 ASSERT(w->position() == sizeof(ELFHeader)); | |
| 428 | |
| 429 Writer::Slot<ELFSection::Header> headers = | |
| 430 w->SlotsHere<ELFSection::Header>(sections_.length()); | |
| 431 | |
| 432 // String table for section table is the first section. | |
| 433 StringTable* strtab = static_cast<StringTable*>(SectionAt(1)); | |
| 434 strtab->AttachWriter(w); | |
| 435 for (int i = 0, length = sections_.length(); | |
| 436 i < length; | |
| 437 i++) { | |
| 438 sections_[i]->PopulateHeader(headers.at(i), strtab); | |
| 439 } | |
| 440 strtab->DetachWriter(); | |
| 441 } | |
| 442 | |
| 443 int SectionHeaderPosition(uint32_t section_index) { | |
| 444 return sizeof(ELFHeader) + sizeof(ELFSection::Header) * section_index; | |
| 445 } | |
| 446 | |
| 447 void WriteSections(Writer* w) { | |
| 448 Writer::Slot<ELFSection::Header> headers = | |
| 449 w->SlotAt<ELFSection::Header>(sizeof(ELFHeader)); | |
| 450 | |
| 451 for (int i = 0, length = sections_.length(); | |
| 452 i < length; | |
| 453 i++) { | |
| 454 sections_[i]->WriteBody(headers.at(i), w); | |
| 455 } | |
| 456 } | |
| 457 | |
| 458 ZoneList<ELFSection*> sections_; | |
| 459 }; | |
| 460 | |
| 461 | |
| 462 class ELFSymbol BASE_EMBEDDED { | |
| 463 public: | |
| 464 enum Type { | |
| 465 TYPE_NOTYPE = 0, | |
| 466 TYPE_OBJECT = 1, | |
| 467 TYPE_FUNC = 2, | |
| 468 TYPE_SECTION = 3, | |
| 469 TYPE_FILE = 4, | |
| 470 TYPE_LOPROC = 13, | |
| 471 TYPE_HIPROC = 15 | |
| 472 }; | |
| 473 | |
| 474 enum Binding { | |
| 475 BIND_LOCAL = 0, | |
| 476 BIND_GLOBAL = 1, | |
| 477 BIND_WEAK = 2, | |
| 478 BIND_LOPROC = 13, | |
| 479 BIND_HIPROC = 15 | |
| 480 }; | |
| 481 | |
| 482 ELFSymbol(const char* name, | |
| 483 uintptr_t value, | |
| 484 uintptr_t size, | |
| 485 Binding binding, | |
| 486 Type type, | |
| 487 uint16_t section) | |
| 488 : name(name), | |
| 489 value(value), | |
| 490 size(size), | |
| 491 info((binding << 4) | type), | |
| 492 other(0), | |
| 493 section(section) { | |
| 494 } | |
| 495 | |
| 496 Binding binding() const { | |
| 497 return static_cast<Binding>(info >> 4); | |
| 498 } | |
| 499 | |
| 500 #if defined(V8_TARGET_ARCH_IA32) | |
| 501 struct SerializedLayout { | |
| 502 SerializedLayout(uint32_t name, | |
| 503 uintptr_t value, | |
| 504 uintptr_t size, | |
| 505 Binding binding, | |
| 506 Type type, | |
| 507 uint16_t section) | |
| 508 : name(name), | |
| 509 value(value), | |
| 510 size(size), | |
| 511 info((binding << 4) | type), | |
| 512 other(0), | |
| 513 section(section) { | |
| 514 } | |
| 515 | |
| 516 uint32_t name; | |
| 517 uintptr_t value; | |
| 518 uintptr_t size; | |
| 519 uint8_t info; | |
| 520 uint8_t other; | |
| 521 uint16_t section; | |
| 522 }; | |
| 523 #elif defined(V8_TARGET_ARCH_X64) | |
| 524 struct SerializedLayout { | |
| 525 SerializedLayout(uint32_t name, | |
| 526 uintptr_t value, | |
| 527 uintptr_t size, | |
| 528 Binding binding, | |
| 529 Type type, | |
| 530 uint16_t section) | |
| 531 : name(name), | |
| 532 info((binding << 4) | type), | |
| 533 other(0), | |
| 534 section(section), | |
| 535 value(value), | |
| 536 size(size) { | |
| 537 } | |
| 538 | |
| 539 uint32_t name; | |
| 540 uint8_t info; | |
| 541 uint8_t other; | |
| 542 uint16_t section; | |
| 543 uintptr_t value; | |
| 544 uintptr_t size; | |
| 545 }; | |
| 546 #endif | |
| 547 | |
| 548 void Write(Writer::Slot<SerializedLayout> s, StringTable* t) { | |
| 549 // Convert symbol names from strings to indexes in the string table. | |
| 550 s->name = t->Add(name); | |
| 551 s->value = value; | |
| 552 s->size = size; | |
| 553 s->info = info; | |
| 554 s->other = other; | |
| 555 s->section = section; | |
| 556 } | |
| 557 | |
| 558 private: | |
| 559 const char* name; | |
| 560 uintptr_t value; | |
| 561 uintptr_t size; | |
| 562 uint8_t info; | |
| 563 uint8_t other; | |
| 564 uint16_t section; | |
| 565 }; | |
| 566 | |
| 567 | |
| 568 class ELFSymbolTable : public ELFSection { | |
| 569 public: | |
| 570 explicit ELFSymbolTable(const char* name) | |
| 571 : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)), | |
| 572 locals_(1), | |
| 573 globals_(1) { | |
| 574 } | |
| 575 | |
| 576 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) { | |
| 577 w->Align(header->alignment); | |
| 578 int total_symbols = locals_.length() + globals_.length() + 1; | |
| 579 header->offset = w->position(); | |
| 580 | |
| 581 Writer::Slot<ELFSymbol::SerializedLayout> symbols = | |
| 582 w->SlotsHere<ELFSymbol::SerializedLayout>(total_symbols); | |
| 583 | |
| 584 header->size = w->position() - header->offset; | |
| 585 | |
| 586 // String table for this symbol table should follow it in the section table. | |
| 587 StringTable* strtab = | |
| 588 static_cast<StringTable*>(w->elf()->SectionAt(index() + 1)); | |
| 589 strtab->AttachWriter(w); | |
| 590 symbols.at(0).set(ELFSymbol::SerializedLayout(0, | |
| 591 0, | |
| 592 0, | |
| 593 ELFSymbol::BIND_LOCAL, | |
| 594 ELFSymbol::TYPE_NOTYPE, | |
| 595 0)); | |
| 596 WriteSymbolsList(&locals_, symbols.at(1), strtab); | |
| 597 WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab); | |
| 598 strtab->DetachWriter(); | |
| 599 } | |
| 600 | |
| 601 void Add(const ELFSymbol& symbol) { | |
| 602 if (symbol.binding() == ELFSymbol::BIND_LOCAL) { | |
| 603 locals_.Add(symbol); | |
| 604 } else { | |
| 605 globals_.Add(symbol); | |
| 606 } | |
| 607 } | |
| 608 | |
| 609 protected: | |
| 610 virtual void PopulateHeader(Writer::Slot<Header> header) { | |
| 611 ELFSection::PopulateHeader(header); | |
| 612 // We are assuming that string table will follow symbol table. | |
| 613 header->link = index() + 1; | |
| 614 header->info = locals_.length() + 1; | |
| 615 header->entry_size = sizeof(ELFSymbol::SerializedLayout); | |
| 616 } | |
| 617 | |
| 618 private: | |
| 619 void WriteSymbolsList(const ZoneList<ELFSymbol>* src, | |
| 620 Writer::Slot<ELFSymbol::SerializedLayout> dst, | |
| 621 StringTable* strtab) { | |
| 622 for (int i = 0, len = src->length(); | |
| 623 i < len; | |
| 624 i++) { | |
| 625 src->at(i).Write(dst.at(i), strtab); | |
| 626 } | |
| 627 } | |
| 628 | |
| 629 ZoneList<ELFSymbol> locals_; | |
| 630 ZoneList<ELFSymbol> globals_; | |
| 631 }; | |
| 632 | |
| 633 | |
| 634 class CodeDescription BASE_EMBEDDED { | |
| 635 public: | |
| 636 CodeDescription(const char* name, | |
| 637 Code* code, | |
| 638 Handle<Script> script, | |
| 639 GDBJITLineInfo* lineinfo) | |
| 640 : name_(name), code_(code), script_(script), lineinfo_(lineinfo) | |
| 641 { } | |
| 642 | |
| 643 const char* code_name() const { | |
| 644 return name_; | |
| 645 } | |
| 646 | |
| 647 uintptr_t code_size() const { | |
| 648 return code_->instruction_end() - code_->instruction_start(); | |
| 649 } | |
| 650 | |
| 651 uintptr_t code_start() const { | |
| 652 return (uintptr_t)code_->instruction_start(); | |
| 653 } | |
| 654 | |
| 655 bool is_line_info_available() { | |
| 656 return !script_.is_null() && | |
| 657 script_->source()->IsString() && | |
| 658 script_->HasValidSource() && | |
| 659 script_->name()->IsString() && | |
| 660 lineinfo_ != NULL; | |
| 661 } | |
| 662 | |
| 663 GDBJITLineInfo* lineinfo() const { return lineinfo_; } | |
| 664 | |
| 665 SmartPointer<char> filename() { | |
| 666 return String::cast(script_->name())->ToCString(); | |
| 667 } | |
| 668 | |
| 669 int GetScriptLineNumber(int pos) { | |
| 670 return GetScriptLineNumberSafe(script_, pos) + 1; | |
| 671 } | |
| 672 | |
| 673 private: | |
| 674 const char* name_; | |
| 675 Code* code_; | |
| 676 Handle<Script> script_; | |
| 677 GDBJITLineInfo* lineinfo_; | |
| 678 }; | |
| 679 | |
| 680 | |
| 681 static void CreateSymbolsTable(CodeDescription* desc, | |
| 682 ELF* elf, | |
| 683 int text_section_index) { | |
| 684 ELFSymbolTable* symtab = new ELFSymbolTable(".symtab"); | |
| 685 StringTable* strtab = new StringTable(".strtab"); | |
| 686 | |
| 687 // Symbol table should be followed by the linked string table. | |
| 688 elf->AddSection(symtab); | |
| 689 elf->AddSection(strtab); | |
| 690 | |
| 691 symtab->Add(ELFSymbol("V8 Code", | |
| 692 0, | |
| 693 0, | |
| 694 ELFSymbol::BIND_LOCAL, | |
| 695 ELFSymbol::TYPE_FILE, | |
| 696 ELFSection::INDEX_ABSOLUTE)); | |
| 697 | |
| 698 symtab->Add(ELFSymbol(desc->code_name(), | |
| 699 0, | |
| 700 desc->code_size(), | |
| 701 ELFSymbol::BIND_GLOBAL, | |
| 702 ELFSymbol::TYPE_FUNC, | |
| 703 text_section_index)); | |
| 704 } | |
| 705 | |
| 706 | |
| 707 class DebugInfoSection : public ELFSection { | |
| 708 public: | |
| 709 explicit DebugInfoSection(CodeDescription* desc) | |
| 710 : ELFSection(".debug_info", TYPE_PROGBITS, 1), desc_(desc) { } | |
| 711 | |
| 712 bool WriteBody(Writer* w) { | |
| 713 Writer::Slot<uint32_t> size = w->SlotHere<uint32_t>(); | |
| 714 uintptr_t start = w->position(); | |
| 715 w->Write<uint16_t>(2); // DWARF version. | |
| 716 w->Write<uint32_t>(0); // Abbreviation table offset. | |
| 717 w->Write<uint8_t>(sizeof(intptr_t)); | |
| 718 | |
| 719 w->WriteULEB128(1); // Abbreviation code. | |
| 720 w->WriteString(*desc_->filename()); | |
| 721 w->Write<intptr_t>(desc_->code_start()); | |
| 722 w->Write<intptr_t>(desc_->code_start() + desc_->code_size()); | |
| 723 w->Write<uint32_t>(0); | |
| 724 size.set(static_cast<uint32_t>(w->position() - start)); | |
| 725 return true; | |
| 726 } | |
| 727 | |
| 728 private: | |
| 729 CodeDescription* desc_; | |
| 730 }; | |
| 731 | |
| 732 | |
| 733 class DebugAbbrevSection : public ELFSection { | |
| 734 public: | |
| 735 DebugAbbrevSection() : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1) { } | |
| 736 | |
| 737 // DWARF2 standard, figure 14. | |
| 738 enum DWARF2Tags { | |
| 739 DW_TAG_COMPILE_UNIT = 0x11 | |
| 740 }; | |
| 741 | |
| 742 // DWARF2 standard, figure 16. | |
| 743 enum DWARF2ChildrenDetermination { | |
| 744 DW_CHILDREN_NO = 0, | |
| 745 DW_CHILDREN_YES = 1 | |
| 746 }; | |
| 747 | |
| 748 // DWARF standard, figure 17. | |
| 749 enum DWARF2Attribute { | |
| 750 DW_AT_NAME = 0x3, | |
| 751 DW_AT_STMT_LIST = 0x10, | |
| 752 DW_AT_LOW_PC = 0x11, | |
| 753 DW_AT_HIGH_PC = 0x12 | |
| 754 }; | |
| 755 | |
| 756 // DWARF2 standard, figure 19. | |
| 757 enum DWARF2AttributeForm { | |
| 758 DW_FORM_ADDR = 0x1, | |
| 759 DW_FORM_STRING = 0x8, | |
| 760 DW_FORM_DATA4 = 0x6 | |
| 761 }; | |
| 762 | |
| 763 bool WriteBody(Writer* w) { | |
| 764 w->WriteULEB128(1); | |
| 765 w->WriteULEB128(DW_TAG_COMPILE_UNIT); | |
| 766 w->Write<uint8_t>(DW_CHILDREN_NO); | |
| 767 w->WriteULEB128(DW_AT_NAME); | |
| 768 w->WriteULEB128(DW_FORM_STRING); | |
| 769 w->WriteULEB128(DW_AT_LOW_PC); | |
| 770 w->WriteULEB128(DW_FORM_ADDR); | |
| 771 w->WriteULEB128(DW_AT_HIGH_PC); | |
| 772 w->WriteULEB128(DW_FORM_ADDR); | |
| 773 w->WriteULEB128(DW_AT_STMT_LIST); | |
| 774 w->WriteULEB128(DW_FORM_DATA4); | |
| 775 w->WriteULEB128(0); | |
| 776 w->WriteULEB128(0); | |
| 777 w->WriteULEB128(0); | |
| 778 return true; | |
| 779 } | |
| 780 }; | |
| 781 | |
| 782 | |
| 783 class DebugLineSection : public ELFSection { | |
| 784 public: | |
| 785 explicit DebugLineSection(CodeDescription* desc) | |
| 786 : ELFSection(".debug_line", TYPE_PROGBITS, 1), | |
| 787 desc_(desc) { } | |
| 788 | |
| 789 // DWARF2 standard, figure 34. | |
| 790 enum DWARF2Opcodes { | |
| 791 DW_LNS_COPY = 1, | |
| 792 DW_LNS_ADVANCE_PC = 2, | |
| 793 DW_LNS_ADVANCE_LINE = 3, | |
| 794 DW_LNS_SET_FILE = 4, | |
| 795 DW_LNS_SET_COLUMN = 5, | |
| 796 DW_LNS_NEGATE_STMT = 6 | |
| 797 }; | |
| 798 | |
| 799 // DWARF2 standard, figure 35. | |
| 800 enum DWARF2ExtendedOpcode { | |
| 801 DW_LNE_END_SEQUENCE = 1, | |
| 802 DW_LNE_SET_ADDRESS = 2, | |
| 803 DW_LNE_DEFINE_FILE = 3 | |
| 804 }; | |
| 805 | |
| 806 bool WriteBody(Writer* w) { | |
| 807 // Write prologue. | |
| 808 Writer::Slot<uint32_t> total_length = w->SlotHere<uint32_t>(); | |
| 809 uintptr_t start = w->position(); | |
| 810 | |
| 811 w->Write<uint16_t>(2); // Field version. | |
| 812 Writer::Slot<uint32_t> prologue_length = w->SlotHere<uint32_t>(); | |
| 813 uintptr_t prologue_start = w->position(); | |
| 814 w->Write<uint8_t>(1); // Field minimum_instruction_length. | |
| 815 w->Write<uint8_t>(1); // Field default_is_stmt. | |
| 816 w->Write<int8_t>(0); // Field line_base. | |
| 817 w->Write<uint8_t>(2); // Field line_range. | |
| 818 w->Write<uint8_t>(DW_LNS_NEGATE_STMT + 1); // Field opcode_base. | |
| 819 w->Write<uint8_t>(0); // DW_LNS_COPY operands count. | |
| 820 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_PC operands count. | |
| 821 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_LINE operands count. | |
| 822 w->Write<uint8_t>(1); // DW_LNS_SET_FILE operands count. | |
| 823 w->Write<uint8_t>(1); // DW_LNS_SET_COLUMN operands count. | |
| 824 w->Write<uint8_t>(0); // DW_LNS_NEGATE_STMT operands count. | |
| 825 w->Write<uint8_t>(0); // Empty include_directories sequence. | |
| 826 w->WriteString(*desc_->filename()); // File name. | |
| 827 w->WriteULEB128(0); // Current directory. | |
| 828 w->WriteULEB128(0); // Unknown modification time. | |
| 829 w->WriteULEB128(0); // Unknown file size. | |
| 830 w->Write<uint8_t>(0); | |
| 831 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start)); | |
| 832 | |
| 833 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t)); | |
| 834 w->Write<intptr_t>(desc_->code_start()); | |
| 835 | |
| 836 intptr_t pc = 0; | |
| 837 intptr_t line = 1; | |
| 838 bool is_statement = true; | |
| 839 | |
| 840 List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info(); | |
| 841 for (int i = 0; i < pc_info->length(); i++) { | |
| 842 GDBJITLineInfo::PCInfo* info = &pc_info->at(i); | |
| 843 uintptr_t pc_diff = info->pc_ - pc; | |
| 844 ASSERT(info->pc_ >= pc); | |
| 845 if (pc_diff != 0) { | |
| 846 w->Write<uint8_t>(DW_LNS_ADVANCE_PC); | |
| 847 w->WriteSLEB128(pc_diff); | |
| 848 pc += pc_diff; | |
| 849 } | |
| 850 intptr_t line_diff = desc_->GetScriptLineNumber(info->pos_) - line; | |
| 851 if (line_diff != 0) { | |
| 852 w->Write<uint8_t>(DW_LNS_ADVANCE_LINE); | |
| 853 w->WriteSLEB128(line_diff); | |
| 854 line += line_diff; | |
| 855 } | |
| 856 if (is_statement != info->is_statement_) { | |
| 857 w->Write<uint8_t>(DW_LNS_NEGATE_STMT); | |
| 858 is_statement = !is_statement; | |
|
Erik Corry
2011/01/04 14:21:48
How about is_statement = info->is_statement_;
Vyacheslav Egorov (Chromium)
2011/01/18 16:10:42
I want to reflect the meaning of an emitted operat
| |
| 859 } | |
| 860 if (pc_diff != 0 || i == 0) { | |
| 861 w->Write<uint8_t>(DW_LNS_COPY); | |
| 862 } | |
| 863 } | |
| 864 WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0); | |
| 865 total_length.set(static_cast<uint32_t>(w->position() - start)); | |
| 866 return true; | |
| 867 } | |
| 868 | |
| 869 private: | |
| 870 void WriteExtendedOpcode(Writer* w, | |
| 871 DWARF2ExtendedOpcode op, | |
| 872 size_t operands_size) { | |
| 873 w->Write<uint8_t>(0); | |
| 874 w->WriteULEB128(operands_size + 1); | |
| 875 w->Write<uint8_t>(op); | |
| 876 } | |
| 877 | |
| 878 CodeDescription* desc_; | |
| 879 }; | |
| 880 | |
| 881 | |
| 882 static void CreateDWARFSections(CodeDescription* desc, ELF* elf) { | |
| 883 if (desc->is_line_info_available()) { | |
| 884 elf->AddSection(new DebugInfoSection(desc)); | |
| 885 elf->AddSection(new DebugAbbrevSection); | |
| 886 elf->AddSection(new DebugLineSection(desc)); | |
| 887 } | |
| 888 } | |
| 889 | |
| 890 | |
| 891 // ------------------------------------------------------------------- | |
| 892 // GDB JIT Interface declarations copied as is from | |
| 893 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html | |
| 894 extern "C" { | |
| 895 typedef enum { | |
| 896 JIT_NOACTION = 0, | |
| 897 JIT_REGISTER_FN, | |
| 898 JIT_UNREGISTER_FN | |
| 899 } jit_actions_t; | |
| 900 | |
| 901 struct jit_code_entry { | |
| 902 struct jit_code_entry *next_entry; | |
| 903 struct jit_code_entry *prev_entry; | |
| 904 char *symfile_addr; | |
| 905 uint64_t symfile_size; | |
| 906 }; | |
| 907 | |
| 908 struct jit_descriptor { | |
| 909 uint32_t version; | |
| 910 uint32_t action_flag; | |
| 911 struct jit_code_entry *relevant_entry; | |
| 912 struct jit_code_entry *first_entry; | |
| 913 }; | |
| 914 | |
| 915 void __attribute__((noinline)) __jit_debug_register_code() { | |
| 916 __asm__ (""); | |
| 917 } | |
| 918 | |
| 919 struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; | |
| 920 } | |
| 921 | |
| 922 | |
| 923 static jit_code_entry* CreateCodeEntry(byte* symfile_addr, | |
| 924 uintptr_t symfile_size) { | |
| 925 jit_code_entry* entry = static_cast<jit_code_entry*>( | |
| 926 malloc(sizeof(jit_code_entry) + symfile_size)); | |
| 927 | |
| 928 entry->symfile_addr = reinterpret_cast<char*>(entry + 1); | |
| 929 entry->symfile_size = symfile_size; | |
| 930 memcpy(entry->symfile_addr, symfile_addr, symfile_size); | |
| 931 | |
| 932 entry->prev_entry = entry->next_entry = NULL; | |
| 933 | |
| 934 return entry; | |
| 935 } | |
| 936 | |
| 937 | |
| 938 static void DestroyCodeEntry(jit_code_entry* entry) { | |
| 939 free(entry); | |
| 940 } | |
| 941 | |
| 942 | |
| 943 static void RegisterCodeEntry(jit_code_entry* entry) { | |
| 944 entry->next_entry = __jit_debug_descriptor.first_entry; | |
| 945 if (entry->next_entry != NULL) entry->next_entry->prev_entry = entry; | |
| 946 __jit_debug_descriptor.first_entry = | |
| 947 __jit_debug_descriptor.relevant_entry = entry; | |
| 948 | |
| 949 __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; | |
| 950 __jit_debug_register_code(); | |
| 951 } | |
| 952 | |
| 953 | |
| 954 static void UnregisterCodeEntry(jit_code_entry* entry) { | |
| 955 if (entry->prev_entry != NULL) { | |
| 956 entry->prev_entry->next_entry = entry->next_entry; | |
| 957 } else { | |
| 958 __jit_debug_descriptor.first_entry = entry->next_entry; | |
| 959 } | |
| 960 | |
| 961 if (entry->next_entry != NULL) { | |
| 962 entry->next_entry->prev_entry = entry->prev_entry; | |
| 963 } | |
| 964 | |
| 965 __jit_debug_descriptor.relevant_entry = entry; | |
| 966 __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN; | |
| 967 __jit_debug_register_code(); | |
| 968 } | |
| 969 | |
| 970 | |
| 971 static jit_code_entry* CreateELFObject(CodeDescription* desc) { | |
| 972 ZoneScope zone_scope(DELETE_ON_EXIT); | |
| 973 | |
| 974 ELF elf; | |
| 975 Writer w(&elf); | |
| 976 | |
| 977 int text_section_index = elf.AddSection( | |
| 978 new FullHeaderELFSection(".text", | |
| 979 ELFSection::TYPE_NOBITS, | |
| 980 kCodeAlignment, | |
| 981 desc->code_start(), | |
| 982 0, | |
| 983 desc->code_size(), | |
| 984 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC)); | |
| 985 | |
| 986 CreateSymbolsTable(desc, &elf, text_section_index); | |
| 987 | |
| 988 CreateDWARFSections(desc, &elf); | |
| 989 | |
| 990 elf.Write(&w); | |
| 991 | |
| 992 return CreateCodeEntry(w.buffer(), w.position()); | |
| 993 } | |
| 994 | |
| 995 | |
| 996 static bool SameCodeObjects(void* key1, void* key2) { | |
| 997 return key1 == key2; | |
| 998 } | |
| 999 | |
| 1000 | |
| 1001 static HashMap entries(&SameCodeObjects); | |
| 1002 | |
| 1003 | |
| 1004 static uint32_t HashForCodeObject(Code* code) { | |
| 1005 static const uintptr_t kGoldenRatio = 2654435761u; | |
| 1006 uintptr_t hash = reinterpret_cast<uintptr_t>(code->address()); | |
| 1007 return static_cast<uint32_t>((hash >> kCodeAlignmentBits) * kGoldenRatio); | |
| 1008 } | |
| 1009 | |
| 1010 | |
| 1011 static const intptr_t kLineInfoTag = 0x1; | |
| 1012 | |
| 1013 | |
| 1014 static bool IsLineInfoTagged(void* ptr) { | |
| 1015 return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag); | |
| 1016 } | |
| 1017 | |
| 1018 | |
| 1019 static void* TagLineInfo(GDBJITLineInfo* ptr) { | |
| 1020 return reinterpret_cast<void*>( | |
| 1021 reinterpret_cast<intptr_t>(ptr) | kLineInfoTag); | |
| 1022 } | |
| 1023 | |
| 1024 | |
| 1025 static GDBJITLineInfo* UntagLineInfo(void* ptr) { | |
| 1026 return reinterpret_cast<GDBJITLineInfo*>( | |
| 1027 reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag); | |
| 1028 } | |
| 1029 | |
| 1030 | |
| 1031 void GDBJITInterface::AddCode(Handle<String> name, | |
| 1032 Handle<Script> script, | |
| 1033 Handle<Code> code) { | |
| 1034 if (!FLAG_gdbjit) return; | |
| 1035 | |
| 1036 // Force initialization of line_ends array. | |
| 1037 GetScriptLineNumber(script, 0); | |
| 1038 | |
| 1039 if (!name.is_null()) { | |
| 1040 SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS); | |
| 1041 AddCode(*name_cstring, *code, *script); | |
| 1042 } else { | |
| 1043 AddCode("", *code, *script); | |
| 1044 } | |
| 1045 } | |
| 1046 | |
| 1047 | |
| 1048 void GDBJITInterface::AddCode(const char* name, | |
| 1049 Code* code, | |
| 1050 Script* script) { | |
| 1051 if (!FLAG_gdbjit) return; | |
| 1052 AssertNoAllocation no_gc; | |
| 1053 | |
| 1054 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); | |
| 1055 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; | |
| 1056 | |
| 1057 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value); | |
| 1058 CodeDescription code_desc(name, | |
| 1059 code, | |
| 1060 script != NULL ? Handle<Script>(script) | |
| 1061 : Handle<Script>(), | |
| 1062 lineinfo); | |
| 1063 | |
| 1064 if (!FLAG_gdbjit_full && !code_desc.is_line_info_available()) { | |
| 1065 delete lineinfo; | |
| 1066 entries.Remove(code, HashForCodeObject(code)); | |
| 1067 return; | |
| 1068 } | |
| 1069 | |
| 1070 jit_code_entry* entry = CreateELFObject(&code_desc); | |
| 1071 ASSERT(!IsLineInfoTagged(entry)); | |
| 1072 | |
| 1073 delete lineinfo; | |
| 1074 e->value = entry; | |
| 1075 | |
| 1076 RegisterCodeEntry(entry); | |
| 1077 } | |
| 1078 | |
| 1079 | |
| 1080 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, | |
| 1081 const char* name, | |
| 1082 Code* code) { | |
| 1083 if (!FLAG_gdbjit) return; | |
| 1084 | |
| 1085 EmbeddedVector<char, 256> buffer; | |
| 1086 StringBuilder builder(buffer.start(), buffer.length()); | |
| 1087 | |
| 1088 builder.AddString(Tag2String(tag)); | |
| 1089 if ((name != NULL) && (*name != '\0')) { | |
| 1090 builder.AddString(": "); | |
| 1091 builder.AddString(name); | |
| 1092 } else { | |
| 1093 builder.AddFormatted(": code object %p", static_cast<void*>(code)); | |
| 1094 } | |
| 1095 | |
| 1096 AddCode(builder.Finalize(), code); | |
| 1097 } | |
| 1098 | |
| 1099 | |
| 1100 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, | |
| 1101 String* name, | |
| 1102 Code* code) { | |
| 1103 if (!FLAG_gdbjit) return; | |
| 1104 AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code); | |
| 1105 } | |
| 1106 | |
| 1107 | |
| 1108 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, Code* code) { | |
| 1109 if (!FLAG_gdbjit) return; | |
| 1110 | |
| 1111 AddCode(tag, "", code); | |
| 1112 } | |
| 1113 | |
| 1114 | |
| 1115 void GDBJITInterface::RemoveCode(Code* code) { | |
| 1116 if (!FLAG_gdbjit) return; | |
| 1117 | |
| 1118 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), false); | |
| 1119 if (e == NULL) return; | |
| 1120 | |
| 1121 if (IsLineInfoTagged(e->value)) { | |
| 1122 delete UntagLineInfo(e->value); | |
| 1123 } else { | |
| 1124 jit_code_entry* entry = static_cast<jit_code_entry*>(e->value); | |
| 1125 UnregisterCodeEntry(entry); | |
| 1126 DestroyCodeEntry(entry); | |
| 1127 } | |
| 1128 e->value = NULL; | |
| 1129 entries.Remove(code, HashForCodeObject(code)); | |
| 1130 } | |
| 1131 | |
| 1132 | |
| 1133 void GDBJITInterface::RegisterDetailedLineInfo(Code* code, | |
| 1134 GDBJITLineInfo* line_info) { | |
| 1135 ASSERT(!IsLineInfoTagged(line_info)); | |
| 1136 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); | |
| 1137 ASSERT(e->value == NULL); | |
| 1138 e->value = TagLineInfo(line_info); | |
| 1139 } | |
| 1140 | |
| 1141 | |
| 1142 } } // namespace v8::internal | |
| 1143 #endif | |
| OLD | NEW |