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

Side by Side Diff: src/debug.cc

Issue 1222093007: Debugger: use debug break slot to break on call. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased and addressed comments Created 5 years, 5 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/debug.h ('k') | src/disassembler.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 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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/debug.h ('k') | src/disassembler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698