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 10069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic void DumpBuffer(FILE* f, StringBuilder* out) { 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f == NULL) { 10269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch PrintF("%s\n", out->Finalize()); 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 10469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch fprintf(f, "%s\n", out->Finalize()); 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch out->Reset(); 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 11069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kOutBufferSize = 2048 + String::kMaxShortPrintLength; 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kRelocInfoPosition = 57; 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int DecodeIt(FILE* f, 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const V8NameConverter& converter, 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* begin, 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* end) { 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NoHandleAllocation ha; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AssertNoAllocation no_alloc; 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReferenceEncoder ref_encoder; 12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = HEAP; 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> decode_buffer; 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; 12569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch StringBuilder out(out_buffer.start(), out_buffer.length()); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* pc = begin; 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block disasm::Disassembler d(converter); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocIterator* it = NULL; 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (converter.code() != NULL) { 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it = new RelocIterator(converter.code()); 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No relocation information when printing code stubs. 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int constants = -1; // no constants being decoded at the start 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (pc < end) { 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First decode instruction so that we know its length. 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (constants > 0) { 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(decode_buffer, 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%08x constant", 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int32_t*>(pc)); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block constants--; 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_const = d.ConstantPoolSizeAt(pc); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_const >= 0) { 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(decode_buffer, 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%08x constant pool begin", 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int32_t*>(pc)); 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block constants = num_const; 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (it != NULL && !it->done() && it->rinfo()->pc() == pc && 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) { 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // raw pointer embedded in code stream, e.g., jump table 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* ptr = *reinterpret_cast<byte**>(pc); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(decode_buffer, 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%08" V8PRIxPTR " jump table entry %4" V8PRIdPTR, 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ptr, 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ptr - begin); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += 4; 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decode_buffer[0] = '\0'; 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(decode_buffer, pc); 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Collect RelocInfo for this instruction (prev_pc .. pc-1) 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<const char*> comments(4); 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<byte*> pcs(1); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<RelocInfo::Mode> rmodes(1); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<intptr_t> datas(1); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (it != NULL) { 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (!it->done() && it->rinfo()->pc() < pc) { 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (RelocInfo::IsComment(it->rinfo()->rmode())) { 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For comments just collect the text. 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block comments.Add(reinterpret_cast<const char*>(it->rinfo()->data())); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For other reloc info collect all data. 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pcs.Add(it->rinfo()->pc()); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rmodes.Add(it->rinfo()->rmode()); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block datas.Add(it->rinfo()->data()); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it->next(); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Comments. 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < comments.length(); i++) { 19069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch out.AddFormatted(" %s", comments[i]); 19169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DumpBuffer(f, &out); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 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 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], NULL); 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. 21169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DumpBuffer(f, &out); 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); 226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SmartArrayPointer<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 } 2507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (kind == Code::CALL_IC || kind == Code::KEYED_CALL_IC) { 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(", argc = %d", code->arguments_count()); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (kind == Code::STUB) { 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reverse lookup required as the minor key cannot be retrieved 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // from the code object. 25644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Object* obj = heap->code_stubs()->SlowReverseLookup(code); 25744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (obj != heap->undefined_value()) { 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(obj->IsSmi()); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the STUB key and extract major and minor key. 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t key = Smi::cast(obj)->value(); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t minor_key = CodeStub::MinorKeyFromKey(key); 26280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen CodeStub::Major major_key = CodeStub::GetMajorKey(code); 26380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(major_key == CodeStub::MajorKeyFromKey(key)); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s, %s, ", 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Kind2String(kind), 26680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen CodeStub::MajorName(major_key, false)); 26780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (major_key) { 268086aeeaae12517475c22695a200be45495516549Ben Murdoch case CodeStub::CallFunction: { 269086aeeaae12517475c22695a200be45495516549Ben Murdoch int argc = 270086aeeaae12517475c22695a200be45495516549Ben Murdoch CallFunctionStub::ExtractArgcFromMinorKey(minor_key); 271086aeeaae12517475c22695a200be45495516549Ben Murdoch out.AddFormatted("argc = %d", argc); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 273086aeeaae12517475c22695a200be45495516549Ben Murdoch } 274086aeeaae12517475c22695a200be45495516549Ben Murdoch default: 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted("minor: %d", minor_key); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" %s", Code::Kind2String(kind)); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { 282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out.AddFormatted(" (id = %d)", static_cast<int>(relocinfo.data())); 283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else if (rmode == RelocInfo::RUNTIME_ENTRY && 2858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Isolate::Current()->deoptimizer_data() != NULL) { 286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A runtime entry reloinfo might be a deoptimization bailout. 287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address addr = relocinfo.target_address(); 288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int id = Deoptimizer::GetDeoptimizationId(addr, Deoptimizer::EAGER); 289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (id == Deoptimizer::kNotDeoptimizationEntry) { 290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); 291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch out.AddFormatted(" ;; deoptimization bailout %d", id); 293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 29869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DumpBuffer(f, &out); 29969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 30069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 30169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Emit comments following the last instruction (if any). 30269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (it != NULL) { 30369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch for ( ; !it->done(); it->next()) { 30469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (RelocInfo::IsComment(it->rinfo()->rmode())) { 30569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch out.AddFormatted(" %s", 30669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch reinterpret_cast<const char*>(it->rinfo()->data())); 30769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DumpBuffer(f, &out); 30869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 30969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete it; 313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return static_cast<int>(pc - begin); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::Decode(FILE* f, byte* begin, byte* end) { 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8NameConverter defaultConverter(NULL); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return DecodeIt(f, defaultConverter, begin, end); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Called by Code::CodePrint. 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Decode(FILE* f, Code* code) { 325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int decode_size = (code->kind() == Code::OPTIMIZED_FUNCTION) 3261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ? static_cast<int>(code->safepoint_table_offset()) 327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : code->instruction_size(); 328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If there might be a stack check table, stop before reaching it. 329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (code->kind() == Code::FUNCTION) { 330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch decode_size = 3311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Min(decode_size, static_cast<int>(code->stack_check_table_offset())); 332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch byte* begin = code->instruction_start(); 335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch byte* end = begin + decode_size; 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8NameConverter v8NameConverter(code); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeIt(f, v8NameConverter, begin, end); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else // ENABLE_DISASSEMBLER 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Dump(FILE* f, byte* begin, byte* end) {} 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::Decode(FILE* f, byte* begin, byte* end) { return 0; } 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Decode(FILE* f, Code* code) {} 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_DISASSEMBLER 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 349