OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 17 matching lines...) Expand all Loading... |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "api.h" | 30 #include "api.h" |
31 #include "arguments.h" | 31 #include "arguments.h" |
32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
34 #include "compiler.h" | 34 #include "compiler.h" |
35 #include "debug.h" | 35 #include "debug.h" |
36 #include "execution.h" | 36 #include "execution.h" |
37 #include "global-handles.h" | 37 #include "global-handles.h" |
| 38 #include "ic.h" |
| 39 #include "ic-inl.h" |
38 #include "natives.h" | 40 #include "natives.h" |
39 #include "stub-cache.h" | 41 #include "stub-cache.h" |
40 #include "log.h" | 42 #include "log.h" |
41 | 43 |
42 namespace v8 { namespace internal { | 44 namespace v8 { namespace internal { |
43 | 45 |
44 #ifdef ENABLE_DEBUGGER_SUPPORT | 46 #ifdef ENABLE_DEBUGGER_SUPPORT |
45 static void PrintLn(v8::Local<v8::Value> value) { | 47 static void PrintLn(v8::Local<v8::Value> value) { |
46 v8::Local<v8::String> s = value->ToString(); | 48 v8::Local<v8::String> s = value->ToString(); |
47 char* data = NewArray<char>(s->Length() + 1); | 49 char* data = NewArray<char>(s->Length() + 1); |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 // function twice might happen when stepping in a function with an exception | 284 // function twice might happen when stepping in a function with an exception |
283 // handler as the handler and the function is the same. | 285 // handler as the handler and the function is the same. |
284 if (IsDebugBreak()) { | 286 if (IsDebugBreak()) { |
285 return; | 287 return; |
286 } | 288 } |
287 | 289 |
288 if (RelocInfo::IsJSReturn(rmode())) { | 290 if (RelocInfo::IsJSReturn(rmode())) { |
289 // Patch the frame exit code with a break point. | 291 // Patch the frame exit code with a break point. |
290 SetDebugBreakAtReturn(); | 292 SetDebugBreakAtReturn(); |
291 } else { | 293 } else { |
292 // Patch the original code with the current address as the current address | 294 // Patch the IC call. |
293 // might have changed by the inline caching since the code was copied. | 295 SetDebugBreakAtIC(); |
294 original_rinfo()->set_target_address(rinfo()->target_address()); | |
295 | |
296 // Patch the code to invoke the builtin debug break function matching the | |
297 // calling convention used by the call site. | |
298 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(rinfo())); | |
299 rinfo()->set_target_address(dbgbrk_code->entry()); | |
300 } | 296 } |
301 ASSERT(IsDebugBreak()); | 297 ASSERT(IsDebugBreak()); |
302 } | 298 } |
303 | 299 |
304 | 300 |
305 void BreakLocationIterator::ClearDebugBreak() { | 301 void BreakLocationIterator::ClearDebugBreak() { |
306 if (RelocInfo::IsJSReturn(rmode())) { | 302 if (RelocInfo::IsJSReturn(rmode())) { |
307 // Restore the frame exit code. | 303 // Restore the frame exit code. |
308 ClearDebugBreakAtReturn(); | 304 ClearDebugBreakAtReturn(); |
309 } else { | 305 } else { |
310 // Patch the code to the original invoke. | 306 // Patch the IC call. |
311 rinfo()->set_target_address(original_rinfo()->target_address()); | 307 ClearDebugBreakAtIC(); |
312 } | 308 } |
313 ASSERT(!IsDebugBreak()); | 309 ASSERT(!IsDebugBreak()); |
314 } | 310 } |
315 | 311 |
316 | 312 |
317 void BreakLocationIterator::PrepareStepIn() { | 313 void BreakLocationIterator::PrepareStepIn() { |
318 HandleScope scope; | 314 HandleScope scope; |
319 | 315 |
320 // Step in can only be prepared if currently positioned on an IC call or | 316 // Step in can only be prepared if currently positioned on an IC call or |
321 // construct call. | 317 // construct call. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 // Check whether there is a debug break at the current position. | 350 // Check whether there is a debug break at the current position. |
355 bool BreakLocationIterator::IsDebugBreak() { | 351 bool BreakLocationIterator::IsDebugBreak() { |
356 if (RelocInfo::IsJSReturn(rmode())) { | 352 if (RelocInfo::IsJSReturn(rmode())) { |
357 return IsDebugBreakAtReturn(); | 353 return IsDebugBreakAtReturn(); |
358 } else { | 354 } else { |
359 return Debug::IsDebugBreak(rinfo()->target_address()); | 355 return Debug::IsDebugBreak(rinfo()->target_address()); |
360 } | 356 } |
361 } | 357 } |
362 | 358 |
363 | 359 |
| 360 void BreakLocationIterator::SetDebugBreakAtIC() { |
| 361 // Patch the original code with the current address as the current address |
| 362 // might have changed by the inline caching since the code was copied. |
| 363 original_rinfo()->set_target_address(rinfo()->target_address()); |
| 364 |
| 365 RelocInfo::Mode mode = rmode(); |
| 366 if (RelocInfo::IsCodeTarget(mode)) { |
| 367 Address target = rinfo()->target_address(); |
| 368 Handle<Code> code(Code::GetCodeFromTargetAddress(target)); |
| 369 |
| 370 // Patch the code to invoke the builtin debug break function matching the |
| 371 // calling convention used by the call site. |
| 372 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(code, mode)); |
| 373 rinfo()->set_target_address(dbgbrk_code->entry()); |
| 374 |
| 375 // For stubs that refer back to an inlined version clear the cached map for |
| 376 // the inlined case to always go through the IC. As long as the break point |
| 377 // is set the patching performed by the runtime system will take place in |
| 378 // the code copy and will therefore have no effect on the running code |
| 379 // keeping it from using the inlined code. |
| 380 if (code->is_keyed_load_stub() && KeyedLoadIC::HasInlinedVersion(pc())) { |
| 381 KeyedLoadIC::ClearInlinedVersion(pc()); |
| 382 } |
| 383 } |
| 384 } |
| 385 |
| 386 |
| 387 void BreakLocationIterator::ClearDebugBreakAtIC() { |
| 388 // Patch the code to the original invoke. |
| 389 rinfo()->set_target_address(original_rinfo()->target_address()); |
| 390 } |
| 391 |
| 392 |
364 Object* BreakLocationIterator::BreakPointObjects() { | 393 Object* BreakLocationIterator::BreakPointObjects() { |
365 return debug_info_->GetBreakPointObjects(code_position()); | 394 return debug_info_->GetBreakPointObjects(code_position()); |
366 } | 395 } |
367 | 396 |
368 | 397 |
369 // Clear out all the debug break code. This is ONLY supposed to be used when | 398 // Clear out all the debug break code. This is ONLY supposed to be used when |
370 // shutting down the debugger as it will leave the break point information in | 399 // shutting down the debugger as it will leave the break point information in |
371 // DebugInfo even though the code is patched back to the non break point state. | 400 // DebugInfo even though the code is patched back to the non break point state. |
372 void BreakLocationIterator::ClearAllDebugBreak() { | 401 void BreakLocationIterator::ClearAllDebugBreak() { |
373 while (!Done()) { | 402 while (!Done()) { |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 // Check whether a code stub with the specified major key is a possible break | 1078 // Check whether a code stub with the specified major key is a possible break |
1050 // location. | 1079 // location. |
1051 bool Debug::IsBreakStub(Code* code) { | 1080 bool Debug::IsBreakStub(Code* code) { |
1052 CodeStub::Major major_key = code->major_key(); | 1081 CodeStub::Major major_key = code->major_key(); |
1053 return major_key == CodeStub::CallFunction || | 1082 return major_key == CodeStub::CallFunction || |
1054 major_key == CodeStub::StackCheck; | 1083 major_key == CodeStub::StackCheck; |
1055 } | 1084 } |
1056 | 1085 |
1057 | 1086 |
1058 // Find the builtin to use for invoking the debug break | 1087 // Find the builtin to use for invoking the debug break |
1059 Handle<Code> Debug::FindDebugBreak(RelocInfo* rinfo) { | 1088 Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) { |
1060 // Find the builtin debug break function matching the calling convention | 1089 // Find the builtin debug break function matching the calling convention |
1061 // used by the call site. | 1090 // used by the call site. |
1062 RelocInfo::Mode mode = rinfo->rmode(); | 1091 if (code->is_inline_cache_stub()) { |
1063 | 1092 if (code->is_call_stub()) { |
1064 if (RelocInfo::IsCodeTarget(mode)) { | 1093 return ComputeCallDebugBreak(code->arguments_count()); |
1065 Address target = rinfo->target_address(); | |
1066 Code* code = Code::GetCodeFromTargetAddress(target); | |
1067 if (code->is_inline_cache_stub()) { | |
1068 if (code->is_call_stub()) { | |
1069 return ComputeCallDebugBreak(code->arguments_count()); | |
1070 } | |
1071 if (code->is_load_stub()) { | |
1072 return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak)); | |
1073 } | |
1074 if (code->is_store_stub()) { | |
1075 return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak)); | |
1076 } | |
1077 if (code->is_keyed_load_stub()) { | |
1078 Handle<Code> result = | |
1079 Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak)); | |
1080 return result; | |
1081 } | |
1082 if (code->is_keyed_store_stub()) { | |
1083 Handle<Code> result = | |
1084 Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak)); | |
1085 return result; | |
1086 } | |
1087 } | 1094 } |
1088 if (RelocInfo::IsConstructCall(mode)) { | 1095 if (code->is_load_stub()) { |
| 1096 return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak)); |
| 1097 } |
| 1098 if (code->is_store_stub()) { |
| 1099 return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak)); |
| 1100 } |
| 1101 if (code->is_keyed_load_stub()) { |
1089 Handle<Code> result = | 1102 Handle<Code> result = |
1090 Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak)); | 1103 Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak)); |
1091 return result; | 1104 return result; |
1092 } | 1105 } |
1093 if (code->kind() == Code::STUB) { | 1106 if (code->is_keyed_store_stub()) { |
1094 ASSERT(code->major_key() == CodeStub::CallFunction || | |
1095 code->major_key() == CodeStub::StackCheck); | |
1096 Handle<Code> result = | 1107 Handle<Code> result = |
1097 Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak)); | 1108 Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak)); |
1098 return result; | 1109 return result; |
1099 } | 1110 } |
1100 } | 1111 } |
| 1112 if (RelocInfo::IsConstructCall(mode)) { |
| 1113 Handle<Code> result = |
| 1114 Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak)); |
| 1115 return result; |
| 1116 } |
| 1117 if (code->kind() == Code::STUB) { |
| 1118 ASSERT(code->major_key() == CodeStub::CallFunction || |
| 1119 code->major_key() == CodeStub::StackCheck); |
| 1120 Handle<Code> result = |
| 1121 Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak)); |
| 1122 return result; |
| 1123 } |
1101 | 1124 |
1102 UNREACHABLE(); | 1125 UNREACHABLE(); |
1103 return Handle<Code>::null(); | 1126 return Handle<Code>::null(); |
1104 } | 1127 } |
1105 | 1128 |
1106 | 1129 |
1107 // Simple function for returning the source positions for active break points. | 1130 // Simple function for returning the source positions for active break points. |
1108 Handle<Object> Debug::GetSourceBreakLocations( | 1131 Handle<Object> Debug::GetSourceBreakLocations( |
1109 Handle<SharedFunctionInfo> shared) { | 1132 Handle<SharedFunctionInfo> shared) { |
1110 if (!HasDebugInfo(shared)) return Handle<Object>(Heap::undefined_value()); | 1133 if (!HasDebugInfo(shared)) return Handle<Object>(Heap::undefined_value()); |
(...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1832 continue; | 1855 continue; |
1833 } | 1856 } |
1834 | 1857 |
1835 // Invoke JavaScript to process the debug request. | 1858 // Invoke JavaScript to process the debug request. |
1836 v8::Local<v8::String> fun_name; | 1859 v8::Local<v8::String> fun_name; |
1837 v8::Local<v8::Function> fun; | 1860 v8::Local<v8::Function> fun; |
1838 v8::Local<v8::Value> request; | 1861 v8::Local<v8::Value> request; |
1839 v8::TryCatch try_catch; | 1862 v8::TryCatch try_catch; |
1840 fun_name = v8::String::New("processDebugRequest"); | 1863 fun_name = v8::String::New("processDebugRequest"); |
1841 fun = v8::Function::Cast(*cmd_processor->Get(fun_name)); | 1864 fun = v8::Function::Cast(*cmd_processor->Get(fun_name)); |
1842 | 1865 |
1843 request = v8::String::New(command.text().start(), | 1866 request = v8::String::New(command.text().start(), |
1844 command.text().length()); | 1867 command.text().length()); |
1845 command.text().Dispose(); | 1868 command.text().Dispose(); |
1846 static const int kArgc = 1; | 1869 static const int kArgc = 1; |
1847 v8::Handle<Value> argv[kArgc] = { request }; | 1870 v8::Handle<Value> argv[kArgc] = { request }; |
1848 v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv); | 1871 v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv); |
1849 | 1872 |
1850 // Get the response. | 1873 // Get the response. |
1851 v8::Local<v8::String> response; | 1874 v8::Local<v8::String> response; |
1852 bool running = false; | 1875 bool running = false; |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2201 return Message(); | 2224 return Message(); |
2202 } | 2225 } |
2203 | 2226 |
2204 | 2227 |
2205 MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) { | 2228 MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) { |
2206 messages_ = NewArray<Message>(size); | 2229 messages_ = NewArray<Message>(size); |
2207 } | 2230 } |
2208 | 2231 |
2209 | 2232 |
2210 MessageQueue::~MessageQueue() { | 2233 MessageQueue::~MessageQueue() { |
2211 while(!IsEmpty()) { | 2234 while (!IsEmpty()) { |
2212 Message m = Get(); | 2235 Message m = Get(); |
2213 m.Dispose(); | 2236 m.Dispose(); |
2214 } | 2237 } |
2215 DeleteArray(messages_); | 2238 DeleteArray(messages_); |
2216 } | 2239 } |
2217 | 2240 |
2218 | 2241 |
2219 Message MessageQueue::Get() { | 2242 Message MessageQueue::Get() { |
2220 ASSERT(!IsEmpty()); | 2243 ASSERT(!IsEmpty()); |
2221 int result = start_; | 2244 int result = start_; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2279 | 2302 |
2280 | 2303 |
2281 void LockingMessageQueue::Clear() { | 2304 void LockingMessageQueue::Clear() { |
2282 ScopedLock sl(lock_); | 2305 ScopedLock sl(lock_); |
2283 queue_.Clear(); | 2306 queue_.Clear(); |
2284 } | 2307 } |
2285 | 2308 |
2286 #endif // ENABLE_DEBUGGER_SUPPORT | 2309 #endif // ENABLE_DEBUGGER_SUPPORT |
2287 | 2310 |
2288 } } // namespace v8::internal | 2311 } } // namespace v8::internal |
OLD | NEW |