OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifdef ENABLE_GDB_JIT_INTERFACE | 5 #ifdef ENABLE_GDB_JIT_INTERFACE |
6 #include "src/v8.h" | 6 #include "src/v8.h" |
7 | 7 |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
(...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
892 src->at(i).Write(dst.at(i), strtab); | 892 src->at(i).Write(dst.at(i), strtab); |
893 } | 893 } |
894 } | 894 } |
895 | 895 |
896 ZoneList<ELFSymbol> locals_; | 896 ZoneList<ELFSymbol> locals_; |
897 ZoneList<ELFSymbol> globals_; | 897 ZoneList<ELFSymbol> globals_; |
898 }; | 898 }; |
899 #endif // defined(__ELF) | 899 #endif // defined(__ELF) |
900 | 900 |
901 | 901 |
| 902 class LineInfo : public Malloced { |
| 903 public: |
| 904 LineInfo() : pc_info_(10) {} |
| 905 |
| 906 void SetPosition(intptr_t pc, int pos, bool is_statement) { |
| 907 AddPCInfo(PCInfo(pc, pos, is_statement)); |
| 908 } |
| 909 |
| 910 struct PCInfo { |
| 911 PCInfo(intptr_t pc, int pos, bool is_statement) |
| 912 : pc_(pc), pos_(pos), is_statement_(is_statement) {} |
| 913 |
| 914 intptr_t pc_; |
| 915 int pos_; |
| 916 bool is_statement_; |
| 917 }; |
| 918 |
| 919 List<PCInfo>* pc_info() { return &pc_info_; } |
| 920 |
| 921 private: |
| 922 void AddPCInfo(const PCInfo& pc_info) { pc_info_.Add(pc_info); } |
| 923 |
| 924 List<PCInfo> pc_info_; |
| 925 }; |
| 926 |
| 927 |
902 class CodeDescription BASE_EMBEDDED { | 928 class CodeDescription BASE_EMBEDDED { |
903 public: | 929 public: |
904 #if V8_TARGET_ARCH_X64 | 930 #if V8_TARGET_ARCH_X64 |
905 enum StackState { | 931 enum StackState { |
906 POST_RBP_PUSH, | 932 POST_RBP_PUSH, |
907 POST_RBP_SET, | 933 POST_RBP_SET, |
908 POST_RBP_POP, | 934 POST_RBP_POP, |
909 STACK_STATE_MAX | 935 STACK_STATE_MAX |
910 }; | 936 }; |
911 #endif | 937 #endif |
912 | 938 |
913 CodeDescription(const char* name, | 939 CodeDescription(const char* name, Code* code, Handle<Script> script, |
914 Code* code, | 940 LineInfo* lineinfo, GDBJITInterface::CodeTag tag, |
915 Handle<Script> script, | |
916 GDBJITLineInfo* lineinfo, | |
917 GDBJITInterface::CodeTag tag, | |
918 CompilationInfo* info) | 941 CompilationInfo* info) |
919 : name_(name), | 942 : name_(name), |
920 code_(code), | 943 code_(code), |
921 script_(script), | 944 script_(script), |
922 lineinfo_(lineinfo), | 945 lineinfo_(lineinfo), |
923 tag_(tag), | 946 tag_(tag), |
924 info_(info) { | 947 info_(info) {} |
925 } | |
926 | 948 |
927 const char* name() const { | 949 const char* name() const { |
928 return name_; | 950 return name_; |
929 } | 951 } |
930 | 952 |
931 GDBJITLineInfo* lineinfo() const { | 953 LineInfo* lineinfo() const { return lineinfo_; } |
932 return lineinfo_; | |
933 } | |
934 | 954 |
935 GDBJITInterface::CodeTag tag() const { | 955 GDBJITInterface::CodeTag tag() const { |
936 return tag_; | 956 return tag_; |
937 } | 957 } |
938 | 958 |
939 CompilationInfo* info() const { | 959 CompilationInfo* info() const { |
940 return info_; | 960 return info_; |
941 } | 961 } |
942 | 962 |
943 bool IsInfoAvailable() const { | 963 bool IsInfoAvailable() const { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 | 1002 |
983 int GetScriptLineNumber(int pos) { | 1003 int GetScriptLineNumber(int pos) { |
984 return script_->GetLineNumber(pos) + 1; | 1004 return script_->GetLineNumber(pos) + 1; |
985 } | 1005 } |
986 | 1006 |
987 | 1007 |
988 private: | 1008 private: |
989 const char* name_; | 1009 const char* name_; |
990 Code* code_; | 1010 Code* code_; |
991 Handle<Script> script_; | 1011 Handle<Script> script_; |
992 GDBJITLineInfo* lineinfo_; | 1012 LineInfo* lineinfo_; |
993 GDBJITInterface::CodeTag tag_; | 1013 GDBJITInterface::CodeTag tag_; |
994 CompilationInfo* info_; | 1014 CompilationInfo* info_; |
995 #if V8_TARGET_ARCH_X64 | 1015 #if V8_TARGET_ARCH_X64 |
996 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX]; | 1016 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX]; |
997 #endif | 1017 #endif |
998 }; | 1018 }; |
999 | 1019 |
1000 #if defined(__ELF) | 1020 #if defined(__ELF) |
1001 static void CreateSymbolsTable(CodeDescription* desc, | 1021 static void CreateSymbolsTable(CodeDescription* desc, |
1002 Zone* zone, | 1022 Zone* zone, |
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1444 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start)); | 1464 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start)); |
1445 | 1465 |
1446 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t)); | 1466 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t)); |
1447 w->Write<intptr_t>(desc_->CodeStart()); | 1467 w->Write<intptr_t>(desc_->CodeStart()); |
1448 w->Write<uint8_t>(DW_LNS_COPY); | 1468 w->Write<uint8_t>(DW_LNS_COPY); |
1449 | 1469 |
1450 intptr_t pc = 0; | 1470 intptr_t pc = 0; |
1451 intptr_t line = 1; | 1471 intptr_t line = 1; |
1452 bool is_statement = true; | 1472 bool is_statement = true; |
1453 | 1473 |
1454 List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info(); | 1474 List<LineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info(); |
1455 pc_info->Sort(&ComparePCInfo); | 1475 pc_info->Sort(&ComparePCInfo); |
1456 | 1476 |
1457 int pc_info_length = pc_info->length(); | 1477 int pc_info_length = pc_info->length(); |
1458 for (int i = 0; i < pc_info_length; i++) { | 1478 for (int i = 0; i < pc_info_length; i++) { |
1459 GDBJITLineInfo::PCInfo* info = &pc_info->at(i); | 1479 LineInfo::PCInfo* info = &pc_info->at(i); |
1460 ASSERT(info->pc_ >= pc); | 1480 ASSERT(info->pc_ >= pc); |
1461 | 1481 |
1462 // Reduce bloating in the debug line table by removing duplicate line | 1482 // Reduce bloating in the debug line table by removing duplicate line |
1463 // entries (per DWARF2 standard). | 1483 // entries (per DWARF2 standard). |
1464 intptr_t new_line = desc_->GetScriptLineNumber(info->pos_); | 1484 intptr_t new_line = desc_->GetScriptLineNumber(info->pos_); |
1465 if (new_line == line) { | 1485 if (new_line == line) { |
1466 continue; | 1486 continue; |
1467 } | 1487 } |
1468 | 1488 |
1469 // Mark statement boundaries. For a better debugging experience, mark | 1489 // Mark statement boundaries. For a better debugging experience, mark |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1520 | 1540 |
1521 private: | 1541 private: |
1522 void WriteExtendedOpcode(Writer* w, | 1542 void WriteExtendedOpcode(Writer* w, |
1523 DWARF2ExtendedOpcode op, | 1543 DWARF2ExtendedOpcode op, |
1524 size_t operands_size) { | 1544 size_t operands_size) { |
1525 w->Write<uint8_t>(0); | 1545 w->Write<uint8_t>(0); |
1526 w->WriteULEB128(operands_size + 1); | 1546 w->WriteULEB128(operands_size + 1); |
1527 w->Write<uint8_t>(op); | 1547 w->Write<uint8_t>(op); |
1528 } | 1548 } |
1529 | 1549 |
1530 static int ComparePCInfo(const GDBJITLineInfo::PCInfo* a, | 1550 static int ComparePCInfo(const LineInfo::PCInfo* a, |
1531 const GDBJITLineInfo::PCInfo* b) { | 1551 const LineInfo::PCInfo* b) { |
1532 if (a->pc_ == b->pc_) { | 1552 if (a->pc_ == b->pc_) { |
1533 if (a->is_statement_ != b->is_statement_) { | 1553 if (a->is_statement_ != b->is_statement_) { |
1534 return b->is_statement_ ? +1 : -1; | 1554 return b->is_statement_ ? +1 : -1; |
1535 } | 1555 } |
1536 return 0; | 1556 return 0; |
1537 } else if (a->pc_ > b->pc_) { | 1557 } else if (a->pc_ > b->pc_) { |
1538 return +1; | 1558 return +1; |
1539 } else { | 1559 } else { |
1540 return -1; | 1560 return -1; |
1541 } | 1561 } |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1960 | 1980 |
1961 | 1981 |
1962 static const intptr_t kLineInfoTag = 0x1; | 1982 static const intptr_t kLineInfoTag = 0x1; |
1963 | 1983 |
1964 | 1984 |
1965 static bool IsLineInfoTagged(void* ptr) { | 1985 static bool IsLineInfoTagged(void* ptr) { |
1966 return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag); | 1986 return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag); |
1967 } | 1987 } |
1968 | 1988 |
1969 | 1989 |
1970 static void* TagLineInfo(GDBJITLineInfo* ptr) { | 1990 static void* TagLineInfo(LineInfo* ptr) { |
1971 return reinterpret_cast<void*>( | 1991 return reinterpret_cast<void*>( |
1972 reinterpret_cast<intptr_t>(ptr) | kLineInfoTag); | 1992 reinterpret_cast<intptr_t>(ptr) | kLineInfoTag); |
1973 } | 1993 } |
1974 | 1994 |
1975 | 1995 |
1976 static GDBJITLineInfo* UntagLineInfo(void* ptr) { | 1996 static LineInfo* UntagLineInfo(void* ptr) { |
1977 return reinterpret_cast<GDBJITLineInfo*>( | 1997 return reinterpret_cast<LineInfo*>(reinterpret_cast<intptr_t>(ptr) & |
1978 reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag); | 1998 ~kLineInfoTag); |
1979 } | 1999 } |
1980 | 2000 |
1981 | 2001 |
1982 void GDBJITInterface::AddCode(Handle<Name> name, | 2002 void GDBJITInterface::AddCode(Handle<Name> name, |
1983 Handle<Script> script, | 2003 Handle<Script> script, |
1984 Handle<Code> code, | 2004 Handle<Code> code, |
1985 CompilationInfo* info) { | 2005 CompilationInfo* info) { |
1986 if (!FLAG_gdbjit) return; | 2006 if (!FLAG_gdbjit) return; |
1987 | 2007 |
1988 Script::InitLineEnds(script); | 2008 Script::InitLineEnds(script); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2044 Script* script, | 2064 Script* script, |
2045 CompilationInfo* info) { | 2065 CompilationInfo* info) { |
2046 if (!FLAG_gdbjit) return; | 2066 if (!FLAG_gdbjit) return; |
2047 | 2067 |
2048 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer()); | 2068 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer()); |
2049 DisallowHeapAllocation no_gc; | 2069 DisallowHeapAllocation no_gc; |
2050 | 2070 |
2051 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); | 2071 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); |
2052 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; | 2072 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; |
2053 | 2073 |
2054 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value); | 2074 LineInfo* lineinfo = UntagLineInfo(e->value); |
2055 CodeDescription code_desc(name, | 2075 CodeDescription code_desc(name, |
2056 code, | 2076 code, |
2057 script != NULL ? Handle<Script>(script) | 2077 script != NULL ? Handle<Script>(script) |
2058 : Handle<Script>(), | 2078 : Handle<Script>(), |
2059 lineinfo, | 2079 lineinfo, |
2060 tag, | 2080 tag, |
2061 info); | 2081 info); |
2062 | 2082 |
2063 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { | 2083 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { |
2064 delete lineinfo; | 2084 delete lineinfo; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2160 dead_codes.Add(code, &zone); | 2180 dead_codes.Add(code, &zone); |
2161 } | 2181 } |
2162 } | 2182 } |
2163 | 2183 |
2164 for (int i = 0; i < dead_codes.length(); i++) { | 2184 for (int i = 0; i < dead_codes.length(); i++) { |
2165 RemoveCode(dead_codes.at(i)); | 2185 RemoveCode(dead_codes.at(i)); |
2166 } | 2186 } |
2167 } | 2187 } |
2168 | 2188 |
2169 | 2189 |
2170 void GDBJITInterface::RegisterDetailedLineInfo(Code* code, | 2190 static void RegisterDetailedLineInfo(Code* code, LineInfo* line_info) { |
2171 GDBJITLineInfo* line_info) { | |
2172 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer()); | 2191 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer()); |
2173 ASSERT(!IsLineInfoTagged(line_info)); | 2192 ASSERT(!IsLineInfoTagged(line_info)); |
2174 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); | 2193 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); |
2175 ASSERT(e->value == NULL); | 2194 ASSERT(e->value == NULL); |
2176 e->value = TagLineInfo(line_info); | 2195 e->value = TagLineInfo(line_info); |
2177 } | 2196 } |
2178 | 2197 |
2179 | 2198 |
| 2199 void GDBJITInterface::EventHandler(const v8::JitCodeEvent* event) { |
| 2200 if (!FLAG_gdbjit) return; |
| 2201 switch (event->type) { |
| 2202 case v8::JitCodeEvent::CODE_ADDED: |
| 2203 case v8::JitCodeEvent::CODE_MOVED: |
| 2204 case v8::JitCodeEvent::CODE_REMOVED: |
| 2205 break; |
| 2206 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: { |
| 2207 LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data); |
| 2208 line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset), |
| 2209 static_cast<int>(event->line_info.pos), |
| 2210 event->line_info.position_type == |
| 2211 v8::JitCodeEvent::STATEMENT_POSITION); |
| 2212 break; |
| 2213 } |
| 2214 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: { |
| 2215 v8::JitCodeEvent* mutable_event = const_cast<v8::JitCodeEvent*>(event); |
| 2216 mutable_event->user_data = new LineInfo(); |
| 2217 break; |
| 2218 } |
| 2219 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: { |
| 2220 LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data); |
| 2221 Code* code = Code::GetCodeFromTargetAddress( |
| 2222 reinterpret_cast<Address>(event->code_start)); |
| 2223 RegisterDetailedLineInfo(code, line_info); |
| 2224 break; |
| 2225 } |
| 2226 } |
| 2227 } |
| 2228 |
| 2229 |
2180 } } // namespace v8::internal | 2230 } } // namespace v8::internal |
2181 #endif | 2231 #endif |
OLD | NEW |