OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 } | 110 } |
111 // Always update the position as we don't want that to be before the | 111 // Always update the position as we don't want that to be before the |
112 // statement position. | 112 // statement position. |
113 position_ = static_cast<int>(rinfo()->data() - | 113 position_ = static_cast<int>(rinfo()->data() - |
114 debug_info_->shared()->start_position()); | 114 debug_info_->shared()->start_position()); |
115 DCHECK(position_ >= 0); | 115 DCHECK(position_ >= 0); |
116 DCHECK(statement_position_ >= 0); | 116 DCHECK(statement_position_ >= 0); |
117 continue; | 117 continue; |
118 } | 118 } |
119 | 119 |
120 // Check for break at return. | |
121 if (RelocInfo::IsJSReturn(rmode())) { | 120 if (RelocInfo::IsJSReturn(rmode())) { |
122 // Set the positions to the end of the function. | 121 // Set the positions to the end of the function. |
123 if (debug_info_->shared()->HasSourceCode()) { | 122 if (debug_info_->shared()->HasSourceCode()) { |
124 position_ = debug_info_->shared()->end_position() - | 123 position_ = debug_info_->shared()->end_position() - |
125 debug_info_->shared()->start_position() - 1; | 124 debug_info_->shared()->start_position() - 1; |
126 } else { | 125 } else { |
127 position_ = 0; | 126 position_ = 0; |
128 } | 127 } |
129 statement_position_ = position_; | 128 statement_position_ = position_; |
130 break_index_++; | |
131 break; | 129 break; |
132 } | 130 } |
133 | 131 |
134 if (RelocInfo::IsCodeTarget(rmode())) { | 132 if (RelocInfo::IsDebugBreakSlot(rmode()) && |
135 // Check for breakable code target. Look in the original code as setting | 133 (type_ == ALL_BREAK_LOCATIONS || |
136 // break points can cause the code targets in the running (debugged) code | 134 RelocInfo::DebugBreakIsCall(rinfo()->data()))) { |
137 // to be of a different kind than in the original code. | |
138 Address target = original_rinfo()->target_address(); | |
139 Code* code = Code::GetCodeFromTargetAddress(target); | |
140 | |
141 if (RelocInfo::IsConstructCall(rmode()) || code->is_call_stub()) { | |
142 break_index_++; | |
143 break; | |
144 } | |
145 | |
146 if (code->kind() == Code::STUB && | |
147 CodeStub::GetMajorKey(code) == CodeStub::CallFunction) { | |
148 break_index_++; | |
149 break; | |
150 } | |
151 } | |
152 | |
153 // Skip below if we only want locations for calls and returns. | |
154 if (type_ == CALLS_AND_RETURNS) continue; | |
155 | |
156 if (RelocInfo::IsDebuggerStatement(rmode())) { | |
157 break_index_++; | |
158 break; | 135 break; |
159 } | 136 } |
160 | 137 |
161 if (RelocInfo::IsDebugBreakSlot(rmode()) && type_ != CALLS_AND_RETURNS) { | 138 if (RelocInfo::IsDebuggerStatement(rmode()) && |
162 // There is always a possible break point at a debug break slot. | 139 type_ == ALL_BREAK_LOCATIONS) { |
163 break_index_++; | |
164 break; | 140 break; |
165 } | 141 } |
166 } | 142 } |
| 143 break_index_++; |
167 } | 144 } |
168 | 145 |
169 | 146 |
170 // Find the break point at the supplied address, or the closest one before | 147 // Find the break point at the supplied address, or the closest one before |
171 // the address. | 148 // the address. |
172 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info, | 149 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info, |
173 BreakLocatorType type, Address pc) { | 150 BreakLocatorType type, Address pc) { |
174 Iterator it(debug_info, type); | 151 Iterator it(debug_info, type); |
175 it.SkipTo(BreakIndexFromAddress(debug_info, type, pc)); | 152 it.SkipTo(BreakIndexFromAddress(debug_info, type, pc)); |
176 return it.GetBreakLocation(); | 153 return it.GetBreakLocation(); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 // function twice might happen when stepping in a function with an exception | 281 // function twice might happen when stepping in a function with an exception |
305 // handler as the handler and the function is the same. | 282 // handler as the handler and the function is the same. |
306 if (IsDebugBreak()) return; | 283 if (IsDebugBreak()) return; |
307 | 284 |
308 if (IsExit()) { | 285 if (IsExit()) { |
309 // Patch the frame exit code with a break point. | 286 // Patch the frame exit code with a break point. |
310 SetDebugBreakAtReturn(); | 287 SetDebugBreakAtReturn(); |
311 } else if (IsDebugBreakSlot()) { | 288 } else if (IsDebugBreakSlot()) { |
312 // Patch the code in the break slot. | 289 // Patch the code in the break slot. |
313 SetDebugBreakAtSlot(); | 290 SetDebugBreakAtSlot(); |
314 } else { | |
315 // Patch the IC call. | |
316 SetDebugBreakAtIC(); | |
317 } | 291 } |
318 DCHECK(IsDebugBreak()); | 292 DCHECK(IsDebugBreak()); |
319 } | 293 } |
320 | 294 |
321 | 295 |
322 void BreakLocation::ClearDebugBreak() { | 296 void BreakLocation::ClearDebugBreak() { |
323 // Debugger statement always calls debugger. No need to modify it. | 297 // Debugger statement always calls debugger. No need to modify it. |
324 if (IsDebuggerStatement()) return; | 298 if (IsDebuggerStatement()) return; |
325 | 299 |
326 if (IsExit()) { | 300 if (IsExit()) { |
327 // Restore the frame exit code with a break point. | 301 // Restore the frame exit code with a break point. |
328 RestoreFromOriginal(Assembler::kJSReturnSequenceLength); | 302 RestoreFromOriginal(Assembler::kJSReturnSequenceLength); |
329 } else if (IsDebugBreakSlot()) { | 303 } else if (IsDebugBreakSlot()) { |
330 // Restore the code in the break slot. | 304 // Restore the code in the break slot. |
331 RestoreFromOriginal(Assembler::kDebugBreakSlotLength); | 305 RestoreFromOriginal(Assembler::kDebugBreakSlotLength); |
332 } else { | |
333 // Restore the IC call. | |
334 rinfo().set_target_address(original_rinfo().target_address()); | |
335 // Some ICs store data in the feedback vector. Clear this to ensure we | |
336 // won't miss future stepping requirements. | |
337 SharedFunctionInfo* shared = debug_info_->shared(); | |
338 shared->feedback_vector()->ClearICSlots(shared); | |
339 } | 306 } |
340 DCHECK(!IsDebugBreak()); | 307 DCHECK(!IsDebugBreak()); |
341 } | 308 } |
342 | 309 |
343 | 310 |
344 void BreakLocation::RestoreFromOriginal(int length_in_bytes) { | 311 void BreakLocation::RestoreFromOriginal(int length_in_bytes) { |
345 memcpy(pc(), original_pc(), length_in_bytes); | 312 memcpy(pc(), original_pc(), length_in_bytes); |
346 CpuFeatures::FlushICache(pc(), length_in_bytes); | 313 CpuFeatures::FlushICache(pc(), length_in_bytes); |
347 } | 314 } |
348 | 315 |
349 | 316 |
350 bool BreakLocation::IsStepInLocation() const { | 317 bool BreakLocation::IsStepInLocation() const { |
351 if (IsConstructCall()) return true; | 318 return IsConstructCall() || IsCall(); |
352 if (RelocInfo::IsCodeTarget(rmode())) { | |
353 HandleScope scope(debug_info_->GetIsolate()); | |
354 Handle<Code> target_code = CodeTarget(); | |
355 return target_code->is_call_stub(); | |
356 } | |
357 return false; | |
358 } | 319 } |
359 | 320 |
360 | 321 |
361 bool BreakLocation::IsDebugBreak() const { | 322 bool BreakLocation::IsDebugBreak() const { |
362 if (IsExit()) { | 323 if (IsExit()) { |
363 return rinfo().IsPatchedReturnSequence(); | 324 return rinfo().IsPatchedReturnSequence(); |
364 } else if (IsDebugBreakSlot()) { | 325 } else if (IsDebugBreakSlot()) { |
365 return rinfo().IsPatchedDebugBreakSlotSequence(); | 326 return rinfo().IsPatchedDebugBreakSlotSequence(); |
366 } else { | |
367 return Debug::IsDebugBreak(rinfo().target_address()); | |
368 } | 327 } |
| 328 return false; |
369 } | 329 } |
370 | 330 |
371 | 331 |
372 // Find the builtin to use for invoking the debug break | |
373 static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) { | |
374 Isolate* isolate = code->GetIsolate(); | |
375 | |
376 // Find the builtin debug break function matching the calling convention | |
377 // used by the call site. | |
378 if (code->is_inline_cache_stub()) { | |
379 DCHECK(code->kind() == Code::CALL_IC); | |
380 return isolate->builtins()->CallICStub_DebugBreak(); | |
381 } | |
382 if (RelocInfo::IsConstructCall(mode)) { | |
383 if (code->has_function_cache()) { | |
384 return isolate->builtins()->CallConstructStub_Recording_DebugBreak(); | |
385 } else { | |
386 return isolate->builtins()->CallConstructStub_DebugBreak(); | |
387 } | |
388 } | |
389 if (code->kind() == Code::STUB) { | |
390 DCHECK(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction); | |
391 return isolate->builtins()->CallFunctionStub_DebugBreak(); | |
392 } | |
393 | |
394 UNREACHABLE(); | |
395 return Handle<Code>::null(); | |
396 } | |
397 | |
398 | |
399 void BreakLocation::SetDebugBreakAtIC() { | |
400 // Patch the original code with the current address as the current address | |
401 // might have changed by the inline caching since the code was copied. | |
402 original_rinfo().set_target_address(rinfo().target_address()); | |
403 | |
404 if (RelocInfo::IsCodeTarget(rmode_)) { | |
405 Handle<Code> target_code = CodeTarget(); | |
406 | |
407 // Patch the code to invoke the builtin debug break function matching the | |
408 // calling convention used by the call site. | |
409 Handle<Code> debug_break_code = DebugBreakForIC(target_code, rmode_); | |
410 rinfo().set_target_address(debug_break_code->entry()); | |
411 } | |
412 } | |
413 | |
414 | |
415 Handle<Object> BreakLocation::BreakPointObjects() const { | 332 Handle<Object> BreakLocation::BreakPointObjects() const { |
416 return debug_info_->GetBreakPointObjects(pc_offset_); | 333 return debug_info_->GetBreakPointObjects(pc_offset_); |
417 } | 334 } |
418 | 335 |
419 | 336 |
420 Handle<Code> BreakLocation::CodeTarget() const { | |
421 DCHECK(IsCodeTarget()); | |
422 Address target = rinfo().target_address(); | |
423 return Handle<Code>(Code::GetCodeFromTargetAddress(target)); | |
424 } | |
425 | |
426 | |
427 Handle<Code> BreakLocation::OriginalCodeTarget() const { | |
428 DCHECK(IsCodeTarget()); | |
429 Address target = original_rinfo().target_address(); | |
430 return Handle<Code>(Code::GetCodeFromTargetAddress(target)); | |
431 } | |
432 | |
433 | |
434 bool BreakLocation::Iterator::RinfoDone() const { | 337 bool BreakLocation::Iterator::RinfoDone() const { |
435 DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done()); | 338 DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done()); |
436 return reloc_iterator_.done(); | 339 return reloc_iterator_.done(); |
437 } | 340 } |
438 | 341 |
439 | 342 |
440 void BreakLocation::Iterator::RinfoNext() { | 343 void BreakLocation::Iterator::RinfoNext() { |
441 reloc_iterator_.next(); | 344 reloc_iterator_.next(); |
442 reloc_iterator_original_.next(); | 345 reloc_iterator_original_.next(); |
443 #ifdef DEBUG | 346 #ifdef DEBUG |
444 DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done()); | 347 DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done()); |
445 DCHECK(reloc_iterator_.done() || rmode() == original_rmode()); | 348 DCHECK(reloc_iterator_.done() || rmode() == original_rinfo()->rmode()); |
446 #endif | 349 #endif |
447 } | 350 } |
448 | 351 |
449 | 352 |
450 // Threading support. | 353 // Threading support. |
451 void Debug::ThreadInit() { | 354 void Debug::ThreadInit() { |
452 thread_local_.break_count_ = 0; | 355 thread_local_.break_count_ = 0; |
453 thread_local_.break_id_ = 0; | 356 thread_local_.break_id_ = 0; |
454 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 357 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
455 thread_local_.last_step_action_ = StepNone; | 358 thread_local_.last_step_action_ = StepNone; |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 // Return if retrieving debug info failed. | 837 // Return if retrieving debug info failed. |
935 return true; | 838 return true; |
936 } | 839 } |
937 | 840 |
938 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 841 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
939 // Source positions starts with zero. | 842 // Source positions starts with zero. |
940 DCHECK(*source_position >= 0); | 843 DCHECK(*source_position >= 0); |
941 | 844 |
942 // Find the break point and change it. | 845 // Find the break point and change it. |
943 BreakLocation location = BreakLocation::FromPosition( | 846 BreakLocation location = BreakLocation::FromPosition( |
944 debug_info, SOURCE_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED); | 847 debug_info, ALL_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED); |
945 *source_position = location.statement_position(); | 848 *source_position = location.statement_position(); |
946 location.SetBreakPoint(break_point_object); | 849 location.SetBreakPoint(break_point_object); |
947 | 850 |
948 // At least one active break point now. | 851 // At least one active break point now. |
949 return debug_info->GetBreakPointCount() > 0; | 852 return debug_info->GetBreakPointCount() > 0; |
950 } | 853 } |
951 | 854 |
952 | 855 |
953 bool Debug::SetBreakPointForScript(Handle<Script> script, | 856 bool Debug::SetBreakPointForScript(Handle<Script> script, |
954 Handle<Object> break_point_object, | 857 Handle<Object> break_point_object, |
(...skipping 23 matching lines...) Expand all Loading... |
978 } else { | 881 } else { |
979 position = *source_position - shared->start_position(); | 882 position = *source_position - shared->start_position(); |
980 } | 883 } |
981 | 884 |
982 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 885 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
983 // Source positions starts with zero. | 886 // Source positions starts with zero. |
984 DCHECK(position >= 0); | 887 DCHECK(position >= 0); |
985 | 888 |
986 // Find the break point and change it. | 889 // Find the break point and change it. |
987 BreakLocation location = BreakLocation::FromPosition( | 890 BreakLocation location = BreakLocation::FromPosition( |
988 debug_info, SOURCE_BREAK_LOCATIONS, position, alignment); | 891 debug_info, ALL_BREAK_LOCATIONS, position, alignment); |
989 location.SetBreakPoint(break_point_object); | 892 location.SetBreakPoint(break_point_object); |
990 | 893 |
991 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position() | 894 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position() |
992 : location.position(); | 895 : location.position(); |
993 | 896 |
994 *source_position = position + shared->start_position(); | 897 *source_position = position + shared->start_position(); |
995 | 898 |
996 // At least one active break point now. | 899 // At least one active break point now. |
997 DCHECK(debug_info->GetBreakPointCount() > 0); | 900 DCHECK(debug_info->GetBreakPointCount() > 0); |
998 return true; | 901 return true; |
(...skipping 11 matching lines...) Expand all Loading... |
1010 // Get information in the break point. | 913 // Get information in the break point. |
1011 Handle<BreakPointInfo> break_point_info = | 914 Handle<BreakPointInfo> break_point_info = |
1012 Handle<BreakPointInfo>::cast(result); | 915 Handle<BreakPointInfo>::cast(result); |
1013 Handle<DebugInfo> debug_info = node->debug_info(); | 916 Handle<DebugInfo> debug_info = node->debug_info(); |
1014 | 917 |
1015 // Find the break point and clear it. | 918 // Find the break point and clear it. |
1016 Address pc = debug_info->code()->entry() + | 919 Address pc = debug_info->code()->entry() + |
1017 break_point_info->code_position()->value(); | 920 break_point_info->code_position()->value(); |
1018 | 921 |
1019 BreakLocation location = | 922 BreakLocation location = |
1020 BreakLocation::FromAddress(debug_info, SOURCE_BREAK_LOCATIONS, pc); | 923 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, pc); |
1021 location.ClearBreakPoint(break_point_object); | 924 location.ClearBreakPoint(break_point_object); |
1022 | 925 |
1023 // If there are no more break points left remove the debug info for this | 926 // If there are no more break points left remove the debug info for this |
1024 // function. | 927 // function. |
1025 if (debug_info->GetBreakPointCount() == 0) { | 928 if (debug_info->GetBreakPointCount() == 0) { |
1026 RemoveDebugInfoAndClearFromShared(debug_info); | 929 RemoveDebugInfoAndClearFromShared(debug_info); |
1027 } | 930 } |
1028 | 931 |
1029 return; | 932 return; |
1030 } | 933 } |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 // Compute whether or not the target is a call target. | 1134 // Compute whether or not the target is a call target. |
1232 bool is_at_restarted_function = false; | 1135 bool is_at_restarted_function = false; |
1233 Handle<Code> call_function_stub; | 1136 Handle<Code> call_function_stub; |
1234 | 1137 |
1235 // PC points to the instruction after the current one, possibly a break | 1138 // PC points to the instruction after the current one, possibly a break |
1236 // location as well. So the "- 1" to exclude it from the search. | 1139 // location as well. So the "- 1" to exclude it from the search. |
1237 Address call_pc = summary.pc() - 1; | 1140 Address call_pc = summary.pc() - 1; |
1238 BreakLocation location = | 1141 BreakLocation location = |
1239 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); | 1142 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); |
1240 | 1143 |
1241 if (thread_local_.restarter_frame_function_pointer_ == NULL) { | 1144 if (thread_local_.restarter_frame_function_pointer_ != NULL) { |
1242 if (location.IsCodeTarget()) { | |
1243 Handle<Code> target_code = location.CodeTarget(); | |
1244 | |
1245 // Check if target code is CallFunction stub. | |
1246 Handle<Code> maybe_call_function_stub = target_code; | |
1247 // If there is a breakpoint at this line look at the original code to | |
1248 // check if it is a CallFunction stub. | |
1249 if (location.IsDebugBreak()) { | |
1250 maybe_call_function_stub = location.OriginalCodeTarget(); | |
1251 } | |
1252 if ((maybe_call_function_stub->kind() == Code::STUB && | |
1253 CodeStub::GetMajorKey(*maybe_call_function_stub) == | |
1254 CodeStub::CallFunction) || | |
1255 maybe_call_function_stub->is_call_stub()) { | |
1256 // Save reference to the code as we may need it to find out arguments | |
1257 // count for 'step in' later. | |
1258 call_function_stub = maybe_call_function_stub; | |
1259 } | |
1260 } | |
1261 } else { | |
1262 is_at_restarted_function = true; | 1145 is_at_restarted_function = true; |
1263 } | 1146 } |
1264 | 1147 |
1265 // If this is the last break code target step out is the only possibility. | 1148 // If this is the last break code target step out is the only possibility. |
1266 if (location.IsExit() || step_action == StepOut) { | 1149 if (location.IsExit() || step_action == StepOut) { |
1267 if (step_action == StepOut) { | 1150 if (step_action == StepOut) { |
1268 // Skip step_count frames starting with the current one. | 1151 // Skip step_count frames starting with the current one. |
1269 while (step_count-- > 0 && !frames_it.done()) { | 1152 while (step_count-- > 0 && !frames_it.done()) { |
1270 frames_it.Advance(); | 1153 frames_it.Advance(); |
1271 } | 1154 } |
(...skipping 18 matching lines...) Expand all Loading... |
1290 return; | 1173 return; |
1291 } | 1174 } |
1292 | 1175 |
1293 if (step_action != StepNext && step_action != StepMin) { | 1176 if (step_action != StepNext && step_action != StepMin) { |
1294 // If there's restarter frame on top of the stack, just get the pointer | 1177 // If there's restarter frame on top of the stack, just get the pointer |
1295 // to function which is going to be restarted. | 1178 // to function which is going to be restarted. |
1296 if (is_at_restarted_function) { | 1179 if (is_at_restarted_function) { |
1297 Handle<JSFunction> restarted_function( | 1180 Handle<JSFunction> restarted_function( |
1298 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_)); | 1181 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_)); |
1299 FloodWithOneShot(restarted_function); | 1182 FloodWithOneShot(restarted_function); |
1300 } else if (!call_function_stub.is_null()) { | 1183 } else if (location.IsCall()) { |
1301 // If it's CallFunction stub ensure target function is compiled and flood | |
1302 // it with one shot breakpoints. | |
1303 bool is_call_ic = call_function_stub->kind() == Code::CALL_IC; | |
1304 | |
1305 // Find out number of arguments from the stub minor key. | |
1306 uint32_t key = call_function_stub->stub_key(); | |
1307 // Argc in the stub is the number of arguments passed - not the | |
1308 // expected arguments of the called function. | |
1309 int call_function_arg_count = is_call_ic | |
1310 ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key)) | |
1311 : CallFunctionStub::ExtractArgcFromMinorKey( | |
1312 CodeStub::MinorKeyFromKey(key)); | |
1313 | |
1314 DCHECK(is_call_ic || | |
1315 CodeStub::GetMajorKey(*call_function_stub) == | |
1316 CodeStub::MajorKeyFromKey(key)); | |
1317 | |
1318 // Find target function on the expression stack. | 1184 // Find target function on the expression stack. |
1319 // Expression stack looks like this (top to bottom): | 1185 // Expression stack looks like this (top to bottom): |
1320 // argN | 1186 // argN |
1321 // ... | 1187 // ... |
1322 // arg0 | 1188 // arg0 |
1323 // Receiver | 1189 // Receiver |
1324 // Function to call | 1190 // Function to call |
1325 int expressions_count = frame->ComputeExpressionsCount(); | 1191 int num_expressions_without_args = |
1326 DCHECK(expressions_count - 2 - call_function_arg_count >= 0); | 1192 frame->ComputeExpressionsCount() - location.CallArgumentsCount(); |
1327 Object* fun = frame->GetExpression( | 1193 DCHECK(num_expressions_without_args >= 2); |
1328 expressions_count - 2 - call_function_arg_count); | 1194 Object* fun = frame->GetExpression(num_expressions_without_args - 2); |
1329 | 1195 |
1330 // Flood the actual target of call/apply. | 1196 // Flood the actual target of call/apply. |
1331 if (fun->IsJSFunction()) { | 1197 if (fun->IsJSFunction()) { |
1332 Isolate* isolate = JSFunction::cast(fun)->GetIsolate(); | 1198 Isolate* isolate = JSFunction::cast(fun)->GetIsolate(); |
1333 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply); | 1199 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply); |
1334 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall); | 1200 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall); |
1335 // Find target function on the expression stack for expression like | 1201 // Find target function on the expression stack for expression like |
1336 // Function.call.call...apply(...) | 1202 // Function.call.call...apply(...) |
1337 int i = 1; | 1203 int i = 1; |
1338 while (fun->IsJSFunction()) { | 1204 while (fun->IsJSFunction()) { |
1339 Code* code = JSFunction::cast(fun)->shared()->code(); | 1205 Code* code = JSFunction::cast(fun)->shared()->code(); |
1340 if (code != apply && code != call) break; | 1206 if (code != apply && code != call) break; |
1341 DCHECK(expressions_count - i - call_function_arg_count >= 0); | 1207 DCHECK(num_expressions_without_args >= i); |
1342 fun = frame->GetExpression(expressions_count - i - | 1208 fun = frame->GetExpression(num_expressions_without_args - i); |
1343 call_function_arg_count); | 1209 i--; |
1344 i -= 1; | |
1345 } | 1210 } |
1346 } | 1211 } |
1347 | 1212 |
1348 if (fun->IsJSFunction()) { | 1213 if (fun->IsJSFunction()) { |
1349 Handle<JSFunction> js_function(JSFunction::cast(fun)); | 1214 Handle<JSFunction> js_function(JSFunction::cast(fun)); |
1350 FloodWithOneShotGeneric(js_function); | 1215 FloodWithOneShotGeneric(js_function); |
1351 } | 1216 } |
1352 } | 1217 } |
1353 | 1218 |
1354 ActivateStepIn(frame); | 1219 ActivateStepIn(frame); |
(...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2202 } | 2067 } |
2203 | 2068 |
2204 // Move back to where the call instruction sequence started. | 2069 // Move back to where the call instruction sequence started. |
2205 after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset; | 2070 after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset; |
2206 } else if (at_debug_break_slot) { | 2071 } else if (at_debug_break_slot) { |
2207 // Address of where the debug break slot starts. | 2072 // Address of where the debug break slot starts. |
2208 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset; | 2073 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset; |
2209 | 2074 |
2210 // Continue just after the slot. | 2075 // Continue just after the slot. |
2211 after_break_target_ = addr + Assembler::kDebugBreakSlotLength; | 2076 after_break_target_ = addr + Assembler::kDebugBreakSlotLength; |
2212 } else { | |
2213 addr = Assembler::target_address_from_return_address(frame->pc()); | |
2214 if (IsDebugBreak(Assembler::target_address_at(addr, *code))) { | |
2215 // We now know that there is still a debug break call at the target | |
2216 // address, so the break point is still there and the original code will | |
2217 // hold the address to jump to in order to complete the call which is | |
2218 // replaced by a call to DebugBreakXXX. | |
2219 | |
2220 // Find the corresponding address in the original code. | |
2221 addr += original_code->instruction_start() - code->instruction_start(); | |
2222 | |
2223 // Install jump to the call address in the original code. This will be the | |
2224 // call which was overwritten by the call to DebugBreakXXX. | |
2225 after_break_target_ = Assembler::target_address_at(addr, *original_code); | |
2226 } else { | |
2227 // There is no longer a break point present. Don't try to look in the | |
2228 // original code as the running code will have the right address. This | |
2229 // takes care of the case where the last break point is removed from the | |
2230 // function and therefore no "original code" is available. | |
2231 after_break_target_ = Assembler::target_address_at(addr, *code); | |
2232 } | |
2233 } | 2077 } |
2234 } | 2078 } |
2235 | 2079 |
2236 | 2080 |
2237 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 2081 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
2238 HandleScope scope(isolate_); | 2082 HandleScope scope(isolate_); |
2239 | 2083 |
2240 // If there are no break points this cannot be break at return, as | 2084 // If there are no break points this cannot be break at return, as |
2241 // the debugger statement and stack guard debug break cannot be at | 2085 // the debugger statement and stack guard debug break cannot be at |
2242 // return. | 2086 // return. |
(...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3327 } | 3171 } |
3328 | 3172 |
3329 | 3173 |
3330 void LockingCommandMessageQueue::Clear() { | 3174 void LockingCommandMessageQueue::Clear() { |
3331 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 3175 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
3332 queue_.Clear(); | 3176 queue_.Clear(); |
3333 } | 3177 } |
3334 | 3178 |
3335 } // namespace internal | 3179 } // namespace internal |
3336 } // namespace v8 | 3180 } // namespace v8 |
OLD | NEW |