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