1086aeeaae12517475c22695a200be45495516549Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/disasm.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/disassembler.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/serialize.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/string-stream.h" 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DISASSEMBLER 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Dump(FILE* f, byte* begin, byte* end) { 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end; pc++) { 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f == NULL) { 25f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch PrintF("%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n", 26f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch reinterpret_cast<intptr_t>(pc), 27f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch pc - begin, 28f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch *pc); 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF(f, "%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n", 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<uintptr_t>(pc), pc - begin, *pc); 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass V8NameConverter: public disasm::NameConverter { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit V8NameConverter(Code* code) : code_(code) {} 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual const char* NameOfAddress(byte* pc) const; 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual const char* NameInCode(byte* addr) const; 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code() const { return code_; } 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code_; 4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block EmbeddedVector<char, 128> v8_buffer_; 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* V8NameConverter::NameOfAddress(byte* pc) const { 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name = code_->GetIsolate()->builtins()->Lookup(pc); 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (name != NULL) { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(v8_buffer_, "%s (%p)", name, pc); 5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return v8_buffer_.start(); 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (code_ != NULL) { 58d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offs = static_cast<int>(pc - code_->instruction_start()); 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // print as code offset, if it seems reasonable 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= offs && offs < code_->instruction_size()) { 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(v8_buffer_, "%d (%p)", offs, pc); 6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return v8_buffer_.start(); 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return disasm::NameConverter::NameOfAddress(pc); 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* V8NameConverter::NameInCode(byte* addr) const { 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The V8NameConverter is used for well known code, so we can "safely" 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // dereference pointers in generated code. 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (code_ != NULL) ? reinterpret_cast<const char*>(addr) : ""; 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic void DumpBuffer(FILE* f, StringBuilder* out) { 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f == NULL) { 7969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch PrintF("%s\n", out->Finalize()); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF(f, "%s\n", out->Finalize()); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch out->Reset(); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kOutBufferSize = 2048 + String::kMaxShortPrintLength; 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kRelocInfoPosition = 57; 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int DecodeIt(Isolate* isolate, 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FILE* f, 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const V8NameConverter& converter, 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* begin, 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* end) { 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SealHandleScope shs(isolate); 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DisallowHeapAllocation no_alloc; 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReferenceEncoder ref_encoder(isolate); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> decode_buffer; 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; 10169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch StringBuilder out(out_buffer.start(), out_buffer.length()); 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* pc = begin; 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block disasm::Disassembler d(converter); 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocIterator* it = NULL; 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (converter.code() != NULL) { 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it = new RelocIterator(converter.code()); 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No relocation information when printing code stubs. 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int constants = -1; // no constants being decoded at the start 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (pc < end) { 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First decode instruction so that we know its length. 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (constants > 0) { 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(decode_buffer, 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%08x constant", 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *reinterpret_cast<int32_t*>(pc)); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block constants--; 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_const = d.ConstantPoolSizeAt(pc); 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_const >= 0) { 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(decode_buffer, 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%08x constant pool begin", 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *reinterpret_cast<int32_t*>(pc)); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block constants = num_const; 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (it != NULL && !it->done() && it->rinfo()->pc() == pc && 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) { 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // raw pointer embedded in code stream, e.g., jump table 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* ptr = *reinterpret_cast<byte**>(pc); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(decode_buffer, 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%08" V8PRIxPTR " jump table entry %4" V8PRIdPTR, 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<intptr_t>(ptr), 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ptr - begin); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decode_buffer[0] = '\0'; 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(decode_buffer, pc); 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Collect RelocInfo for this instruction (prev_pc .. pc-1) 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<const char*> comments(4); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<byte*> pcs(1); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<RelocInfo::Mode> rmodes(1); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<intptr_t> datas(1); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (it != NULL) { 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (!it->done() && it->rinfo()->pc() < pc) { 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (RelocInfo::IsComment(it->rinfo()->rmode())) { 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For comments just collect the text. 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block comments.Add(reinterpret_cast<const char*>(it->rinfo()->data())); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For other reloc info collect all data. 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pcs.Add(it->rinfo()->pc()); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rmodes.Add(it->rinfo()->rmode()); 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block datas.Add(it->rinfo()->data()); 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it->next(); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Comments. 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < comments.length(); i++) { 16669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch out.AddFormatted(" %s", comments[i]); 16769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DumpBuffer(f, &out); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction address and instruction offset. 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("%p %4d ", prev_pc, prev_pc - begin); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction. 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("%s", decode_buffer.start()); 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print all the reloc info for this instruction which are not comments. 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < pcs.length(); i++) { 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Put together the reloc info 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], converter.code()); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indent the printing of the reloc info. 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i == 0) { 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The first reloc info is printed after the disassembled instruction. 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddPadding(' ', kRelocInfoPosition - out.position()); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Additional reloc infos are printed on separate lines. 18769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DumpBuffer(f, &out); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddPadding(' ', kRelocInfoPosition); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode = relocinfo.rmode(); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (RelocInfo::IsPosition(rmode)) { 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (RelocInfo::IsStatementPosition(rmode)) { 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; debug: statement %d", relocinfo.data()); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; debug: position %d", relocinfo.data()); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rmode == RelocInfo::EMBEDDED_OBJECT) { 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapStringAllocator allocator; 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringStream accumulator(&allocator); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block relocinfo.target_object()->ShortPrint(&accumulator); 202589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SmartArrayPointer<const char> obj_name = accumulator.ToCString(); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out.AddFormatted(" ;; object: %s", obj_name.get()); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* reference_name = 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ref_encoder.NameOfAddress(relocinfo.target_reference()); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; external reference (%s)", reference_name); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (RelocInfo::IsCodeTarget(rmode)) { 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; code:"); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rmode == RelocInfo::CONSTRUCT_CALL) { 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" constructor,"); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address()); 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Kind kind = code->kind(); 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (code->is_inline_cache_stub()) { 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (kind == Code::LOAD_IC && 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadICState::GetContextualMode(code->extra_ic_state()) == 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CONTEXTUAL) { 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" contextual,"); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InlineCacheState ic_state = code->ic_state(); 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s, %s", Code::Kind2String(kind), 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::ICState2String(ic_state)); 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ic_state == MONOMORPHIC) { 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::StubType type = code->type(); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out.AddFormatted(", %s", Code::StubType2String(type)); 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (kind == Code::STUB || kind == Code::HANDLER) { 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the STUB key and extract major and minor key. 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t key = code->stub_key(); 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t minor_key = CodeStub::MinorKeyFromKey(key); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeStub::Major major_key = CodeStub::GetMajorKey(code); 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(major_key == CodeStub::MajorKeyFromKey(key)); 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out.AddFormatted(" %s, %s, ", Code::Kind2String(kind), 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeStub::MajorName(major_key, false)); 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (major_key) { 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CodeStub::CallFunction: { 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int argc = CallFunctionStub::ExtractArgcFromMinorKey(minor_key); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out.AddFormatted("argc = %d", argc); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out.AddFormatted("minor: %d", minor_key); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s", Code::Kind2String(kind)); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { 249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out.AddFormatted(" (id = %d)", static_cast<int>(relocinfo.data())); 250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (RelocInfo::IsRuntimeEntry(rmode) && 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->deoptimizer_data() != NULL) { 253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A runtime entry reloinfo might be a deoptimization bailout. 254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address addr = relocinfo.target_address(); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int id = Deoptimizer::GetDeoptimizationId(isolate, 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addr, 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::EAGER); 258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (id == Deoptimizer::kNotDeoptimizationEntry) { 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch id = Deoptimizer::GetDeoptimizationId(isolate, 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addr, 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::LAZY); 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (id == Deoptimizer::kNotDeoptimizationEntry) { 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch id = Deoptimizer::GetDeoptimizationId(isolate, 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addr, 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::SOFT); 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (id == Deoptimizer::kNotDeoptimizationEntry) { 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out.AddFormatted(" ;; soft deoptimization bailout %d", id); 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out.AddFormatted(" ;; lazy deoptimization bailout %d", id); 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch out.AddFormatted(" ;; deoptimization bailout %d", id); 276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 28169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DumpBuffer(f, &out); 28269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 28369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 28469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Emit comments following the last instruction (if any). 28569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (it != NULL) { 28669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch for ( ; !it->done(); it->next()) { 28769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (RelocInfo::IsComment(it->rinfo()->rmode())) { 28869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch out.AddFormatted(" %s", 28969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch reinterpret_cast<const char*>(it->rinfo()->data())); 29069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DumpBuffer(f, &out); 29169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 29269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete it; 296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return static_cast<int>(pc - begin); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Disassembler::Decode(Isolate* isolate, FILE* f, byte* begin, byte* end) { 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8NameConverter defaultConverter(NULL); 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return DecodeIt(isolate, f, defaultConverter, begin, end); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Called by Code::CodePrint. 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Decode(FILE* f, Code* code) { 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = code->GetIsolate(); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int decode_size = code->is_crankshafted() 3101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ? static_cast<int>(code->safepoint_table_offset()) 311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : code->instruction_size(); 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If there might be a back edge table, stop before reaching it. 313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (code->kind() == Code::FUNCTION) { 314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch decode_size = 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Min(decode_size, static_cast<int>(code->back_edge_table_offset())); 316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch byte* begin = code->instruction_start(); 319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch byte* end = begin + decode_size; 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8NameConverter v8NameConverter(code); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeIt(isolate, f, v8NameConverter, begin, end); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else // ENABLE_DISASSEMBLER 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Dump(FILE* f, byte* begin, byte* end) {} 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Disassembler::Decode(Isolate* isolate, FILE* f, byte* begin, byte* end) { 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Decode(FILE* f, Code* code) {} 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_DISASSEMBLER 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 337