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