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

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

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