disassembler.cc revision 8b112d2025046f85ef7f6be087c6129c872ebad2
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" 318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.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_; 6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block EmbeddedVector<char, 128> v8_buffer_; 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* V8NameConverter::NameOfAddress(byte* pc) const { 7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const char* name = Isolate::Current()->builtins()->Lookup(pc); 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (name != NULL) { 7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block OS::SNPrintF(v8_buffer_, "%s (%p)", name, pc); 7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return v8_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()) { 8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block OS::SNPrintF(v8_buffer_, "%d (%p)", offs, pc); 8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return v8_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; 11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = HEAP; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> decode_buffer; 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* pc = begin; 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block disasm::Disassembler d(converter); 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocIterator* it = NULL; 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (converter.code() != NULL) { 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it = new RelocIterator(converter.code()); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No relocation information when printing code stubs. 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int constants = -1; // no constants being decoded at the start 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (pc < end) { 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First decode instruction so that we know its length. 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (constants > 0) { 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(decode_buffer, 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%08x constant", 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int32_t*>(pc)); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block constants--; 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_const = d.ConstantPoolSizeAt(pc); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_const >= 0) { 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(decode_buffer, 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%08x constant pool begin", 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int32_t*>(pc)); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block constants = num_const; 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (it != NULL && !it->done() && it->rinfo()->pc() == pc && 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) { 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // raw pointer embedded in code stream, e.g., jump table 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* ptr = *reinterpret_cast<byte**>(pc); 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(decode_buffer, 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%08" V8PRIxPTR " jump table entry %4" V8PRIdPTR, 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ptr, 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ptr - begin); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decode_buffer[0] = '\0'; 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(decode_buffer, pc); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Collect RelocInfo for this instruction (prev_pc .. pc-1) 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<const char*> comments(4); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<byte*> pcs(1); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<RelocInfo::Mode> rmodes(1); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<intptr_t> datas(1); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (it != NULL) { 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (!it->done() && it->rinfo()->pc() < pc) { 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (RelocInfo::IsComment(it->rinfo()->rmode())) { 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For comments just collect the text. 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block comments.Add(reinterpret_cast<const char*>(it->rinfo()->data())); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For other reloc info collect all data. 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pcs.Add(it->rinfo()->pc()); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rmodes.Add(it->rinfo()->rmode()); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block datas.Add(it->rinfo()->data()); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it->next(); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringBuilder out(out_buffer.start(), out_buffer.length()); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Comments. 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < comments.length(); i++) { 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s\n", comments[i]); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write out comments, resets outp so that we can format the next line. 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DumpBuffer(f, out.Finalize()); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.Reset(); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction address and instruction offset. 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("%p %4d ", prev_pc, prev_pc - begin); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction. 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("%s", decode_buffer.start()); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print all the reloc info for this instruction which are not comments. 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < pcs.length(); i++) { 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Put together the reloc info 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo relocinfo(pcs[i], rmodes[i], datas[i]); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indent the printing of the reloc info. 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i == 0) { 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The first reloc info is printed after the disassembled instruction. 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddPadding(' ', kRelocInfoPosition - out.position()); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Additional reloc infos are printed on separate lines. 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("\n"); 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddPadding(' ', kRelocInfoPosition); 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode = relocinfo.rmode(); 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (RelocInfo::IsPosition(rmode)) { 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (RelocInfo::IsStatementPosition(rmode)) { 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; debug: statement %d", relocinfo.data()); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; debug: position %d", relocinfo.data()); 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rmode == RelocInfo::EMBEDDED_OBJECT) { 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HeapStringAllocator allocator; 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringStream accumulator(&allocator); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block relocinfo.target_object()->ShortPrint(&accumulator); 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SmartPointer<const char> obj_name = accumulator.ToCString(); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; object: %s", *obj_name); 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* reference_name = 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ref_encoder.NameOfAddress(*relocinfo.target_reference_address()); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; external reference (%s)", reference_name); 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (RelocInfo::IsCodeTarget(rmode)) { 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; code:"); 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rmode == RelocInfo::CONSTRUCT_CALL) { 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" constructor,"); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address()); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Kind kind = code->kind(); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (code->is_inline_cache_stub()) { 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rmode == RelocInfo::CODE_TARGET_CONTEXT) { 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" contextual,"); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InlineCacheState ic_state = code->ic_state(); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s, %s", Code::Kind2String(kind), 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::ICState2String(ic_state)); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ic_state == MONOMORPHIC) { 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PropertyType type = code->type(); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(", %s", Code::PropertyType2String(type)); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (code->ic_in_loop() == IN_LOOP) { 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(", in_loop"); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (kind == Code::CALL_IC || kind == Code::KEYED_CALL_IC) { 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(", argc = %d", code->arguments_count()); 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (kind == Code::STUB) { 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reverse lookup required as the minor key cannot be retrieved 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the code object. 26044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Object* obj = heap->code_stubs()->SlowReverseLookup(code); 26144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (obj != heap->undefined_value()) { 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(obj->IsSmi()); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the STUB key and extract major and minor key. 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t key = Smi::cast(obj)->value(); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t minor_key = CodeStub::MinorKeyFromKey(key); 26680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen CodeStub::Major major_key = CodeStub::GetMajorKey(code); 26780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(major_key == CodeStub::MajorKeyFromKey(key)); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s, %s, ", 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Kind2String(kind), 27080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen CodeStub::MajorName(major_key, false)); 27180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (major_key) { 272086aeeaae12517475c22695a200be45495516549Ben Murdoch case CodeStub::CallFunction: { 273086aeeaae12517475c22695a200be45495516549Ben Murdoch int argc = 274086aeeaae12517475c22695a200be45495516549Ben Murdoch CallFunctionStub::ExtractArgcFromMinorKey(minor_key); 275086aeeaae12517475c22695a200be45495516549Ben Murdoch out.AddFormatted("argc = %d", argc); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 277086aeeaae12517475c22695a200be45495516549Ben Murdoch } 278086aeeaae12517475c22695a200be45495516549Ben Murdoch default: 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("minor: %d", minor_key); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s", Code::Kind2String(kind)); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else if (rmode == RelocInfo::RUNTIME_ENTRY && 2868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Isolate::Current()->deoptimizer_data() != NULL) { 287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A runtime entry reloinfo might be a deoptimization bailout. 288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address addr = relocinfo.target_address(); 289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int id = Deoptimizer::GetDeoptimizationId(addr, Deoptimizer::EAGER); 290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (id == Deoptimizer::kNotDeoptimizationEntry) { 291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); 292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch out.AddFormatted(" ;; deoptimization bailout %d", id); 294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddString("\n"); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DumpBuffer(f, out.Finalize()); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.Reset(); 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete it; 305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return static_cast<int>(pc - begin); 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::Decode(FILE* f, byte* begin, byte* end) { 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8NameConverter defaultConverter(NULL); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return DecodeIt(f, defaultConverter, begin, end); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Called by Code::CodePrint. 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Decode(FILE* f, Code* code) { 317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int decode_size = (code->kind() == Code::OPTIMIZED_FUNCTION) 3181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ? static_cast<int>(code->safepoint_table_offset()) 319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : code->instruction_size(); 320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If there might be a stack check table, stop before reaching it. 321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (code->kind() == Code::FUNCTION) { 322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch decode_size = 3231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Min(decode_size, static_cast<int>(code->stack_check_table_offset())); 324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch byte* begin = code->instruction_start(); 327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch byte* end = begin + decode_size; 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8NameConverter v8NameConverter(code); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeIt(f, v8NameConverter, begin, end); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else // ENABLE_DISASSEMBLER 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Dump(FILE* f, byte* begin, byte* end) {} 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::Decode(FILE* f, byte* begin, byte* end) { return 0; } 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Decode(FILE* f, Code* code) {} 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_DISASSEMBLER 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 341