Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/gdb-jit.cc

Issue 957673004: Rebase GDBJIT interface solely on JITCodeEvent (Closed) Base URL: https://chromium.googlesource.com/v8/v8@master
Patch Set: Address nits Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gdb-jit.h ('k') | src/heap/mark-compact.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
6 #include "src/v8.h" 5 #include "src/v8.h"
7 6
8 #include "src/base/bits.h" 7 #include "src/base/bits.h"
9 #include "src/base/platform/platform.h" 8 #include "src/base/platform/platform.h"
10 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
11 #include "src/compiler.h" 10 #include "src/compiler.h"
12 #include "src/frames-inl.h" 11 #include "src/frames-inl.h"
13 #include "src/frames.h" 12 #include "src/frames.h"
14 #include "src/gdb-jit.h" 13 #include "src/gdb-jit.h"
15 #include "src/global-handles.h" 14 #include "src/global-handles.h"
16 #include "src/messages.h" 15 #include "src/messages.h"
17 #include "src/natives.h" 16 #include "src/natives.h"
17 #include "src/objects.h"
18 #include "src/ostreams.h" 18 #include "src/ostreams.h"
19 #include "src/scopes.h"
20 19
21 namespace v8 { 20 namespace v8 {
22 namespace internal { 21 namespace internal {
22 namespace GDBJITInterface {
23
24 #ifdef ENABLE_GDB_JIT_INTERFACE
23 25
24 #ifdef __APPLE__ 26 #ifdef __APPLE__
25 #define __MACH_O 27 #define __MACH_O
26 class MachO; 28 class MachO;
27 class MachOSection; 29 class MachOSection;
28 typedef MachO DebugObject; 30 typedef MachO DebugObject;
29 typedef MachOSection DebugSection; 31 typedef MachOSection DebugSection;
30 #else 32 #else
31 #define __ELF 33 #define __ELF
32 class ELF; 34 class ELF;
(...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 public: 928 public:
927 #if V8_TARGET_ARCH_X64 929 #if V8_TARGET_ARCH_X64
928 enum StackState { 930 enum StackState {
929 POST_RBP_PUSH, 931 POST_RBP_PUSH,
930 POST_RBP_SET, 932 POST_RBP_SET,
931 POST_RBP_POP, 933 POST_RBP_POP,
932 STACK_STATE_MAX 934 STACK_STATE_MAX
933 }; 935 };
934 #endif 936 #endif
935 937
936 CodeDescription(const char* name, Code* code, Handle<Script> script, 938 CodeDescription(const char* name, Code* code, SharedFunctionInfo* shared,
937 LineInfo* lineinfo, GDBJITInterface::CodeTag tag, 939 LineInfo* lineinfo)
938 CompilationInfo* info) 940 : name_(name), code_(code), shared_info_(shared), lineinfo_(lineinfo) {}
939 : name_(name),
940 code_(code),
941 script_(script),
942 lineinfo_(lineinfo),
943 tag_(tag),
944 info_(info) {}
945 941
946 const char* name() const { 942 const char* name() const {
947 return name_; 943 return name_;
948 } 944 }
949 945
950 LineInfo* lineinfo() const { return lineinfo_; } 946 LineInfo* lineinfo() const { return lineinfo_; }
951 947
952 GDBJITInterface::CodeTag tag() const { 948 bool is_function() const {
953 return tag_; 949 Code::Kind kind = code_->kind();
950 return kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION;
954 } 951 }
955 952
956 CompilationInfo* info() const { 953 bool has_scope_info() const { return shared_info_ != NULL; }
957 return info_;
958 }
959 954
960 bool IsInfoAvailable() const { 955 ScopeInfo* scope_info() const {
961 return info_ != NULL; 956 DCHECK(has_scope_info());
957 return shared_info_->scope_info();
962 } 958 }
963 959
964 uintptr_t CodeStart() const { 960 uintptr_t CodeStart() const {
965 return reinterpret_cast<uintptr_t>(code_->instruction_start()); 961 return reinterpret_cast<uintptr_t>(code_->instruction_start());
966 } 962 }
967 963
968 uintptr_t CodeEnd() const { 964 uintptr_t CodeEnd() const {
969 return reinterpret_cast<uintptr_t>(code_->instruction_end()); 965 return reinterpret_cast<uintptr_t>(code_->instruction_end());
970 } 966 }
971 967
972 uintptr_t CodeSize() const { 968 uintptr_t CodeSize() const {
973 return CodeEnd() - CodeStart(); 969 return CodeEnd() - CodeStart();
974 } 970 }
975 971
972 bool has_script() {
973 return shared_info_ != NULL && shared_info_->script()->IsScript();
974 }
975
976 Script* script() { return Script::cast(shared_info_->script()); }
977
976 bool IsLineInfoAvailable() { 978 bool IsLineInfoAvailable() {
977 return !script_.is_null() && 979 return has_script() && script()->source()->IsString() &&
978 script_->source()->IsString() && 980 script()->HasValidSource() && script()->name()->IsString() &&
979 script_->HasValidSource() && 981 lineinfo_ != NULL;
980 script_->name()->IsString() &&
981 lineinfo_ != NULL;
982 } 982 }
983 983
984 #if V8_TARGET_ARCH_X64 984 #if V8_TARGET_ARCH_X64
985 uintptr_t GetStackStateStartAddress(StackState state) const { 985 uintptr_t GetStackStateStartAddress(StackState state) const {
986 DCHECK(state < STACK_STATE_MAX); 986 DCHECK(state < STACK_STATE_MAX);
987 return stack_state_start_addresses_[state]; 987 return stack_state_start_addresses_[state];
988 } 988 }
989 989
990 void SetStackStateStartAddress(StackState state, uintptr_t addr) { 990 void SetStackStateStartAddress(StackState state, uintptr_t addr) {
991 DCHECK(state < STACK_STATE_MAX); 991 DCHECK(state < STACK_STATE_MAX);
992 stack_state_start_addresses_[state] = addr; 992 stack_state_start_addresses_[state] = addr;
993 } 993 }
994 #endif 994 #endif
995 995
996 SmartArrayPointer<char> GetFilename() { 996 SmartArrayPointer<char> GetFilename() {
997 return String::cast(script_->name())->ToCString(); 997 return String::cast(script()->name())->ToCString();
998 } 998 }
999 999
1000 int GetScriptLineNumber(int pos) { 1000 int GetScriptLineNumber(int pos) { return script()->GetLineNumber(pos) + 1; }
1001 return script_->GetLineNumber(pos) + 1;
1002 }
1003 1001
1004 1002
1005 private: 1003 private:
1006 const char* name_; 1004 const char* name_;
1007 Code* code_; 1005 Code* code_;
1008 Handle<Script> script_; 1006 SharedFunctionInfo* shared_info_;
1009 LineInfo* lineinfo_; 1007 LineInfo* lineinfo_;
1010 GDBJITInterface::CodeTag tag_;
1011 CompilationInfo* info_;
1012 #if V8_TARGET_ARCH_X64 1008 #if V8_TARGET_ARCH_X64
1013 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX]; 1009 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
1014 #endif 1010 #endif
1015 }; 1011 };
1016 1012
1017 #if defined(__ELF) 1013 #if defined(__ELF)
1018 static void CreateSymbolsTable(CodeDescription* desc, 1014 static void CreateSymbolsTable(CodeDescription* desc,
1019 Zone* zone, 1015 Zone* zone,
1020 ELF* elf, 1016 ELF* elf,
1021 int text_section_index) { 1017 int text_section_index) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1088 w->WriteString(desc_->GetFilename().get()); 1084 w->WriteString(desc_->GetFilename().get());
1089 w->Write<intptr_t>(desc_->CodeStart()); 1085 w->Write<intptr_t>(desc_->CodeStart());
1090 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); 1086 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1091 w->Write<uint32_t>(0); 1087 w->Write<uint32_t>(0);
1092 1088
1093 uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start); 1089 uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start);
1094 w->WriteULEB128(3); 1090 w->WriteULEB128(3);
1095 w->Write<uint8_t>(kPointerSize); 1091 w->Write<uint8_t>(kPointerSize);
1096 w->WriteString("v8value"); 1092 w->WriteString("v8value");
1097 1093
1098 if (desc_->IsInfoAvailable()) { 1094 if (desc_->has_scope_info()) {
1099 Scope* scope = desc_->info()->scope(); 1095 ScopeInfo* scope = desc_->scope_info();
1100 w->WriteULEB128(2); 1096 w->WriteULEB128(2);
1101 w->WriteString(desc_->name()); 1097 w->WriteString(desc_->name());
1102 w->Write<intptr_t>(desc_->CodeStart()); 1098 w->Write<intptr_t>(desc_->CodeStart());
1103 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); 1099 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1104 Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>(); 1100 Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
1105 uintptr_t fb_block_start = w->position(); 1101 uintptr_t fb_block_start = w->position();
1106 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87 1102 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
1107 w->Write<uint8_t>(DW_OP_reg5); // The frame pointer's here on ia32 1103 w->Write<uint8_t>(DW_OP_reg5); // The frame pointer's here on ia32
1108 #elif V8_TARGET_ARCH_X64 1104 #elif V8_TARGET_ARCH_X64
1109 w->Write<uint8_t>(DW_OP_reg6); // and here on x64. 1105 w->Write<uint8_t>(DW_OP_reg6); // and here on x64.
1110 #elif V8_TARGET_ARCH_ARM 1106 #elif V8_TARGET_ARCH_ARM
1111 UNIMPLEMENTED(); 1107 UNIMPLEMENTED();
1112 #elif V8_TARGET_ARCH_MIPS 1108 #elif V8_TARGET_ARCH_MIPS
1113 UNIMPLEMENTED(); 1109 UNIMPLEMENTED();
1114 #elif V8_TARGET_ARCH_MIPS64 1110 #elif V8_TARGET_ARCH_MIPS64
1115 UNIMPLEMENTED(); 1111 UNIMPLEMENTED();
1116 #else 1112 #else
1117 #error Unsupported target architecture. 1113 #error Unsupported target architecture.
1118 #endif 1114 #endif
1119 fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start)); 1115 fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
1120 1116
1121 int params = scope->num_parameters(); 1117 int params = scope->ParameterCount();
1122 int slots = scope->num_stack_slots(); 1118 int slots = scope->StackLocalCount();
1123 int context_slots = scope->ContextLocalCount(); 1119 int context_slots = scope->ContextLocalCount();
1124 // The real slot ID is internal_slots + context_slot_id. 1120 // The real slot ID is internal_slots + context_slot_id.
1125 int internal_slots = Context::MIN_CONTEXT_SLOTS; 1121 int internal_slots = Context::MIN_CONTEXT_SLOTS;
1126 int locals = scope->StackLocalCount(); 1122 int locals = scope->StackLocalCount();
1127 int current_abbreviation = 4; 1123 int current_abbreviation = 4;
1128 1124
1129 for (int param = 0; param < params; ++param) { 1125 for (int param = 0; param < params; ++param) {
1130 w->WriteULEB128(current_abbreviation++); 1126 w->WriteULEB128(current_abbreviation++);
1131 w->WriteString( 1127 w->WriteString(
1132 scope->parameter(param)->name()->ToCString(DISALLOW_NULLS).get()); 1128 scope->ParameterName(param)->ToCString(DISALLOW_NULLS).get());
1133 w->Write<uint32_t>(ty_offset); 1129 w->Write<uint32_t>(ty_offset);
1134 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); 1130 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1135 uintptr_t block_start = w->position(); 1131 uintptr_t block_start = w->position();
1136 w->Write<uint8_t>(DW_OP_fbreg); 1132 w->Write<uint8_t>(DW_OP_fbreg);
1137 w->WriteSLEB128( 1133 w->WriteSLEB128(
1138 JavaScriptFrameConstants::kLastParameterOffset + 1134 JavaScriptFrameConstants::kLastParameterOffset +
1139 kPointerSize * (params - param - 1)); 1135 kPointerSize * (params - param - 1));
1140 block_size.set(static_cast<uint32_t>(w->position() - block_start)); 1136 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1141 } 1137 }
1142 1138
(...skipping 24 matching lines...) Expand all
1167 1163
1168 for (int context_slot = 0; 1164 for (int context_slot = 0;
1169 context_slot < context_slots; 1165 context_slot < context_slots;
1170 ++context_slot) { 1166 ++context_slot) {
1171 w->WriteULEB128(current_abbreviation++); 1167 w->WriteULEB128(current_abbreviation++);
1172 builder.Reset(); 1168 builder.Reset();
1173 builder.AddFormatted("context_slot%d", context_slot + internal_slots); 1169 builder.AddFormatted("context_slot%d", context_slot + internal_slots);
1174 w->WriteString(builder.Finalize()); 1170 w->WriteString(builder.Finalize());
1175 } 1171 }
1176 1172
1177 ZoneList<Variable*> stack_locals(locals, scope->zone());
1178 ZoneList<Variable*> context_locals(context_slots, scope->zone());
1179 scope->CollectStackAndContextLocals(&stack_locals, &context_locals);
1180 for (int local = 0; local < locals; ++local) { 1173 for (int local = 0; local < locals; ++local) {
1181 w->WriteULEB128(current_abbreviation++); 1174 w->WriteULEB128(current_abbreviation++);
1182 w->WriteString( 1175 w->WriteString(
1183 stack_locals[local]->name()->ToCString(DISALLOW_NULLS).get()); 1176 scope->StackLocalName(local)->ToCString(DISALLOW_NULLS).get());
1184 w->Write<uint32_t>(ty_offset); 1177 w->Write<uint32_t>(ty_offset);
1185 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); 1178 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1186 uintptr_t block_start = w->position(); 1179 uintptr_t block_start = w->position();
1187 w->Write<uint8_t>(DW_OP_fbreg); 1180 w->Write<uint8_t>(DW_OP_fbreg);
1188 w->WriteSLEB128( 1181 w->WriteSLEB128(
1189 JavaScriptFrameConstants::kLocal0Offset - 1182 JavaScriptFrameConstants::kLocal0Offset -
1190 kPointerSize * local); 1183 kPointerSize * local);
1191 block_size.set(static_cast<uint32_t>(w->position() - block_start)); 1184 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1192 } 1185 }
1193 1186
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 w->WriteULEB128(DW_FORM_REF4); 1288 w->WriteULEB128(DW_FORM_REF4);
1296 w->WriteULEB128(DW_AT_LOCATION); 1289 w->WriteULEB128(DW_AT_LOCATION);
1297 w->WriteULEB128(DW_FORM_BLOCK4); 1290 w->WriteULEB128(DW_FORM_BLOCK4);
1298 } 1291 }
1299 w->WriteULEB128(0); 1292 w->WriteULEB128(0);
1300 w->WriteULEB128(0); 1293 w->WriteULEB128(0);
1301 } 1294 }
1302 1295
1303 bool WriteBodyInternal(Writer* w) { 1296 bool WriteBodyInternal(Writer* w) {
1304 int current_abbreviation = 1; 1297 int current_abbreviation = 1;
1305 bool extra_info = desc_->IsInfoAvailable(); 1298 bool extra_info = desc_->has_scope_info();
1306 DCHECK(desc_->IsLineInfoAvailable()); 1299 DCHECK(desc_->IsLineInfoAvailable());
1307 w->WriteULEB128(current_abbreviation++); 1300 w->WriteULEB128(current_abbreviation++);
1308 w->WriteULEB128(DW_TAG_COMPILE_UNIT); 1301 w->WriteULEB128(DW_TAG_COMPILE_UNIT);
1309 w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO); 1302 w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1310 w->WriteULEB128(DW_AT_NAME); 1303 w->WriteULEB128(DW_AT_NAME);
1311 w->WriteULEB128(DW_FORM_STRING); 1304 w->WriteULEB128(DW_FORM_STRING);
1312 w->WriteULEB128(DW_AT_LOW_PC); 1305 w->WriteULEB128(DW_AT_LOW_PC);
1313 w->WriteULEB128(DW_FORM_ADDR); 1306 w->WriteULEB128(DW_FORM_ADDR);
1314 w->WriteULEB128(DW_AT_HIGH_PC); 1307 w->WriteULEB128(DW_AT_HIGH_PC);
1315 w->WriteULEB128(DW_FORM_ADDR); 1308 w->WriteULEB128(DW_FORM_ADDR);
1316 w->WriteULEB128(DW_AT_STMT_LIST); 1309 w->WriteULEB128(DW_AT_STMT_LIST);
1317 w->WriteULEB128(DW_FORM_DATA4); 1310 w->WriteULEB128(DW_FORM_DATA4);
1318 w->WriteULEB128(0); 1311 w->WriteULEB128(0);
1319 w->WriteULEB128(0); 1312 w->WriteULEB128(0);
1320 1313
1321 if (extra_info) { 1314 if (extra_info) {
1322 Scope* scope = desc_->info()->scope(); 1315 ScopeInfo* scope = desc_->scope_info();
1323 int params = scope->num_parameters(); 1316 int params = scope->ParameterCount();
1324 int slots = scope->num_stack_slots(); 1317 int slots = scope->StackLocalCount();
1325 int context_slots = scope->ContextLocalCount(); 1318 int context_slots = scope->ContextLocalCount();
1326 // The real slot ID is internal_slots + context_slot_id. 1319 // The real slot ID is internal_slots + context_slot_id.
1327 int internal_slots = Context::MIN_CONTEXT_SLOTS; 1320 int internal_slots = Context::MIN_CONTEXT_SLOTS;
1328 int locals = scope->StackLocalCount(); 1321 int locals = scope->StackLocalCount();
1329 // Total children is params + slots + context_slots + internal_slots + 1322 // Total children is params + slots + context_slots + internal_slots +
1330 // locals + 2 (__function and __context). 1323 // locals + 2 (__function and __context).
1331 1324
1332 // The extra duplication below seems to be necessary to keep 1325 // The extra duplication below seems to be necessary to keep
1333 // gdb from getting upset on OSX. 1326 // gdb from getting upset on OSX.
1334 w->WriteULEB128(current_abbreviation++); // Abbreviation code. 1327 w->WriteULEB128(current_abbreviation++); // Abbreviation code.
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after
1861 1854
1862 return entry; 1855 return entry;
1863 } 1856 }
1864 1857
1865 1858
1866 static void DestroyCodeEntry(JITCodeEntry* entry) { 1859 static void DestroyCodeEntry(JITCodeEntry* entry) {
1867 free(entry); 1860 free(entry);
1868 } 1861 }
1869 1862
1870 1863
1871 static void RegisterCodeEntry(JITCodeEntry* entry, 1864 static void RegisterCodeEntry(JITCodeEntry* entry) {
1872 bool dump_if_enabled,
1873 const char* name_hint) {
1874 #if defined(DEBUG) && !V8_OS_WIN
1875 static int file_num = 0;
1876 if (FLAG_gdbjit_dump && dump_if_enabled) {
1877 static const int kMaxFileNameSize = 64;
1878 static const char* kElfFilePrefix = "/tmp/elfdump";
1879 static const char* kObjFileExt = ".o";
1880 char file_name[64];
1881
1882 SNPrintF(Vector<char>(file_name, kMaxFileNameSize),
1883 "%s%s%d%s",
1884 kElfFilePrefix,
1885 (name_hint != NULL) ? name_hint : "",
1886 file_num++,
1887 kObjFileExt);
1888 WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
1889 }
1890 #endif
1891
1892 entry->next_ = __jit_debug_descriptor.first_entry_; 1865 entry->next_ = __jit_debug_descriptor.first_entry_;
1893 if (entry->next_ != NULL) entry->next_->prev_ = entry; 1866 if (entry->next_ != NULL) entry->next_->prev_ = entry;
1894 __jit_debug_descriptor.first_entry_ = 1867 __jit_debug_descriptor.first_entry_ =
1895 __jit_debug_descriptor.relevant_entry_ = entry; 1868 __jit_debug_descriptor.relevant_entry_ = entry;
1896 1869
1897 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN; 1870 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
1898 __jit_debug_register_code(); 1871 __jit_debug_register_code();
1899 } 1872 }
1900 1873
1901 1874
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1948 1921
1949 CreateDWARFSections(desc, &zone, &elf); 1922 CreateDWARFSections(desc, &zone, &elf);
1950 1923
1951 elf.Write(&w); 1924 elf.Write(&w);
1952 #endif 1925 #endif
1953 1926
1954 return CreateCodeEntry(w.buffer(), w.position()); 1927 return CreateCodeEntry(w.buffer(), w.position());
1955 } 1928 }
1956 1929
1957 1930
1958 static bool SameCodeObjects(void* key1, void* key2) { 1931 struct AddressRange {
1959 return key1 == key2; 1932 Address start;
1933 Address end;
1934 };
1935
1936 class JITCodeEntry;
1937
1938 struct SplayTreeConfig {
1939 typedef AddressRange Key;
1940 typedef JITCodeEntry* Value;
1941 static const AddressRange kNoKey;
1942 static Value NoValue() { return NULL; }
1943 static int Compare(const AddressRange& a, const AddressRange& b) {
1944 // ptrdiff_t probably doesn't fit in an int.
1945 if (a.start < b.start) return -1;
1946 if (a.start == b.start) return 0;
1947 return 1;
1948 }
1949 };
1950
1951 const AddressRange SplayTreeConfig::kNoKey = {0, 0};
1952 typedef SplayTree<SplayTreeConfig> CodeMap;
1953
1954 static CodeMap* GetCodeMap() {
1955 static CodeMap* code_map = NULL;
1956 if (code_map == NULL) code_map = new CodeMap();
1957 return code_map;
1960 } 1958 }
1961 1959
1962 1960
1963 static HashMap* GetEntries() { 1961 static uint32_t HashCodeAddress(Address addr) {
1964 static HashMap* entries = NULL; 1962 static const intptr_t kGoldenRatio = 2654435761;
1965 if (entries == NULL) { 1963 uintptr_t offset = OffsetFrom(addr);
1966 entries = new HashMap(&SameCodeObjects); 1964 return static_cast<uint32_t>((offset >> kCodeAlignmentBits) * kGoldenRatio);
1967 }
1968 return entries;
1969 } 1965 }
1970 1966
1971 1967
1972 static uint32_t HashForCodeObject(Code* code) { 1968 static HashMap* GetLineMap() {
1973 static const uintptr_t kGoldenRatio = 2654435761u; 1969 static HashMap* line_map = NULL;
1974 uintptr_t hash = reinterpret_cast<uintptr_t>(code->address()); 1970 if (line_map == NULL) line_map = new HashMap(&HashMap::PointersMatch);
1975 return static_cast<uint32_t>((hash >> kCodeAlignmentBits) * kGoldenRatio); 1971 return line_map;
1976 } 1972 }
1977 1973
1978 1974
1979 static const intptr_t kLineInfoTag = 0x1; 1975 static void PutLineInfo(Address addr, LineInfo* info) {
1980 1976 HashMap* line_map = GetLineMap();
1981 1977 HashMap::Entry* e = line_map->Lookup(addr, HashCodeAddress(addr), true);
1982 static bool IsLineInfoTagged(void* ptr) { 1978 if (e->value != NULL) delete static_cast<LineInfo*>(e->value);
1983 return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag); 1979 e->value = info;
1984 } 1980 }
1985 1981
1986 1982
1987 static void* TagLineInfo(LineInfo* ptr) { 1983 static LineInfo* GetLineInfo(Address addr) {
1988 return reinterpret_cast<void*>( 1984 void* value = GetLineMap()->Remove(addr, HashCodeAddress(addr));
1989 reinterpret_cast<intptr_t>(ptr) | kLineInfoTag); 1985 return static_cast<LineInfo*>(value);
1990 }
1991
1992
1993 static LineInfo* UntagLineInfo(void* ptr) {
1994 return reinterpret_cast<LineInfo*>(reinterpret_cast<intptr_t>(ptr) &
1995 ~kLineInfoTag);
1996 }
1997
1998
1999 void GDBJITInterface::AddCode(Handle<Name> name,
2000 Handle<Script> script,
2001 Handle<Code> code,
2002 CompilationInfo* info) {
2003 if (!FLAG_gdbjit) return;
2004
2005 Script::InitLineEnds(script);
2006
2007 if (!name.is_null() && name->IsString()) {
2008 SmartArrayPointer<char> name_cstring =
2009 Handle<String>::cast(name)->ToCString(DISALLOW_NULLS);
2010 AddCode(name_cstring.get(), *code, GDBJITInterface::FUNCTION, *script,
2011 info);
2012 } else {
2013 AddCode("", *code, GDBJITInterface::FUNCTION, *script, info);
2014 }
2015 } 1986 }
2016 1987
2017 1988
2018 static void AddUnwindInfo(CodeDescription* desc) { 1989 static void AddUnwindInfo(CodeDescription* desc) {
2019 #if V8_TARGET_ARCH_X64 1990 #if V8_TARGET_ARCH_X64
2020 if (desc->tag() == GDBJITInterface::FUNCTION) { 1991 if (desc->is_function()) {
2021 // To avoid propagating unwinding information through 1992 // To avoid propagating unwinding information through
2022 // compilation pipeline we use an approximation. 1993 // compilation pipeline we use an approximation.
2023 // For most use cases this should not affect usability. 1994 // For most use cases this should not affect usability.
2024 static const int kFramePointerPushOffset = 1; 1995 static const int kFramePointerPushOffset = 1;
2025 static const int kFramePointerSetOffset = 4; 1996 static const int kFramePointerSetOffset = 4;
2026 static const int kFramePointerPopOffset = -3; 1997 static const int kFramePointerPopOffset = -3;
2027 1998
2028 uintptr_t frame_pointer_push_address = 1999 uintptr_t frame_pointer_push_address =
2029 desc->CodeStart() + kFramePointerPushOffset; 2000 desc->CodeStart() + kFramePointerPushOffset;
2030 2001
(...skipping 17 matching lines...) Expand all
2048 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP, 2019 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2049 desc->CodeEnd()); 2020 desc->CodeEnd());
2050 } 2021 }
2051 #endif // V8_TARGET_ARCH_X64 2022 #endif // V8_TARGET_ARCH_X64
2052 } 2023 }
2053 2024
2054 2025
2055 static base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER; 2026 static base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
2056 2027
2057 2028
2058 void GDBJITInterface::AddCode(const char* name, 2029 // Remove entries from the splay tree that intersect the given address range,
2059 Code* code, 2030 // and deregister them from GDB.
2060 GDBJITInterface::CodeTag tag, 2031 static void RemoveJITCodeEntries(CodeMap* map, const AddressRange& range) {
2061 Script* script, 2032 DCHECK(range.start < range.end);
2062 CompilationInfo* info) { 2033 CodeMap::Locator cur;
2063 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer()); 2034 if (map->FindGreatestLessThan(range, &cur) || map->FindLeast(&cur)) {
2035 // Skip entries that are entirely less than the range of interest.
2036 while (cur.key().end <= range.start) {
2037 // CodeMap::FindLeastGreaterThan succeeds for entries whose key is greater
2038 // than _or equal to_ the given key, so we have to advance our key to get
2039 // the next one.
2040 AddressRange new_key;
2041 new_key.start = cur.key().end;
2042 new_key.end = 0;
2043 if (!map->FindLeastGreaterThan(new_key, &cur)) return;
2044 }
2045 // Evict intersecting ranges.
2046 while (cur.key().start < range.end) {
2047 AddressRange old_range = cur.key();
2048 JITCodeEntry* old_entry = cur.value();
2049
2050 UnregisterCodeEntry(old_entry);
2051 DestroyCodeEntry(old_entry);
2052
2053 CHECK(map->Remove(old_range));
2054 if (!map->FindLeastGreaterThan(old_range, &cur)) return;
2055 }
2056 }
2057 }
2058
2059
2060 // Insert the entry into the splay tree and register it with GDB.
2061 static void AddJITCodeEntry(CodeMap* map, const AddressRange& range,
2062 JITCodeEntry* entry, bool dump_if_enabled,
2063 const char* name_hint) {
2064 #if defined(DEBUG) && !V8_OS_WIN
2065 static int file_num = 0;
2066 if (FLAG_gdbjit_dump && dump_if_enabled) {
2067 static const int kMaxFileNameSize = 64;
2068 char file_name[64];
2069
2070 SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "/tmp/elfdump%s%d.o",
2071 (name_hint != NULL) ? name_hint : "", file_num++);
2072 WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
2073 }
2074 #endif
2075
2076 CodeMap::Locator cur;
2077 CHECK(map->Insert(range, &cur));
2078 cur.set_value(entry);
2079
2080 RegisterCodeEntry(entry);
2081 }
2082
2083
2084 static void AddCode(const char* name, Code* code, SharedFunctionInfo* shared,
2085 LineInfo* lineinfo) {
2064 DisallowHeapAllocation no_gc; 2086 DisallowHeapAllocation no_gc;
2065 2087
2066 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); 2088 CodeMap* code_map = GetCodeMap();
2067 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; 2089 AddressRange range;
2090 range.start = code->address();
2091 range.end = code->address() + code->CodeSize();
2092 RemoveJITCodeEntries(code_map, range);
2068 2093
2069 LineInfo* lineinfo = UntagLineInfo(e->value); 2094 CodeDescription code_desc(name, code, shared, lineinfo);
2070 CodeDescription code_desc(name,
2071 code,
2072 script != NULL ? Handle<Script>(script)
2073 : Handle<Script>(),
2074 lineinfo,
2075 tag,
2076 info);
2077 2095
2078 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { 2096 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
2079 delete lineinfo; 2097 delete lineinfo;
2080 GetEntries()->Remove(code, HashForCodeObject(code));
2081 return; 2098 return;
2082 } 2099 }
2083 2100
2084 AddUnwindInfo(&code_desc); 2101 AddUnwindInfo(&code_desc);
2085 Isolate* isolate = code->GetIsolate(); 2102 Isolate* isolate = code->GetIsolate();
2086 JITCodeEntry* entry = CreateELFObject(&code_desc, isolate); 2103 JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
2087 DCHECK(!IsLineInfoTagged(entry));
2088 2104
2089 delete lineinfo; 2105 delete lineinfo;
2090 e->value = entry;
2091 2106
2092 const char* name_hint = NULL; 2107 const char* name_hint = NULL;
2093 bool should_dump = false; 2108 bool should_dump = false;
2094 if (FLAG_gdbjit_dump) { 2109 if (FLAG_gdbjit_dump) {
2095 if (strlen(FLAG_gdbjit_dump_filter) == 0) { 2110 if (strlen(FLAG_gdbjit_dump_filter) == 0) {
2096 name_hint = name; 2111 name_hint = name;
2097 should_dump = true; 2112 should_dump = true;
2098 } else if (name != NULL) { 2113 } else if (name != NULL) {
2099 name_hint = strstr(name, FLAG_gdbjit_dump_filter); 2114 name_hint = strstr(name, FLAG_gdbjit_dump_filter);
2100 should_dump = (name_hint != NULL); 2115 should_dump = (name_hint != NULL);
2101 } 2116 }
2102 } 2117 }
2103 RegisterCodeEntry(entry, should_dump, name_hint); 2118 AddJITCodeEntry(code_map, range, entry, should_dump, name_hint);
2104 } 2119 }
2105 2120
2106 2121
2107 void GDBJITInterface::RemoveCode(Code* code) { 2122 void EventHandler(const v8::JitCodeEvent* event) {
2108 if (!FLAG_gdbjit) return; 2123 if (!FLAG_gdbjit) return;
2109
2110 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer()); 2124 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
2111 HashMap::Entry* e = GetEntries()->Lookup(code,
2112 HashForCodeObject(code),
2113 false);
2114 if (e == NULL) return;
2115
2116 if (IsLineInfoTagged(e->value)) {
2117 delete UntagLineInfo(e->value);
2118 } else {
2119 JITCodeEntry* entry = static_cast<JITCodeEntry*>(e->value);
2120 UnregisterCodeEntry(entry);
2121 DestroyCodeEntry(entry);
2122 }
2123 e->value = NULL;
2124 GetEntries()->Remove(code, HashForCodeObject(code));
2125 }
2126
2127
2128 void GDBJITInterface::RemoveCodeRange(Address start, Address end) {
2129 HashMap* entries = GetEntries();
2130 Zone zone;
2131 ZoneList<Code*> dead_codes(1, &zone);
2132
2133 for (HashMap::Entry* e = entries->Start(); e != NULL; e = entries->Next(e)) {
2134 Code* code = reinterpret_cast<Code*>(e->key);
2135 if (code->address() >= start && code->address() < end) {
2136 dead_codes.Add(code, &zone);
2137 }
2138 }
2139
2140 for (int i = 0; i < dead_codes.length(); i++) {
2141 RemoveCode(dead_codes.at(i));
2142 }
2143 }
2144
2145
2146 static void RegisterDetailedLineInfo(Code* code, LineInfo* line_info) {
2147 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
2148 DCHECK(!IsLineInfoTagged(line_info));
2149 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
2150 DCHECK(e->value == NULL);
2151 e->value = TagLineInfo(line_info);
2152 }
2153
2154
2155 void GDBJITInterface::EventHandler(const v8::JitCodeEvent* event) {
2156 if (!FLAG_gdbjit) return;
2157 switch (event->type) { 2125 switch (event->type) {
2158 case v8::JitCodeEvent::CODE_ADDED: { 2126 case v8::JitCodeEvent::CODE_ADDED: {
2159 Code* code = Code::GetCodeFromTargetAddress( 2127 Address addr = reinterpret_cast<Address>(event->code_start);
2160 reinterpret_cast<Address>(event->code_start)); 2128 Code* code = Code::GetCodeFromTargetAddress(addr);
2161 if (code->kind() == Code::OPTIMIZED_FUNCTION || 2129 LineInfo* lineinfo = GetLineInfo(addr);
2162 code->kind() == Code::FUNCTION) {
2163 break;
2164 }
2165 EmbeddedVector<char, 256> buffer; 2130 EmbeddedVector<char, 256> buffer;
2166 StringBuilder builder(buffer.start(), buffer.length()); 2131 StringBuilder builder(buffer.start(), buffer.length());
2167 builder.AddSubstring(event->name.str, static_cast<int>(event->name.len)); 2132 builder.AddSubstring(event->name.str, static_cast<int>(event->name.len));
2168 AddCode(builder.Finalize(), code, NON_FUNCTION, NULL, NULL); 2133 // It's called UnboundScript in the API but it's a SharedFunctionInfo.
2134 SharedFunctionInfo* shared =
2135 event->script.IsEmpty() ? NULL : *Utils::OpenHandle(*event->script);
2136 AddCode(builder.Finalize(), code, shared, lineinfo);
2169 break; 2137 break;
2170 } 2138 }
2171 case v8::JitCodeEvent::CODE_MOVED: 2139 case v8::JitCodeEvent::CODE_MOVED:
2140 // Enabling the GDB JIT interface should disable code compaction.
2141 UNREACHABLE();
2172 break; 2142 break;
2173 case v8::JitCodeEvent::CODE_REMOVED: { 2143 case v8::JitCodeEvent::CODE_REMOVED:
2174 Code* code = Code::GetCodeFromTargetAddress( 2144 // Do nothing. Instead, adding code causes eviction of any entry whose
2175 reinterpret_cast<Address>(event->code_start)); 2145 // address range intersects the address range of the added code.
2176 RemoveCode(code);
2177 break; 2146 break;
2178 }
2179 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: { 2147 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
2180 LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data); 2148 LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
2181 line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset), 2149 line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
2182 static_cast<int>(event->line_info.pos), 2150 static_cast<int>(event->line_info.pos),
2183 event->line_info.position_type == 2151 event->line_info.position_type ==
2184 v8::JitCodeEvent::STATEMENT_POSITION); 2152 v8::JitCodeEvent::STATEMENT_POSITION);
2185 break; 2153 break;
2186 } 2154 }
2187 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: { 2155 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
2188 v8::JitCodeEvent* mutable_event = const_cast<v8::JitCodeEvent*>(event); 2156 v8::JitCodeEvent* mutable_event = const_cast<v8::JitCodeEvent*>(event);
2189 mutable_event->user_data = new LineInfo(); 2157 mutable_event->user_data = new LineInfo();
2190 break; 2158 break;
2191 } 2159 }
2192 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: { 2160 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
2193 LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data); 2161 LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
2194 Code* code = Code::GetCodeFromTargetAddress( 2162 PutLineInfo(reinterpret_cast<Address>(event->code_start), line_info);
2195 reinterpret_cast<Address>(event->code_start));
2196 RegisterDetailedLineInfo(code, line_info);
2197 break; 2163 break;
2198 } 2164 }
2199 } 2165 }
2200 } 2166 }
2201
2202
2203 } } // namespace v8::internal
2204 #endif 2167 #endif
2168 } // namespace GDBJITInterface
2169 } // namespace internal
2170 } // namespace v8
OLDNEW
« no previous file with comments | « src/gdb-jit.h ('k') | src/heap/mark-compact.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698