00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "code-stubs.h"
00031 #include "codegen.h"
00032 #include "debug.h"
00033 #include "disasm.h"
00034 #include "disassembler.h"
00035 #include "macro-assembler.h"
00036 #include "serialize.h"
00037 #include "string-stream.h"
00038
00039 namespace v8 { namespace internal {
00040
00041 #ifdef ENABLE_DISASSEMBLER
00042
00043 void Disassembler::Dump(FILE* f, byte* begin, byte* end) {
00044 for (byte* pc = begin; pc < end; pc++) {
00045 if (f == NULL) {
00046 PrintF("%p %4d %02x\n", pc, pc - begin, *pc);
00047 } else {
00048 fprintf(f, "%p %4d %02x\n", pc, pc - begin, *pc);
00049 }
00050 }
00051 }
00052
00053
00054 class V8NameConverter: public disasm::NameConverter {
00055 public:
00056 explicit V8NameConverter(Code* code) : code_(code) {}
00057 virtual const char* NameOfAddress(byte* pc) const;
00058 virtual const char* NameInCode(byte* addr) const;
00059 Code* code() const { return code_; }
00060 private:
00061 Code* code_;
00062 };
00063
00064
00065 const char* V8NameConverter::NameOfAddress(byte* pc) const {
00066 static v8::internal::EmbeddedVector<char, 128> buffer;
00067
00068 const char* name = Builtins::Lookup(pc);
00069 if (name != NULL) {
00070 OS::SNPrintF(buffer, "%s (%p)", name, pc);
00071 return buffer.start();
00072 }
00073
00074 if (code_ != NULL) {
00075 int offs = pc - code_->instruction_start();
00076
00077 if (0 <= offs && offs < code_->instruction_size()) {
00078 OS::SNPrintF(buffer, "%d (%p)", offs, pc);
00079 return buffer.start();
00080 }
00081 }
00082
00083 return disasm::NameConverter::NameOfAddress(pc);
00084 }
00085
00086
00087 const char* V8NameConverter::NameInCode(byte* addr) const {
00088
00089
00090 return (code_ != NULL) ? reinterpret_cast<const char*>(addr) : "";
00091 }
00092
00093
00094 static void DumpBuffer(FILE* f, char* buff) {
00095 if (f == NULL) {
00096 PrintF("%s", buff);
00097 } else {
00098 fprintf(f, "%s", buff);
00099 }
00100 }
00101
00102 static const int kOutBufferSize = 256 + String::kMaxShortPrintLength;
00103 static const int kRelocInfoPosition = 57;
00104
00105 static int DecodeIt(FILE* f,
00106 const V8NameConverter& converter,
00107 byte* begin,
00108 byte* end) {
00109 NoHandleAllocation ha;
00110 AssertNoAllocation no_alloc;
00111 ExternalReferenceEncoder ref_encoder;
00112
00113 v8::internal::EmbeddedVector<char, 128> decode_buffer;
00114 v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer;
00115 byte* pc = begin;
00116 disasm::Disassembler d(converter);
00117 RelocIterator* it = NULL;
00118 if (converter.code() != NULL) {
00119 it = new RelocIterator(converter.code());
00120 } else {
00121
00122 }
00123 int constants = -1;
00124
00125 while (pc < end) {
00126
00127 byte* prev_pc = pc;
00128 if (constants > 0) {
00129 OS::SNPrintF(decode_buffer,
00130 "%08x constant",
00131 *reinterpret_cast<int32_t*>(pc));
00132 constants--;
00133 pc += 4;
00134 } else {
00135 int num_const = d.ConstantPoolSizeAt(pc);
00136 if (num_const >= 0) {
00137 OS::SNPrintF(decode_buffer,
00138 "%08x constant pool begin",
00139 *reinterpret_cast<int32_t*>(pc));
00140 constants = num_const;
00141 pc += 4;
00142 } else if (it != NULL && !it->done() && it->rinfo()->pc() == pc &&
00143 it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) {
00144
00145 byte* ptr = *reinterpret_cast<byte**>(pc);
00146 OS::SNPrintF(decode_buffer,
00147 "%08x jump table entry %4d",
00148 reinterpret_cast<int32_t>(ptr),
00149 ptr - begin);
00150 pc += 4;
00151 } else {
00152 decode_buffer[0] = '\0';
00153 pc += d.InstructionDecode(decode_buffer, pc);
00154 }
00155 }
00156
00157
00158 List<const char*> comments(4);
00159 List<byte*> pcs(1);
00160 List<RelocInfo::Mode> rmodes(1);
00161 List<intptr_t> datas(1);
00162 if (it != NULL) {
00163 while (!it->done() && it->rinfo()->pc() < pc) {
00164 if (RelocInfo::IsComment(it->rinfo()->rmode())) {
00165
00166 comments.Add(reinterpret_cast<const char*>(it->rinfo()->data()));
00167 } else {
00168
00169 pcs.Add(it->rinfo()->pc());
00170 rmodes.Add(it->rinfo()->rmode());
00171 datas.Add(it->rinfo()->data());
00172 }
00173 it->next();
00174 }
00175 }
00176
00177 StringBuilder out(out_buffer.start(), out_buffer.length());
00178
00179
00180 for (int i = 0; i < comments.length(); i++) {
00181 out.AddFormatted(" %s\n", comments[i]);
00182 }
00183
00184
00185 DumpBuffer(f, out.Finalize());
00186 out.Reset();
00187
00188
00189 out.AddFormatted("%p %4d ", prev_pc, prev_pc - begin);
00190
00191
00192 out.AddFormatted("%s", decode_buffer.start());
00193
00194
00195 for (int i = 0; i < pcs.length(); i++) {
00196
00197 RelocInfo relocinfo(pcs[i], rmodes[i], datas[i]);
00198
00199
00200 if (i == 0) {
00201
00202 out.AddPadding(' ', kRelocInfoPosition - out.position());
00203 } else {
00204
00205 out.AddFormatted("\n");
00206 out.AddPadding(' ', kRelocInfoPosition);
00207 }
00208
00209 RelocInfo::Mode rmode = relocinfo.rmode();
00210 if (RelocInfo::IsPosition(rmode)) {
00211 if (RelocInfo::IsStatementPosition(rmode)) {
00212 out.AddFormatted(" ;; debug: statement %d", relocinfo.data());
00213 } else {
00214 out.AddFormatted(" ;; debug: position %d", relocinfo.data());
00215 }
00216 } else if (rmode == RelocInfo::EMBEDDED_OBJECT) {
00217 HeapStringAllocator allocator;
00218 StringStream accumulator(&allocator);
00219 relocinfo.target_object()->ShortPrint(&accumulator);
00220 SmartPointer<char> obj_name = accumulator.ToCString();
00221 out.AddFormatted(" ;; object: %s", *obj_name);
00222 } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
00223 const char* reference_name =
00224 ref_encoder.NameOfAddress(*relocinfo.target_reference_address());
00225 out.AddFormatted(" ;; external reference (%s)", reference_name);
00226 } else if (RelocInfo::IsCodeTarget(rmode)) {
00227 out.AddFormatted(" ;; code:");
00228 if (rmode == RelocInfo::CONSTRUCT_CALL) {
00229 out.AddFormatted(" constructor,");
00230 }
00231 Code* code = Debug::GetCodeTarget(relocinfo.target_address());
00232 Code::Kind kind = code->kind();
00233 if (code->is_inline_cache_stub()) {
00234 if (rmode == RelocInfo::CODE_TARGET_CONTEXT) {
00235 out.AddFormatted(" contextual,");
00236 }
00237 InlineCacheState ic_state = code->ic_state();
00238 out.AddFormatted(" %s, %s", Code::Kind2String(kind),
00239 Code::ICState2String(ic_state));
00240 if (kind == Code::CALL_IC) {
00241 out.AddFormatted(", argc = %d", code->arguments_count());
00242 }
00243 } else if (kind == Code::STUB) {
00244
00245
00246 Object* obj = Heap::code_stubs()->SlowReverseLookup(code);
00247 if (obj != Heap::undefined_value()) {
00248 ASSERT(obj->IsSmi());
00249
00250 uint32_t key = Smi::cast(obj)->value();
00251 uint32_t minor_key = CodeStub::MinorKeyFromKey(key);
00252 ASSERT(code->major_key() == CodeStub::MajorKeyFromKey(key));
00253 out.AddFormatted(" %s, %s, ",
00254 Code::Kind2String(kind),
00255 CodeStub::MajorName(code->major_key()));
00256 switch (code->major_key()) {
00257 case CodeStub::CallFunction:
00258 out.AddFormatted("argc = %d", minor_key);
00259 break;
00260 case CodeStub::Runtime: {
00261 const char* name =
00262 RuntimeStub::GetNameFromMinorKey(minor_key);
00263 out.AddFormatted("%s", name);
00264 break;
00265 }
00266 default:
00267 out.AddFormatted("minor: %d", minor_key);
00268 }
00269 }
00270 } else {
00271 out.AddFormatted(" %s", Code::Kind2String(kind));
00272 }
00273 } else {
00274 out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode));
00275 }
00276 }
00277 out.AddString("\n");
00278 DumpBuffer(f, out.Finalize());
00279 out.Reset();
00280 }
00281
00282 delete it;
00283 return pc - begin;
00284 }
00285
00286
00287 int Disassembler::Decode(FILE* f, byte* begin, byte* end) {
00288 V8NameConverter defaultConverter(NULL);
00289 return DecodeIt(f, defaultConverter, begin, end);
00290 }
00291
00292
00293
00294 void Disassembler::Decode(FILE* f, Code* code) {
00295 byte* begin = Code::cast(code)->instruction_start();
00296 byte* end = begin + Code::cast(code)->instruction_size();
00297 V8NameConverter v8NameConverter(code);
00298 DecodeIt(f, v8NameConverter, begin, end);
00299 }
00300
00301 #else // ENABLE_DISASSEMBLER
00302
00303 void Disassembler::Dump(FILE* f, byte* begin, byte* end) {}
00304 int Disassembler::Decode(FILE* f, byte* begin, byte* end) { return 0; }
00305 void Disassembler::Decode(FILE* f, Code* code) {}
00306
00307 #endif // ENABLE_DISASSEMBLER
00308
00309 } }