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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |