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

Side by Side Diff: src/debug.cc

Issue 1234833003: Debugger: use debug break slots to break at function exit. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix for arm 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/factory.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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); 52 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
53 // Isolate::context() may have been NULL when "script collected" event 53 // Isolate::context() may have been NULL when "script collected" event
54 // occured. 54 // occured.
55 if (context.is_null()) return v8::Local<v8::Context>(); 55 if (context.is_null()) return v8::Local<v8::Context>();
56 Handle<Context> native_context(context->native_context()); 56 Handle<Context> native_context(context->native_context());
57 return v8::Utils::ToLocal(native_context); 57 return v8::Utils::ToLocal(native_context);
58 } 58 }
59 59
60 60
61 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo, 61 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo,
62 RelocInfo* original_rinfo, int position, 62 int position, int statement_position)
63 int statement_position)
64 : debug_info_(debug_info), 63 : debug_info_(debug_info),
65 pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())), 64 pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())),
66 original_pc_offset_(static_cast<int>(
67 original_rinfo->pc() - debug_info->original_code()->entry())),
68 rmode_(rinfo->rmode()), 65 rmode_(rinfo->rmode()),
69 original_rmode_(original_rinfo->rmode()),
70 data_(rinfo->data()), 66 data_(rinfo->data()),
71 original_data_(original_rinfo->data()),
72 position_(position), 67 position_(position),
73 statement_position_(statement_position) {} 68 statement_position_(statement_position) {}
74 69
75 70
76 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, 71 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
77 BreakLocatorType type) 72 BreakLocatorType type)
78 : debug_info_(debug_info), 73 : debug_info_(debug_info),
79 reloc_iterator_(debug_info->code(), GetModeMask(type)), 74 reloc_iterator_(debug_info->code(), GetModeMask(type)),
80 reloc_iterator_original_(debug_info->original_code(), GetModeMask(type)),
81 break_index_(-1), 75 break_index_(-1),
82 position_(1), 76 position_(1),
83 statement_position_(1) { 77 statement_position_(1) {
84 if (!RinfoDone()) Next(); 78 if (!Done()) Next();
85 } 79 }
86 80
87 81
88 int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) { 82 int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) {
89 int mask = 0; 83 int mask = 0;
90 mask |= RelocInfo::ModeMask(RelocInfo::POSITION); 84 mask |= RelocInfo::ModeMask(RelocInfo::POSITION);
91 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION); 85 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION);
92 mask |= RelocInfo::ModeMask(RelocInfo::JS_RETURN); 86 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
93 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); 87 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
94 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CONSTRUCT_CALL); 88 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CONSTRUCT_CALL);
95 if (type == ALL_BREAK_LOCATIONS) { 89 if (type == ALL_BREAK_LOCATIONS) {
96 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION); 90 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
97 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT); 91 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT);
98 } 92 }
99 return mask; 93 return mask;
100 } 94 }
101 95
102 96
103 void BreakLocation::Iterator::Next() { 97 void BreakLocation::Iterator::Next() {
104 DisallowHeapAllocation no_gc; 98 DisallowHeapAllocation no_gc;
105 DCHECK(!RinfoDone()); 99 DCHECK(!Done());
106 100
107 // Iterate through reloc info for code and original code stopping at each 101 // Iterate through reloc info for code and original code stopping at each
108 // breakable code target. 102 // breakable code target.
109 bool first = break_index_ == -1; 103 bool first = break_index_ == -1;
110 while (!RinfoDone()) { 104 while (!Done()) {
111 if (!first) RinfoNext(); 105 if (!first) reloc_iterator_.next();
112 first = false; 106 first = false;
113 if (RinfoDone()) return; 107 if (Done()) return;
114 108
115 // Whenever a statement position or (plain) position is passed update the 109 // Whenever a statement position or (plain) position is passed update the
116 // current value of these. 110 // current value of these.
117 if (RelocInfo::IsPosition(rmode())) { 111 if (RelocInfo::IsPosition(rmode())) {
118 if (RelocInfo::IsStatementPosition(rmode())) { 112 if (RelocInfo::IsStatementPosition(rmode())) {
119 statement_position_ = static_cast<int>( 113 statement_position_ = static_cast<int>(
120 rinfo()->data() - debug_info_->shared()->start_position()); 114 rinfo()->data() - debug_info_->shared()->start_position());
121 } 115 }
122 // Always update the position as we don't want that to be before the 116 // Always update the position as we don't want that to be before the
123 // statement position. 117 // statement position.
124 position_ = static_cast<int>(rinfo()->data() - 118 position_ = static_cast<int>(rinfo()->data() -
125 debug_info_->shared()->start_position()); 119 debug_info_->shared()->start_position());
126 DCHECK(position_ >= 0); 120 DCHECK(position_ >= 0);
127 DCHECK(statement_position_ >= 0); 121 DCHECK(statement_position_ >= 0);
128 continue; 122 continue;
129 } 123 }
130 124
131 if (RelocInfo::IsJSReturn(rmode())) { 125 DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) ||
126 RelocInfo::IsDebuggerStatement(rmode()));
127
128 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
132 // Set the positions to the end of the function. 129 // Set the positions to the end of the function.
133 if (debug_info_->shared()->HasSourceCode()) { 130 if (debug_info_->shared()->HasSourceCode()) {
134 position_ = debug_info_->shared()->end_position() - 131 position_ = debug_info_->shared()->end_position() -
135 debug_info_->shared()->start_position() - 1; 132 debug_info_->shared()->start_position() - 1;
136 } else { 133 } else {
137 position_ = 0; 134 position_ = 0;
138 } 135 }
139 statement_position_ = position_; 136 statement_position_ = position_;
140 break;
141 } 137 }
142 138
143 DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) ||
144 RelocInfo::IsDebuggerStatement(rmode()));
145 break; 139 break;
146 } 140 }
147 break_index_++; 141 break_index_++;
148 } 142 }
149 143
150 144
151 // Find the break point at the supplied address, or the closest one before 145 // Find the break point at the supplied address, or the closest one before
152 // the address. 146 // the address.
153 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info, 147 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info,
154 BreakLocatorType type, Address pc) { 148 BreakLocatorType type, Address pc) {
149 DCHECK(debug_info->code()->has_debug_break_slots());
155 Iterator it(debug_info, type); 150 Iterator it(debug_info, type);
156 it.SkipTo(BreakIndexFromAddress(debug_info, type, pc)); 151 it.SkipTo(BreakIndexFromAddress(debug_info, type, pc));
157 return it.GetBreakLocation(); 152 return it.GetBreakLocation();
158 } 153 }
159 154
160 155
161 // Find the break point at the supplied address, or the closest one before 156 // Find the break point at the supplied address, or the closest one before
162 // the address. 157 // the address.
163 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info, 158 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info,
164 BreakLocatorType type, Address pc, 159 BreakLocatorType type, Address pc,
165 List<BreakLocation>* result_out) { 160 List<BreakLocation>* result_out) {
161 DCHECK(debug_info->code()->has_debug_break_slots());
166 int break_index = BreakIndexFromAddress(debug_info, type, pc); 162 int break_index = BreakIndexFromAddress(debug_info, type, pc);
167 Iterator it(debug_info, type); 163 Iterator it(debug_info, type);
168 it.SkipTo(break_index); 164 it.SkipTo(break_index);
169 int statement_position = it.statement_position(); 165 int statement_position = it.statement_position();
170 while (!it.Done() && it.statement_position() == statement_position) { 166 while (!it.Done() && it.statement_position() == statement_position) {
171 result_out->Add(it.GetBreakLocation()); 167 result_out->Add(it.GetBreakLocation());
172 it.Next(); 168 it.Next();
173 } 169 }
174 } 170 }
175 171
(...skipping 12 matching lines...) Expand all
188 if (distance == 0) break; 184 if (distance == 0) break;
189 } 185 }
190 } 186 }
191 return closest_break; 187 return closest_break;
192 } 188 }
193 189
194 190
195 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info, 191 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
196 BreakLocatorType type, int position, 192 BreakLocatorType type, int position,
197 BreakPositionAlignment alignment) { 193 BreakPositionAlignment alignment) {
194 DCHECK(debug_info->code()->has_debug_break_slots());
198 // Run through all break points to locate the one closest to the source 195 // Run through all break points to locate the one closest to the source
199 // position. 196 // position.
200 int closest_break = 0; 197 int closest_break = 0;
201 int distance = kMaxInt; 198 int distance = kMaxInt;
202 199
203 for (Iterator it(debug_info, type); !it.Done(); it.Next()) { 200 for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
204 int next_position; 201 int next_position;
205 if (alignment == STATEMENT_ALIGNED) { 202 if (alignment == STATEMENT_ALIGNED) {
206 next_position = it.statement_position(); 203 next_position = it.statement_position();
207 } else { 204 } else {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 void BreakLocation::SetDebugBreak() { 276 void BreakLocation::SetDebugBreak() {
280 // Debugger statement always calls debugger. No need to modify it. 277 // Debugger statement always calls debugger. No need to modify it.
281 if (IsDebuggerStatement()) return; 278 if (IsDebuggerStatement()) return;
282 279
283 // If there is already a break point here just return. This might happen if 280 // If there is already a break point here just return. This might happen if
284 // the same code is flooded with break points twice. Flooding the same 281 // the same code is flooded with break points twice. Flooding the same
285 // function twice might happen when stepping in a function with an exception 282 // function twice might happen when stepping in a function with an exception
286 // handler as the handler and the function is the same. 283 // handler as the handler and the function is the same.
287 if (IsDebugBreak()) return; 284 if (IsDebugBreak()) return;
288 285
289 if (IsExit()) { 286 DCHECK(IsDebugBreakSlot());
290 // Patch the frame exit code with a break point. 287 Builtins* builtins = debug_info_->GetIsolate()->builtins();
291 SetDebugBreakAtReturn(); 288 Handle<Code> target =
292 } else if (IsDebugBreakSlot()) { 289 IsReturn() ? builtins->Return_DebugBreak() : builtins->Slot_DebugBreak();
293 // Patch the code in the break slot. 290 DebugCodegen::PatchDebugBreakSlot(pc(), target);
294 SetDebugBreakAtSlot();
295 }
296 DCHECK(IsDebugBreak()); 291 DCHECK(IsDebugBreak());
297 } 292 }
298 293
299 294
300 void BreakLocation::ClearDebugBreak() { 295 void BreakLocation::ClearDebugBreak() {
301 // Debugger statement always calls debugger. No need to modify it. 296 // Debugger statement always calls debugger. No need to modify it.
302 if (IsDebuggerStatement()) return; 297 if (IsDebuggerStatement()) return;
303 298
304 if (IsExit()) { 299 DCHECK(IsDebugBreakSlot());
305 // Restore the frame exit code with a break point. 300 DebugCodegen::ClearDebugBreakSlot(pc());
306 RestoreFromOriginal(Assembler::kJSReturnSequenceLength);
307 } else if (IsDebugBreakSlot()) {
308 // Restore the code in the break slot.
309 RestoreFromOriginal(Assembler::kDebugBreakSlotLength);
310 }
311 DCHECK(!IsDebugBreak()); 301 DCHECK(!IsDebugBreak());
312 } 302 }
313 303
314 304
315 void BreakLocation::RestoreFromOriginal(int length_in_bytes) {
316 memcpy(pc(), original_pc(), length_in_bytes);
317 CpuFeatures::FlushICache(pc(), length_in_bytes);
318 }
319
320
321 bool BreakLocation::IsStepInLocation() const { 305 bool BreakLocation::IsStepInLocation() const {
322 return IsConstructCall() || IsCall(); 306 return IsConstructCall() || IsCall();
323 } 307 }
324 308
325 309
326 bool BreakLocation::IsDebugBreak() const { 310 bool BreakLocation::IsDebugBreak() const {
327 if (IsExit()) { 311 if (IsDebugBreakSlot()) {
328 return rinfo().IsPatchedReturnSequence();
329 } else if (IsDebugBreakSlot()) {
330 return rinfo().IsPatchedDebugBreakSlotSequence(); 312 return rinfo().IsPatchedDebugBreakSlotSequence();
331 } 313 }
332 return false; 314 return false;
333 } 315 }
334 316
335 317
336 Handle<Object> BreakLocation::BreakPointObjects() const { 318 Handle<Object> BreakLocation::BreakPointObjects() const {
337 return debug_info_->GetBreakPointObjects(pc_offset_); 319 return debug_info_->GetBreakPointObjects(pc_offset_);
338 } 320 }
339 321
340 322
341 bool BreakLocation::Iterator::RinfoDone() const {
342 DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
343 return reloc_iterator_.done();
344 }
345
346
347 void BreakLocation::Iterator::RinfoNext() {
348 reloc_iterator_.next();
349 reloc_iterator_original_.next();
350 #ifdef DEBUG
351 DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
352 DCHECK(reloc_iterator_.done() || rmode() == original_rinfo()->rmode());
353 #endif
354 }
355
356
357 // Threading support. 323 // Threading support.
358 void Debug::ThreadInit() { 324 void Debug::ThreadInit() {
359 thread_local_.break_count_ = 0; 325 thread_local_.break_count_ = 0;
360 thread_local_.break_id_ = 0; 326 thread_local_.break_id_ = 0;
361 thread_local_.break_frame_id_ = StackFrame::NO_ID; 327 thread_local_.break_frame_id_ = StackFrame::NO_ID;
362 thread_local_.last_step_action_ = StepNone; 328 thread_local_.last_step_action_ = StepNone;
363 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; 329 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
364 thread_local_.step_count_ = 0; 330 thread_local_.step_count_ = 0;
365 thread_local_.last_fp_ = 0; 331 thread_local_.last_fp_ = 0;
366 thread_local_.queued_step_count_ = 0; 332 thread_local_.queued_step_count_ = 0;
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 // location as well. So the "- 1" to exclude it from the search. 1109 // location as well. So the "- 1" to exclude it from the search.
1144 Address call_pc = summary.pc() - 1; 1110 Address call_pc = summary.pc() - 1;
1145 BreakLocation location = 1111 BreakLocation location =
1146 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); 1112 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
1147 1113
1148 if (thread_local_.restarter_frame_function_pointer_ != NULL) { 1114 if (thread_local_.restarter_frame_function_pointer_ != NULL) {
1149 is_at_restarted_function = true; 1115 is_at_restarted_function = true;
1150 } 1116 }
1151 1117
1152 // If this is the last break code target step out is the only possibility. 1118 // If this is the last break code target step out is the only possibility.
1153 if (location.IsExit() || step_action == StepOut) { 1119 if (location.IsReturn() || step_action == StepOut) {
1154 if (step_action == StepOut) { 1120 if (step_action == StepOut) {
1155 // Skip step_count frames starting with the current one. 1121 // Skip step_count frames starting with the current one.
1156 while (step_count-- > 0 && !frames_it.done()) { 1122 while (step_count-- > 0 && !frames_it.done()) {
1157 frames_it.Advance(); 1123 frames_it.Advance();
1158 } 1124 }
1159 } else { 1125 } else {
1160 DCHECK(location.IsExit()); 1126 DCHECK(location.IsReturn());
1161 frames_it.Advance(); 1127 frames_it.Advance();
1162 } 1128 }
1163 // Skip native and extension functions on the stack. 1129 // Skip native and extension functions on the stack.
1164 while (!frames_it.done() && 1130 while (!frames_it.done() &&
1165 !frames_it.frame()->function()->IsSubjectToDebugging()) { 1131 !frames_it.frame()->function()->IsSubjectToDebugging()) {
1166 frames_it.Advance(); 1132 frames_it.Advance();
1167 } 1133 }
1168 // Step out: If there is a JavaScript caller frame, we need to 1134 // Step out: If there is a JavaScript caller frame, we need to
1169 // flood it with breakpoints. 1135 // flood it with breakpoints.
1170 if (!frames_it.done()) { 1136 if (!frames_it.done()) {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 1222
1257 // We stepped into a new frame if the frame pointer changed. 1223 // We stepped into a new frame if the frame pointer changed.
1258 if (step_action == StepFrame) { 1224 if (step_action == StepFrame) {
1259 return frame->UnpaddedFP() == thread_local_.last_fp_; 1225 return frame->UnpaddedFP() == thread_local_.last_fp_;
1260 } 1226 }
1261 1227
1262 // If the step last action was step next or step in make sure that a new 1228 // If the step last action was step next or step in make sure that a new
1263 // statement is hit. 1229 // statement is hit.
1264 if (step_action == StepNext || step_action == StepIn) { 1230 if (step_action == StepNext || step_action == StepIn) {
1265 // Never continue if returning from function. 1231 // Never continue if returning from function.
1266 if (break_location->IsExit()) return false; 1232 if (break_location->IsReturn()) return false;
1267 1233
1268 // Continue if we are still on the same frame and in the same statement. 1234 // Continue if we are still on the same frame and in the same statement.
1269 int current_statement_position = 1235 int current_statement_position =
1270 break_location->code()->SourceStatementPosition(frame->pc()); 1236 break_location->code()->SourceStatementPosition(frame->pc());
1271 return thread_local_.last_fp_ == frame->UnpaddedFP() && 1237 return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1272 thread_local_.last_statement_position_ == current_statement_position; 1238 thread_local_.last_statement_position_ == current_statement_position;
1273 } 1239 }
1274 1240
1275 // No step next action - don't continue. 1241 // No step next action - don't continue.
1276 return false; 1242 return false;
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after
2008 1974
2009 shared->set_debug_info(isolate_->heap()->undefined_value()); 1975 shared->set_debug_info(isolate_->heap()->undefined_value());
2010 } 1976 }
2011 1977
2012 1978
2013 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { 1979 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
2014 after_break_target_ = NULL; 1980 after_break_target_ = NULL;
2015 1981
2016 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job. 1982 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job.
2017 1983
2018 HandleScope scope(isolate_); 1984 // Continue just after the slot.
2019 PrepareForBreakPoints(); 1985 after_break_target_ = frame->pc();
2020
2021 // Get the executing function in which the debug break occurred.
2022 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2023 Handle<SharedFunctionInfo> shared(function->shared());
2024 if (!EnsureDebugInfo(shared, function)) {
2025 // Return if we failed to retrieve the debug info.
2026 return;
2027 }
2028 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2029 Handle<Code> code(debug_info->code());
2030 Handle<Code> original_code(debug_info->original_code());
2031 #ifdef DEBUG
2032 // Get the code which is actually executing.
2033 Handle<Code> frame_code(frame->LookupCode());
2034 DCHECK(frame_code.is_identical_to(code));
2035 #endif
2036
2037 // Find the call address in the running code. This address holds the call to
2038 // either a DebugBreakXXX or to the debug break return entry code if the
2039 // break point is still active after processing the break point.
2040 Address addr = Assembler::break_address_from_return_address(frame->pc());
2041
2042 // Check if the location is at JS exit or debug break slot.
2043 bool at_js_return = false;
2044 bool break_at_js_return_active = false;
2045 bool at_debug_break_slot = false;
2046 RelocIterator it(debug_info->code());
2047 while (!it.done() && !at_js_return && !at_debug_break_slot) {
2048 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2049 at_js_return = (it.rinfo()->pc() ==
2050 addr - Assembler::kPatchReturnSequenceAddressOffset);
2051 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
2052 }
2053 if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2054 at_debug_break_slot = (it.rinfo()->pc() ==
2055 addr - Assembler::kPatchDebugBreakSlotAddressOffset);
2056 }
2057 it.next();
2058 }
2059
2060 // Handle the jump to continue execution after break point depending on the
2061 // break location.
2062 if (at_js_return) {
2063 // If the break point at return is still active jump to the corresponding
2064 // place in the original code. If not the break point was removed during
2065 // break point processing.
2066 if (break_at_js_return_active) {
2067 addr += original_code->instruction_start() - code->instruction_start();
2068 }
2069
2070 // Move back to where the call instruction sequence started.
2071 after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset;
2072 } else if (at_debug_break_slot) {
2073 // Address of where the debug break slot starts.
2074 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
2075
2076 // Continue just after the slot.
2077 after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
2078 }
2079 } 1986 }
2080 1987
2081 1988
2082 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { 1989 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
2083 HandleScope scope(isolate_); 1990 HandleScope scope(isolate_);
2084 1991
2085 // If there are no break points this cannot be break at return, as 1992 // If there are no break points this cannot be break at return, as
2086 // the debugger statement and stack guard debug break cannot be at 1993 // the debugger statement and stack guard debug break cannot be at
2087 // return. 1994 // return.
2088 if (!has_break_points_) { 1995 if (!has_break_points_) return false;
2089 return false;
2090 }
2091 1996
2092 PrepareForBreakPoints(); 1997 PrepareForBreakPoints();
2093 1998
2094 // Get the executing function in which the debug break occurred. 1999 // Get the executing function in which the debug break occurred.
2095 Handle<JSFunction> function(JSFunction::cast(frame->function())); 2000 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2096 Handle<SharedFunctionInfo> shared(function->shared()); 2001 Handle<SharedFunctionInfo> shared(function->shared());
2097 if (!EnsureDebugInfo(shared, function)) { 2002 if (!EnsureDebugInfo(shared, function)) {
2098 // Return if we failed to retrieve the debug info. 2003 // Return if we failed to retrieve the debug info.
2099 return false; 2004 return false;
2100 } 2005 }
2101 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 2006 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2102 Handle<Code> code(debug_info->code()); 2007 Handle<Code> code(debug_info->code());
2103 #ifdef DEBUG 2008 #ifdef DEBUG
2104 // Get the code which is actually executing. 2009 // Get the code which is actually executing.
2105 Handle<Code> frame_code(frame->LookupCode()); 2010 Handle<Code> frame_code(frame->LookupCode());
2106 DCHECK(frame_code.is_identical_to(code)); 2011 DCHECK(frame_code.is_identical_to(code));
2107 #endif 2012 #endif
2108 2013
2109 // Find the call address in the running code. 2014 // Find the reloc info matching the start of the debug break slot.
2110 Address addr = Assembler::break_address_from_return_address(frame->pc()); 2015 Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength;
2111 2016 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
2112 // Check if the location is at JS return. 2017 for (RelocIterator it(debug_info->code(), mask); !it.done(); it.next()) {
2113 RelocIterator it(debug_info->code()); 2018 if (it.rinfo()->pc() == slot_pc) return true;
2114 while (!it.done()) {
2115 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2116 return (it.rinfo()->pc() ==
2117 addr - Assembler::kPatchReturnSequenceAddressOffset);
2118 }
2119 it.next();
2120 } 2019 }
2121 return false; 2020 return false;
2122 } 2021 }
2123 2022
2124 2023
2125 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, 2024 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
2126 LiveEdit::FrameDropMode mode, 2025 LiveEdit::FrameDropMode mode,
2127 Object** restarter_frame_function_pointer) { 2026 Object** restarter_frame_function_pointer) {
2128 if (mode != LiveEdit::CURRENTLY_SET_MODE) { 2027 if (mode != LiveEdit::CURRENTLY_SET_MODE) {
2129 thread_local_.frame_drop_mode_ = mode; 2028 thread_local_.frame_drop_mode_ = mode;
(...skipping 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after
3170 queue_.Put(message); 3069 queue_.Put(message);
3171 logger_->DebugEvent("Put", message.text()); 3070 logger_->DebugEvent("Put", message.text());
3172 } 3071 }
3173 3072
3174 3073
3175 void LockingCommandMessageQueue::Clear() { 3074 void LockingCommandMessageQueue::Clear() {
3176 base::LockGuard<base::Mutex> lock_guard(&mutex_); 3075 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3177 queue_.Clear(); 3076 queue_.Clear();
3178 } 3077 }
3179 3078
3180
3181 void DebugCodegen::RecordRelocInfo(MacroAssembler* masm,
3182 DebugCodegen::SlotLocation location,
3183 int call_argc) {
3184 switch (location) {
3185 case PLAIN_DEBUG_BREAK:
3186 masm->RecordDebugBreakSlot();
3187 return;
3188 case DEBUG_BREAK_AT_CALL:
3189 DCHECK_LE(0, call_argc);
3190 masm->RecordDebugBreakSlotForCall(call_argc);
3191 return;
3192 case DEBUG_BREAK_AT_CONSTRUCT_CALL:
3193 masm->RecordDebugBreakSlotForConstructCall();
3194 return;
3195 }
3196 }
3197
3198 } // namespace internal 3079 } // namespace internal
3199 } // namespace v8 3080 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug.h ('k') | src/factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698