| 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 |