disassembler.cc revision 086aeeaae12517475c22695a200be45495516549
1086aeeaae12517475c22695a200be45495516549Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "code-stubs.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h" 33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "disasm.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "disassembler.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h" 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "string-stream.h" 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DISASSEMBLER 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Dump(FILE* f, byte* begin, byte* end) { 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end; pc++) { 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f == NULL) { 48f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch PrintF("%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n", 49f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch reinterpret_cast<intptr_t>(pc), 50f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch pc - begin, 51f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch *pc); 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n", 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<uintptr_t>(pc), pc - begin, *pc); 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass V8NameConverter: public disasm::NameConverter { 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit V8NameConverter(Code* code) : code_(code) {} 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual const char* NameOfAddress(byte* pc) const; 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual const char* NameInCode(byte* addr) const; 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code() const { return code_; } 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code_; 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* V8NameConverter::NameOfAddress(byte* pc) const { 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static v8::internal::EmbeddedVector<char, 128> buffer; 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* name = Builtins::Lookup(pc); 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (name != NULL) { 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(buffer, "%s (%p)", name, pc); 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return buffer.start(); 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (code_ != NULL) { 81d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offs = static_cast<int>(pc - code_->instruction_start()); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // print as code offset, if it seems reasonable 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= offs && offs < code_->instruction_size()) { 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(buffer, "%d (%p)", offs, pc); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return buffer.start(); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return disasm::NameConverter::NameOfAddress(pc); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* V8NameConverter::NameInCode(byte* addr) const { 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The V8NameConverter is used for well known code, so we can "safely" 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // dereference pointers in generated code. 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (code_ != NULL) ? reinterpret_cast<const char*>(addr) : ""; 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void DumpBuffer(FILE* f, char* buff) { 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f == NULL) { 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("%s", buff); 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%s", buff); 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kOutBufferSize = 2048 + String::kMaxShortPrintLength; 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kRelocInfoPosition = 57; 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int DecodeIt(FILE* f, 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const V8NameConverter& converter, 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* begin, 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* end) { 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NoHandleAllocation ha; 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AssertNoAllocation no_alloc; 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReferenceEncoder ref_encoder; 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> decode_buffer; 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* pc = begin; 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block disasm::Disassembler d(converter); 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocIterator* it = NULL; 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (converter.code() != NULL) { 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it = new RelocIterator(converter.code()); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No relocation information when printing code stubs. 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int constants = -1; // no constants being decoded at the start 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (pc < end) { 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First decode instruction so that we know its length. 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (constants > 0) { 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(decode_buffer, 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%08x constant", 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int32_t*>(pc)); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block constants--; 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_const = d.ConstantPoolSizeAt(pc); 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_const >= 0) { 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(decode_buffer, 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%08x constant pool begin", 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int32_t*>(pc)); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block constants = num_const; 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (it != NULL && !it->done() && it->rinfo()->pc() == pc && 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) { 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // raw pointer embedded in code stream, e.g., jump table 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* ptr = *reinterpret_cast<byte**>(pc); 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(decode_buffer, 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%08" V8PRIxPTR " jump table entry %4" V8PRIdPTR, 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ptr, 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ptr - begin); 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decode_buffer[0] = '\0'; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(decode_buffer, pc); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Collect RelocInfo for this instruction (prev_pc .. pc-1) 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<const char*> comments(4); 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<byte*> pcs(1); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<RelocInfo::Mode> rmodes(1); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<intptr_t> datas(1); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (it != NULL) { 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (!it->done() && it->rinfo()->pc() < pc) { 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (RelocInfo::IsComment(it->rinfo()->rmode())) { 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For comments just collect the text. 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block comments.Add(reinterpret_cast<const char*>(it->rinfo()->data())); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For other reloc info collect all data. 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pcs.Add(it->rinfo()->pc()); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rmodes.Add(it->rinfo()->rmode()); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block datas.Add(it->rinfo()->data()); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it->next(); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringBuilder out(out_buffer.start(), out_buffer.length()); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Comments. 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < comments.length(); i++) { 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s\n", comments[i]); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write out comments, resets outp so that we can format the next line. 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DumpBuffer(f, out.Finalize()); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.Reset(); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction address and instruction offset. 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("%p %4d ", prev_pc, prev_pc - begin); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction. 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("%s", decode_buffer.start()); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print all the reloc info for this instruction which are not comments. 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < pcs.length(); i++) { 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Put together the reloc info 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo relocinfo(pcs[i], rmodes[i], datas[i]); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indent the printing of the reloc info. 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i == 0) { 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The first reloc info is printed after the disassembled instruction. 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddPadding(' ', kRelocInfoPosition - out.position()); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Additional reloc infos are printed on separate lines. 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("\n"); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddPadding(' ', kRelocInfoPosition); 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode = relocinfo.rmode(); 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (RelocInfo::IsPosition(rmode)) { 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (RelocInfo::IsStatementPosition(rmode)) { 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; debug: statement %d", relocinfo.data()); 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; debug: position %d", relocinfo.data()); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rmode == RelocInfo::EMBEDDED_OBJECT) { 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapStringAllocator allocator; 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringStream accumulator(&allocator); 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block relocinfo.target_object()->ShortPrint(&accumulator); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmartPointer<const char> obj_name = accumulator.ToCString(); 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; object: %s", *obj_name); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* reference_name = 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ref_encoder.NameOfAddress(*relocinfo.target_reference_address()); 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; external reference (%s)", reference_name); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (RelocInfo::IsCodeTarget(rmode)) { 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; code:"); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rmode == RelocInfo::CONSTRUCT_CALL) { 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" constructor,"); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address()); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Kind kind = code->kind(); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (code->is_inline_cache_stub()) { 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rmode == RelocInfo::CODE_TARGET_CONTEXT) { 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" contextual,"); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InlineCacheState ic_state = code->ic_state(); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s, %s", Code::Kind2String(kind), 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::ICState2String(ic_state)); 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ic_state == MONOMORPHIC) { 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PropertyType type = code->type(); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(", %s", Code::PropertyType2String(type)); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (code->ic_in_loop() == IN_LOOP) { 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(", in_loop"); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (kind == Code::CALL_IC || kind == Code::KEYED_CALL_IC) { 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(", argc = %d", code->arguments_count()); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (kind == Code::STUB) { 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reverse lookup required as the minor key cannot be retrieved 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the code object. 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* obj = Heap::code_stubs()->SlowReverseLookup(code); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (obj != Heap::undefined_value()) { 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(obj->IsSmi()); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the STUB key and extract major and minor key. 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t key = Smi::cast(obj)->value(); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t minor_key = CodeStub::MinorKeyFromKey(key); 26580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen CodeStub::Major major_key = CodeStub::GetMajorKey(code); 26680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(major_key == CodeStub::MajorKeyFromKey(key)); 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s, %s, ", 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Kind2String(kind), 26980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen CodeStub::MajorName(major_key, false)); 27080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (major_key) { 271086aeeaae12517475c22695a200be45495516549Ben Murdoch case CodeStub::CallFunction: { 272086aeeaae12517475c22695a200be45495516549Ben Murdoch int argc = 273086aeeaae12517475c22695a200be45495516549Ben Murdoch CallFunctionStub::ExtractArgcFromMinorKey(minor_key); 274086aeeaae12517475c22695a200be45495516549Ben Murdoch out.AddFormatted("argc = %d", argc); 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 276086aeeaae12517475c22695a200be45495516549Ben Murdoch } 277086aeeaae12517475c22695a200be45495516549Ben Murdoch default: 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("minor: %d", minor_key); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s", Code::Kind2String(kind)); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (rmode == RelocInfo::RUNTIME_ENTRY) { 285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A runtime entry reloinfo might be a deoptimization bailout. 286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address addr = relocinfo.target_address(); 287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int id = Deoptimizer::GetDeoptimizationId(addr, Deoptimizer::EAGER); 288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (id == Deoptimizer::kNotDeoptimizationEntry) { 289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); 290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch out.AddFormatted(" ;; deoptimization bailout %d", id); 292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddString("\n"); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DumpBuffer(f, out.Finalize()); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.Reset(); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete it; 303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return static_cast<int>(pc - begin); 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::Decode(FILE* f, byte* begin, byte* end) { 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8NameConverter defaultConverter(NULL); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return DecodeIt(f, defaultConverter, begin, end); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Called by Code::CodePrint. 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Decode(FILE* f, Code* code) { 315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int decode_size = (code->kind() == Code::OPTIMIZED_FUNCTION) 316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? static_cast<int>(code->safepoint_table_start()) 317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : code->instruction_size(); 318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If there might be a stack check table, stop before reaching it. 319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (code->kind() == Code::FUNCTION) { 320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch decode_size = 321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Min(decode_size, static_cast<int>(code->stack_check_table_start())); 322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch byte* begin = code->instruction_start(); 325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch byte* end = begin + decode_size; 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8NameConverter v8NameConverter(code); 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeIt(f, v8NameConverter, begin, end); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else // ENABLE_DISASSEMBLER 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Dump(FILE* f, byte* begin, byte* end) {} 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::Decode(FILE* f, byte* begin, byte* end) { return 0; } 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Decode(FILE* f, Code* code) {} 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_DISASSEMBLER 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 339