V8 Project
disassembler.cc
Go to the documentation of this file.
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/v8.h"
6 
7 #include "src/code-stubs.h"
8 #include "src/codegen.h"
9 #include "src/debug.h"
10 #include "src/deoptimizer.h"
11 #include "src/disasm.h"
12 #include "src/disassembler.h"
13 #include "src/macro-assembler.h"
14 #include "src/serialize.h"
15 #include "src/string-stream.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 #ifdef ENABLE_DISASSEMBLER
21 
22 class V8NameConverter: public disasm::NameConverter {
23  public:
24  explicit V8NameConverter(Code* code) : code_(code) {}
25  virtual const char* NameOfAddress(byte* pc) const;
26  virtual const char* NameInCode(byte* addr) const;
27  Code* code() const { return code_; }
28  private:
29  Code* code_;
30 
31  EmbeddedVector<char, 128> v8_buffer_;
32 };
33 
34 
35 const char* V8NameConverter::NameOfAddress(byte* pc) const {
36  const char* name = code_->GetIsolate()->builtins()->Lookup(pc);
37  if (name != NULL) {
38  SNPrintF(v8_buffer_, "%s (%p)", name, pc);
39  return v8_buffer_.start();
40  }
41 
42  if (code_ != NULL) {
43  int offs = static_cast<int>(pc - code_->instruction_start());
44  // print as code offset, if it seems reasonable
45  if (0 <= offs && offs < code_->instruction_size()) {
46  SNPrintF(v8_buffer_, "%d (%p)", offs, pc);
47  return v8_buffer_.start();
48  }
49  }
50 
52 }
53 
54 
55 const char* V8NameConverter::NameInCode(byte* addr) const {
56  // The V8NameConverter is used for well known code, so we can "safely"
57  // dereference pointers in generated code.
58  return (code_ != NULL) ? reinterpret_cast<const char*>(addr) : "";
59 }
60 
61 
62 static void DumpBuffer(OStream* os, StringBuilder* out) {
63  (*os) << out->Finalize() << endl;
64  out->Reset();
65 }
66 
67 
68 static const int kOutBufferSize = 2048 + String::kMaxShortPrintLength;
69 static const int kRelocInfoPosition = 57;
70 
71 static int DecodeIt(Isolate* isolate, OStream* os,
72  const V8NameConverter& converter, byte* begin, byte* end) {
73  SealHandleScope shs(isolate);
74  DisallowHeapAllocation no_alloc;
75  ExternalReferenceEncoder ref_encoder(isolate);
76 
79  StringBuilder out(out_buffer.start(), out_buffer.length());
80  byte* pc = begin;
81  disasm::Disassembler d(converter);
82  RelocIterator* it = NULL;
83  if (converter.code() != NULL) {
84  it = new RelocIterator(converter.code());
85  } else {
86  // No relocation information when printing code stubs.
87  }
88  int constants = -1; // no constants being decoded at the start
89 
90  while (pc < end) {
91  // First decode instruction so that we know its length.
92  byte* prev_pc = pc;
93  if (constants > 0) {
94  SNPrintF(decode_buffer,
95  "%08x constant",
96  *reinterpret_cast<int32_t*>(pc));
97  constants--;
98  pc += 4;
99  } else {
100  int num_const = d.ConstantPoolSizeAt(pc);
101  if (num_const >= 0) {
102  SNPrintF(decode_buffer,
103  "%08x constant pool begin",
104  *reinterpret_cast<int32_t*>(pc));
105  constants = num_const;
106  pc += 4;
107  } else if (it != NULL && !it->done() && it->rinfo()->pc() == pc &&
108  it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) {
109  // raw pointer embedded in code stream, e.g., jump table
110  byte* ptr = *reinterpret_cast<byte**>(pc);
111  SNPrintF(decode_buffer,
112  "%08" V8PRIxPTR " jump table entry %4" V8PRIdPTR,
113  reinterpret_cast<intptr_t>(ptr),
114  ptr - begin);
115  pc += 4;
116  } else {
117  decode_buffer[0] = '\0';
118  pc += d.InstructionDecode(decode_buffer, pc);
119  }
120  }
121 
122  // Collect RelocInfo for this instruction (prev_pc .. pc-1)
123  List<const char*> comments(4);
124  List<byte*> pcs(1);
125  List<RelocInfo::Mode> rmodes(1);
126  List<intptr_t> datas(1);
127  if (it != NULL) {
128  while (!it->done() && it->rinfo()->pc() < pc) {
129  if (RelocInfo::IsComment(it->rinfo()->rmode())) {
130  // For comments just collect the text.
131  comments.Add(reinterpret_cast<const char*>(it->rinfo()->data()));
132  } else {
133  // For other reloc info collect all data.
134  pcs.Add(it->rinfo()->pc());
135  rmodes.Add(it->rinfo()->rmode());
136  datas.Add(it->rinfo()->data());
137  }
138  it->next();
139  }
140  }
141 
142  // Comments.
143  for (int i = 0; i < comments.length(); i++) {
144  out.AddFormatted(" %s", comments[i]);
145  DumpBuffer(os, &out);
146  }
147 
148  // Instruction address and instruction offset.
149  out.AddFormatted("%p %4d ", prev_pc, prev_pc - begin);
150 
151  // Instruction.
152  out.AddFormatted("%s", decode_buffer.start());
153 
154  // Print all the reloc info for this instruction which are not comments.
155  for (int i = 0; i < pcs.length(); i++) {
156  // Put together the reloc info
157  RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], converter.code());
158 
159  // Indent the printing of the reloc info.
160  if (i == 0) {
161  // The first reloc info is printed after the disassembled instruction.
162  out.AddPadding(' ', kRelocInfoPosition - out.position());
163  } else {
164  // Additional reloc infos are printed on separate lines.
165  DumpBuffer(os, &out);
166  out.AddPadding(' ', kRelocInfoPosition);
167  }
168 
169  RelocInfo::Mode rmode = relocinfo.rmode();
170  if (RelocInfo::IsPosition(rmode)) {
171  if (RelocInfo::IsStatementPosition(rmode)) {
172  out.AddFormatted(" ;; debug: statement %d", relocinfo.data());
173  } else {
174  out.AddFormatted(" ;; debug: position %d", relocinfo.data());
175  }
176  } else if (rmode == RelocInfo::EMBEDDED_OBJECT) {
177  HeapStringAllocator allocator;
178  StringStream accumulator(&allocator);
179  relocinfo.target_object()->ShortPrint(&accumulator);
180  SmartArrayPointer<const char> obj_name = accumulator.ToCString();
181  out.AddFormatted(" ;; object: %s", obj_name.get());
182  } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
183  const char* reference_name =
184  ref_encoder.NameOfAddress(relocinfo.target_reference());
185  out.AddFormatted(" ;; external reference (%s)", reference_name);
186  } else if (RelocInfo::IsCodeTarget(rmode)) {
187  out.AddFormatted(" ;; code:");
188  if (rmode == RelocInfo::CONSTRUCT_CALL) {
189  out.AddFormatted(" constructor,");
190  }
191  Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address());
192  Code::Kind kind = code->kind();
193  if (code->is_inline_cache_stub()) {
194  if (kind == Code::LOAD_IC &&
195  LoadICState::GetContextualMode(code->extra_ic_state()) ==
196  CONTEXTUAL) {
197  out.AddFormatted(" contextual,");
198  }
199  InlineCacheState ic_state = code->ic_state();
200  out.AddFormatted(" %s, %s", Code::Kind2String(kind),
201  Code::ICState2String(ic_state));
202  if (ic_state == MONOMORPHIC) {
203  Code::StubType type = code->type();
204  out.AddFormatted(", %s", Code::StubType2String(type));
205  }
206  } else if (kind == Code::STUB || kind == Code::HANDLER) {
207  // Get the STUB key and extract major and minor key.
208  uint32_t key = code->stub_key();
209  uint32_t minor_key = CodeStub::MinorKeyFromKey(key);
210  CodeStub::Major major_key = CodeStub::GetMajorKey(code);
211  DCHECK(major_key == CodeStub::MajorKeyFromKey(key));
212  out.AddFormatted(" %s, %s, ", Code::Kind2String(kind),
213  CodeStub::MajorName(major_key, false));
214  switch (major_key) {
215  case CodeStub::CallFunction: {
216  int argc = CallFunctionStub::ExtractArgcFromMinorKey(minor_key);
217  out.AddFormatted("argc = %d", argc);
218  break;
219  }
220  default:
221  out.AddFormatted("minor: %d", minor_key);
222  }
223  } else {
224  out.AddFormatted(" %s", Code::Kind2String(kind));
225  }
226  if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
227  out.AddFormatted(" (id = %d)", static_cast<int>(relocinfo.data()));
228  }
229  } else if (RelocInfo::IsRuntimeEntry(rmode) &&
230  isolate->deoptimizer_data() != NULL) {
231  // A runtime entry reloinfo might be a deoptimization bailout.
232  Address addr = relocinfo.target_address();
233  int id = Deoptimizer::GetDeoptimizationId(isolate,
234  addr,
238  addr,
242  addr,
245  out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode));
246  } else {
247  out.AddFormatted(" ;; soft deoptimization bailout %d", id);
248  }
249  } else {
250  out.AddFormatted(" ;; lazy deoptimization bailout %d", id);
251  }
252  } else {
253  out.AddFormatted(" ;; deoptimization bailout %d", id);
254  }
255  } else {
256  out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode));
257  }
258  }
259  DumpBuffer(os, &out);
260  }
261 
262  // Emit comments following the last instruction (if any).
263  if (it != NULL) {
264  for ( ; !it->done(); it->next()) {
265  if (RelocInfo::IsComment(it->rinfo()->rmode())) {
266  out.AddFormatted(" %s",
267  reinterpret_cast<const char*>(it->rinfo()->data()));
268  DumpBuffer(os, &out);
269  }
270  }
271  }
272 
273  delete it;
274  return static_cast<int>(pc - begin);
275 }
276 
277 
278 int Disassembler::Decode(Isolate* isolate, OStream* os, byte* begin, byte* end,
279  Code* code) {
280  V8NameConverter v8NameConverter(code);
281  return DecodeIt(isolate, os, v8NameConverter, begin, end);
282 }
283 
284 #else // ENABLE_DISASSEMBLER
285 
286 int Disassembler::Decode(Isolate* isolate, OStream* os, byte* begin, byte* end,
287  Code* code) {
288  return 0;
289 }
290 
291 #endif // ENABLE_DISASSEMBLER
292 
293 } } // namespace v8::internal
virtual const char * NameOfAddress(byte *addr) const
static int ExtractArgcFromMinorKey(int minor_key)
Definition: code-stubs.h:1535
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:5018
static const char * Kind2String(Kind kind)
Definition: objects.cc:10627
static const int kNotDeoptimizationEntry
Definition: deoptimizer.h:247
static int GetDeoptimizationId(Isolate *isolate, Address addr, BailoutType type)
Definition: deoptimizer.cc:690
static int Decode(Isolate *isolate, OStream *os, byte *begin, byte *end, Code *code=NULL)
static bool IsComment(Mode mode)
Definition: assembler.h:415
static bool IsRuntimeEntry(Mode mode)
Definition: assembler.h:405
static bool IsPosition(Mode mode)
Definition: assembler.h:424
static bool IsCodeTarget(Mode mode)
Definition: assembler.h:399
static bool IsStatementPosition(Mode mode)
Definition: assembler.h:427
static const int kMaxShortPrintLength
Definition: objects.h:8827
T * start() const
Definition: vector.h:47
int length() const
Definition: vector.h:41
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
Definition: logging.h:205
#define V8PRIdPTR
Definition: macros.h:364
#define V8PRIxPTR
Definition: macros.h:363
int int32_t
Definition: unicode.cc:24
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
Definition: assert-scope.h:110
OStream & endl(OStream &os)
Definition: ostreams.cc:112
int SNPrintF(Vector< char > str, const char *format,...)
Definition: utils.cc:105
const Register pc
byte * Address
Definition: globals.h:101
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20