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
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/disassembler.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <memory>
8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/assembler-inl.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/disasm.h"
1513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/ic/ic.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h"
1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/snapshot/serializer-common.h"
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/string-stream.h"
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DISASSEMBLER
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass V8NameConverter: public disasm::NameConverter {
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit V8NameConverter(Code* code) : code_(code) {}
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual const char* NameOfAddress(byte* pc) const;
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual const char* NameInCode(byte* addr) const;
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code() const { return code_; }
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code_;
3444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  EmbeddedVector<char, 128> v8_buffer_;
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* V8NameConverter::NameOfAddress(byte* pc) const {
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const char* name =
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      code_ == NULL ? NULL : code_->GetIsolate()->builtins()->Lookup(pc);
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (name != NULL) {
4413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    SNPrintF(v8_buffer_, "%s  (%p)", name, static_cast<void*>(pc));
4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return v8_buffer_.start();
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (code_ != NULL) {
49d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int offs = static_cast<int>(pc - code_->instruction_start());
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // print as code offset, if it seems reasonable
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (0 <= offs && offs < code_->instruction_size()) {
5213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      SNPrintF(v8_buffer_, "%d  (%p)", offs, static_cast<void*>(pc));
5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return v8_buffer_.start();
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return disasm::NameConverter::NameOfAddress(pc);
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* V8NameConverter::NameInCode(byte* addr) const {
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The V8NameConverter is used for well known code, so we can "safely"
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // dereference pointers in generated code.
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return (code_ != NULL) ? reinterpret_cast<const char*>(addr) : "";
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void DumpBuffer(std::ostream* os, StringBuilder* out) {
69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  (*os) << out->Finalize() << std::endl;
7069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  out->Reset();
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kOutBufferSize = 2048 + String::kMaxShortPrintLength;
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kRelocInfoPosition = 57;
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic int DecodeIt(Isolate* isolate, std::ostream* os,
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                    const V8NameConverter& converter, byte* begin, byte* end) {
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SealHandleScope shs(isolate);
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_alloc;
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReferenceEncoder ref_encoder(isolate);
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::EmbeddedVector<char, 128> decode_buffer;
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer;
8569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  StringBuilder out(out_buffer.start(), out_buffer.length());
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* pc = begin;
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  disasm::Disassembler d(converter);
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RelocIterator* it = NULL;
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (converter.code() != NULL) {
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    it = new RelocIterator(converter.code());
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No relocation information when printing code stubs.
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int constants = -1;  // no constants being decoded at the start
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (pc < end) {
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // First decode instruction so that we know its length.
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* prev_pc = pc;
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (constants > 0) {
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SNPrintF(decode_buffer,
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "%08x       constant",
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               *reinterpret_cast<int32_t*>(pc));
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      constants--;
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      pc += 4;
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int num_const = d.ConstantPoolSizeAt(pc);
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (num_const >= 0) {
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SNPrintF(decode_buffer,
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 "%08x       constant pool begin (num_const = %d)",
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 *reinterpret_cast<int32_t*>(pc), num_const);
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        constants = num_const;
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        pc += 4;
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (it != NULL && !it->done() && it->rinfo()->pc() == pc &&
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) {
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // raw pointer embedded in code stream, e.g., jump table
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte* ptr = *reinterpret_cast<byte**>(pc);
117bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        SNPrintF(
118bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            decode_buffer, "%08" V8PRIxPTR "      jump table entry %4" PRIuS,
119bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            reinterpret_cast<intptr_t>(ptr), static_cast<size_t>(ptr - begin));
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        pc += sizeof(ptr);
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        decode_buffer[0] = '\0';
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        pc += d.InstructionDecode(decode_buffer, pc);
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Collect RelocInfo for this instruction (prev_pc .. pc-1)
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    List<const char*> comments(4);
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    List<byte*> pcs(1);
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    List<RelocInfo::Mode> rmodes(1);
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    List<intptr_t> datas(1);
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (it != NULL) {
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      while (!it->done() && it->rinfo()->pc() < pc) {
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (RelocInfo::IsComment(it->rinfo()->rmode())) {
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // For comments just collect the text.
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          comments.Add(reinterpret_cast<const char*>(it->rinfo()->data()));
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // For other reloc info collect all data.
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          pcs.Add(it->rinfo()->pc());
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          rmodes.Add(it->rinfo()->rmode());
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          datas.Add(it->rinfo()->data());
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        it->next();
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Comments.
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < comments.length(); i++) {
14969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      out.AddFormatted("                  %s", comments[i]);
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DumpBuffer(os, &out);
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Instruction address and instruction offset.
15413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    out.AddFormatted("%p  %4" V8PRIdPTRDIFF "  ", static_cast<void*>(prev_pc),
15513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                     prev_pc - begin);
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Instruction.
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    out.AddFormatted("%s", decode_buffer.start());
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Print all the reloc info for this instruction which are not comments.
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < pcs.length(); i++) {
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Put together the reloc info
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      RelocInfo relocinfo(isolate, pcs[i], rmodes[i], datas[i],
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          converter.code());
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Indent the printing of the reloc info.
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (i == 0) {
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // The first reloc info is printed after the disassembled instruction.
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        out.AddPadding(' ', kRelocInfoPosition - out.position());
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Additional reloc infos are printed on separate lines.
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DumpBuffer(os, &out);
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        out.AddPadding(' ', kRelocInfoPosition);
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RelocInfo::Mode rmode = relocinfo.rmode();
177c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) {
178c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        out.AddFormatted("    ;; debug: deopt position, script offset '%d'",
179c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                         static_cast<int>(relocinfo.data()));
180c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      } else if (rmode == RelocInfo::DEOPT_INLINING_ID) {
181c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        out.AddFormatted("    ;; debug: deopt position, inlining id '%d'",
182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                         static_cast<int>(relocinfo.data()));
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (rmode == RelocInfo::DEOPT_REASON) {
184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DeoptimizeReason reason =
185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            static_cast<DeoptimizeReason>(relocinfo.data());
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        out.AddFormatted("    ;; debug: deopt reason '%s'",
187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                         DeoptimizeReasonToString(reason));
188bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else if (rmode == RelocInfo::DEOPT_ID) {
189bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        out.AddFormatted("    ;; debug: deopt index %d",
190bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                         static_cast<int>(relocinfo.data()));
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (rmode == RelocInfo::EMBEDDED_OBJECT) {
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        HeapStringAllocator allocator;
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        StringStream accumulator(&allocator);
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        relocinfo.target_object()->ShortPrint(&accumulator);
195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        std::unique_ptr<char[]> obj_name = accumulator.ToCString();
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        out.AddFormatted("    ;; object: %s", obj_name.get());
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        const char* reference_name = ref_encoder.NameOfAddress(
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            isolate, relocinfo.target_external_reference());
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        out.AddFormatted("    ;; external reference (%s)", reference_name);
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (RelocInfo::IsCodeTarget(rmode)) {
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        out.AddFormatted("    ;; code:");
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address());
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Code::Kind kind = code->kind();
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (code->is_inline_cache_stub()) {
20613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          out.AddFormatted(" %s", Code::Kind2String(kind));
20713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          if (!IC::ICUseVector(kind)) {
20813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            InlineCacheState ic_state = IC::StateFromCode(code);
20913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            out.AddFormatted(" %s", Code::ICState2String(ic_state));
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (kind == Code::STUB || kind == Code::HANDLER) {
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Get the STUB key and extract major and minor key.
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          uint32_t key = code->stub_key();
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          uint32_t minor_key = CodeStub::MinorKeyFromKey(key);
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          CodeStub::Major major_key = CodeStub::GetMajorKey(code);
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          DCHECK(major_key == CodeStub::MajorKeyFromKey(key));
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          out.AddFormatted(" %s, %s, ", Code::Kind2String(kind),
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           CodeStub::MajorName(major_key));
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          out.AddFormatted("minor: %d", minor_key);
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          out.AddFormatted(" %s", Code::Kind2String(kind));
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          out.AddFormatted(" (id = %d)", static_cast<int>(relocinfo.data()));
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (RelocInfo::IsRuntimeEntry(rmode) &&
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 isolate->deoptimizer_data() != NULL) {
228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // A runtime entry reloinfo might be a deoptimization bailout.
229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Address addr = relocinfo.target_address();
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int id = Deoptimizer::GetDeoptimizationId(isolate,
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  addr,
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  Deoptimizer::EAGER);
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (id == Deoptimizer::kNotDeoptimizationEntry) {
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          id = Deoptimizer::GetDeoptimizationId(isolate,
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                addr,
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Deoptimizer::LAZY);
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (id == Deoptimizer::kNotDeoptimizationEntry) {
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            id = Deoptimizer::GetDeoptimizationId(isolate,
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  addr,
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  Deoptimizer::SOFT);
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            if (id == Deoptimizer::kNotDeoptimizationEntry) {
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              out.AddFormatted("    ;; %s", RelocInfo::RelocModeName(rmode));
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            } else {
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              out.AddFormatted("    ;; soft deoptimization bailout %d", id);
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            }
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            out.AddFormatted("    ;; lazy deoptimization bailout %d", id);
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          out.AddFormatted("    ;; deoptimization bailout %d", id);
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        out.AddFormatted("    ;; %s", RelocInfo::RelocModeName(rmode));
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DumpBuffer(os, &out);
25769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
25869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
25969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Emit comments following the last instruction (if any).
26069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (it != NULL) {
26169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    for ( ; !it->done(); it->next()) {
26269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (RelocInfo::IsComment(it->rinfo()->rmode())) {
26369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        out.AddFormatted("                  %s",
26469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                         reinterpret_cast<const char*>(it->rinfo()->data()));
265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DumpBuffer(os, &out);
26669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
26769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  delete it;
271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return static_cast<int>(pc - begin);
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierint Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin,
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         byte* end, Code* code) {
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8NameConverter v8NameConverter(code);
278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return DecodeIt(isolate, os, v8NameConverter, begin, end);
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else  // ENABLE_DISASSEMBLER
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierint Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin,
284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         byte* end, Code* code) {
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return 0;
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // ENABLE_DISASSEMBLER
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
292