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

Side by Side Diff: src/debug.cc

Issue 967323002: Refactor BreakLocationIterator. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: static_cast instead Created 5 years, 9 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/ia32/assembler-ia32.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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) { 53 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
54 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); 54 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
55 // Isolate::context() may have been NULL when "script collected" event 55 // Isolate::context() may have been NULL when "script collected" event
56 // occured. 56 // occured.
57 if (context.is_null()) return v8::Local<v8::Context>(); 57 if (context.is_null()) return v8::Local<v8::Context>();
58 Handle<Context> native_context(context->native_context()); 58 Handle<Context> native_context(context->native_context());
59 return v8::Utils::ToLocal(native_context); 59 return v8::Utils::ToLocal(native_context);
60 } 60 }
61 61
62 62
63 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info, 63 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
64 BreakLocatorType type) { 64 BreakLocatorType type)
65 debug_info_ = debug_info; 65 : debug_info_(debug_info),
66 type_ = type; 66 type_(type),
67 reloc_iterator_ = NULL; 67 reloc_iterator_(debug_info->code(),
68 reloc_iterator_original_ = NULL; 68 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)),
69 Reset(); // Initialize the rest of the member variables. 69 reloc_iterator_original_(
70 debug_info->original_code(),
71 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)),
72 break_index_(-1),
73 position_(1),
74 statement_position_(1) {
75 Next();
70 } 76 }
71 77
72 78
73 BreakLocationIterator::~BreakLocationIterator() { 79 void BreakLocation::Iterator::Next() {
74 DCHECK(reloc_iterator_ != NULL);
75 DCHECK(reloc_iterator_original_ != NULL);
76 delete reloc_iterator_;
77 delete reloc_iterator_original_;
78 }
79
80
81 // Check whether a code stub with the specified major key is a possible break
82 // point location when looking for source break locations.
83 static bool IsSourceBreakStub(Code* code) {
84 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
85 return major_key == CodeStub::CallFunction;
86 }
87
88
89 // Check whether a code stub with the specified major key is a possible break
90 // location.
91 static bool IsBreakStub(Code* code) {
92 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
93 return major_key == CodeStub::CallFunction;
94 }
95
96
97 void BreakLocationIterator::Next() {
98 DisallowHeapAllocation no_gc; 80 DisallowHeapAllocation no_gc;
99 DCHECK(!RinfoDone()); 81 DCHECK(!RinfoDone());
100 82
101 // Iterate through reloc info for code and original code stopping at each 83 // Iterate through reloc info for code and original code stopping at each
102 // breakable code target. 84 // breakable code target.
103 bool first = break_point_ == -1; 85 bool first = break_index_ == -1;
104 while (!RinfoDone()) { 86 while (!RinfoDone()) {
105 if (!first) RinfoNext(); 87 if (!first) RinfoNext();
106 first = false; 88 first = false;
107 if (RinfoDone()) return; 89 if (RinfoDone()) return;
108 90
109 // Whenever a statement position or (plain) position is passed update the 91 // Whenever a statement position or (plain) position is passed update the
110 // current value of these. 92 // current value of these.
111 if (RelocInfo::IsPosition(rmode())) { 93 if (RelocInfo::IsPosition(rmode())) {
112 if (RelocInfo::IsStatementPosition(rmode())) { 94 if (RelocInfo::IsStatementPosition(rmode())) {
113 statement_position_ = static_cast<int>( 95 statement_position_ = static_cast<int>(
114 rinfo()->data() - debug_info_->shared()->start_position()); 96 rinfo()->data() - debug_info_->shared()->start_position());
115 } 97 }
116 // Always update the position as we don't want that to be before the 98 // Always update the position as we don't want that to be before the
117 // statement position. 99 // statement position.
118 position_ = static_cast<int>( 100 position_ = static_cast<int>(rinfo()->data() -
119 rinfo()->data() - debug_info_->shared()->start_position()); 101 debug_info_->shared()->start_position());
120 DCHECK(position_ >= 0); 102 DCHECK(position_ >= 0);
121 DCHECK(statement_position_ >= 0); 103 DCHECK(statement_position_ >= 0);
122 } 104 }
123 105
124 // Check for break at return. 106 // Check for break at return.
125 if (RelocInfo::IsJSReturn(rmode())) { 107 if (RelocInfo::IsJSReturn(rmode())) {
126 // Set the positions to the end of the function. 108 // Set the positions to the end of the function.
127 if (debug_info_->shared()->HasSourceCode()) { 109 if (debug_info_->shared()->HasSourceCode()) {
128 position_ = debug_info_->shared()->end_position() - 110 position_ = debug_info_->shared()->end_position() -
129 debug_info_->shared()->start_position() - 1; 111 debug_info_->shared()->start_position() - 1;
130 } else { 112 } else {
131 position_ = 0; 113 position_ = 0;
132 } 114 }
133 statement_position_ = position_; 115 statement_position_ = position_;
134 break_point_++; 116 break_index_++;
135 return; 117 return;
136 } 118 }
137 119
138 if (RelocInfo::IsCodeTarget(rmode())) { 120 if (RelocInfo::IsCodeTarget(rmode())) {
139 // Check for breakable code target. Look in the original code as setting 121 // Check for breakable code target. Look in the original code as setting
140 // break points can cause the code targets in the running (debugged) code 122 // break points can cause the code targets in the running (debugged) code
141 // to be of a different kind than in the original code. 123 // to be of a different kind than in the original code.
142 Address target = original_rinfo()->target_address(); 124 Address target = original_rinfo()->target_address();
143 Code* code = Code::GetCodeFromTargetAddress(target); 125 Code* code = Code::GetCodeFromTargetAddress(target);
144 126
145 if (RelocInfo::IsConstructCall(rmode()) || code->is_call_stub()) { 127 if (RelocInfo::IsConstructCall(rmode()) || code->is_call_stub()) {
146 break_point_++; 128 break_index_++;
147 return; 129 return;
148 } 130 }
149 131
150 // Skip below if we only want locations for calls and returns. 132 // Skip below if we only want locations for calls and returns.
151 if (type_ == CALLS_AND_RETURNS) continue; 133 if (type_ == CALLS_AND_RETURNS) continue;
152 134
153 if ((code->is_inline_cache_stub() && !code->is_binary_op_stub() && 135 if ((code->is_inline_cache_stub() && !code->is_binary_op_stub() &&
154 !code->is_compare_ic_stub() && !code->is_to_boolean_ic_stub())) { 136 !code->is_compare_ic_stub() && !code->is_to_boolean_ic_stub())) {
155 break_point_++; 137 break_index_++;
156 return; 138 return;
157 } 139 }
158 if (code->kind() == Code::STUB) { 140 if (code->kind() == Code::STUB) {
159 if (IsDebuggerStatement()) { 141 if (RelocInfo::IsDebuggerStatement(rmode())) {
160 break_point_++; 142 break_index_++;
161 return; 143 return;
162 } else if (type_ == ALL_BREAK_LOCATIONS) { 144 } else if (CodeStub::GetMajorKey(code) == CodeStub::CallFunction) {
163 if (IsBreakStub(code)) { 145 break_index_++;
164 break_point_++; 146 return;
165 return;
166 }
167 } else {
168 DCHECK(type_ == SOURCE_BREAK_LOCATIONS);
169 if (IsSourceBreakStub(code)) {
170 break_point_++;
171 return;
172 }
173 } 147 }
174 } 148 }
175 } 149 }
176 150
177 if (IsDebugBreakSlot() && type_ != CALLS_AND_RETURNS) { 151 if (RelocInfo::IsDebugBreakSlot(rmode()) && type_ != CALLS_AND_RETURNS) {
178 // There is always a possible break point at a debug break slot. 152 // There is always a possible break point at a debug break slot.
179 break_point_++; 153 break_index_++;
180 return; 154 return;
181 } 155 }
182 } 156 }
183 } 157 }
184 158
185 159
186 void BreakLocationIterator::Next(int count) { 160 // Find the break point at the supplied address, or the closest one before
187 while (count > 0) { 161 // the address.
188 Next(); 162 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info,
189 count--; 163 BreakLocatorType type, Address pc) {
190 } 164 Iterator it(debug_info, type);
165 it.SkipTo(BreakIndexFromAddress(debug_info, type, pc));
166 return it.GetBreakLocation();
191 } 167 }
192 168
193 169
194 // Find the break point at the supplied address, or the closest one before 170 // Find the break point at the supplied address, or the closest one before
195 // the address. 171 // the address.
196 void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) { 172 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info,
173 BreakLocatorType type, Address pc,
174 List<BreakLocation>* result_out) {
175 int break_index = BreakIndexFromAddress(debug_info, type, pc);
176 Iterator it(debug_info, type);
177 it.SkipTo(break_index);
178 int statement_position = it.statement_position();
179 while (!it.Done() && it.statement_position() == statement_position) {
180 result_out->Add(it.GetBreakLocation());
181 it.Next();
182 }
183 }
184
185
186 int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info,
187 BreakLocatorType type, Address pc) {
197 // Run through all break points to locate the one closest to the address. 188 // Run through all break points to locate the one closest to the address.
198 int closest_break_point = 0; 189 int closest_break = 0;
199 int distance = kMaxInt; 190 int distance = kMaxInt;
200 while (!Done()) { 191 for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
201 // Check if this break point is closer that what was previously found. 192 // Check if this break point is closer that what was previously found.
202 if (this->pc() <= pc && pc - this->pc() < distance) { 193 if (it.pc() <= pc && pc - it.pc() < distance) {
203 closest_break_point = break_point(); 194 closest_break = it.break_index();
204 distance = static_cast<int>(pc - this->pc()); 195 distance = static_cast<int>(pc - it.pc());
205 // Check whether we can't get any closer. 196 // Check whether we can't get any closer.
206 if (distance == 0) break; 197 if (distance == 0) break;
207 } 198 }
208 Next();
209 } 199 }
210 200 return closest_break;
211 // Move to the break point found.
212 Reset();
213 Next(closest_break_point);
214 } 201 }
215 202
216 203
217 // Find the break point closest to the supplied source position. 204 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
218 void BreakLocationIterator::FindBreakLocationFromPosition(int position, 205 BreakLocatorType type, int position,
219 BreakPositionAlignment alignment) { 206 BreakPositionAlignment alignment) {
220 // Run through all break points to locate the one closest to the source 207 // Run through all break points to locate the one closest to the source
221 // position. 208 // position.
222 int closest_break_point = 0; 209 int closest_break = 0;
223 int distance = kMaxInt; 210 int distance = kMaxInt;
224 211
225 while (!Done()) { 212 for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
226 int next_position; 213 int next_position;
227 switch (alignment) { 214 if (alignment == STATEMENT_ALIGNED) {
228 case STATEMENT_ALIGNED: 215 next_position = it.statement_position();
229 next_position = this->statement_position(); 216 } else {
230 break; 217 DCHECK(alignment == BREAK_POSITION_ALIGNED);
231 case BREAK_POSITION_ALIGNED: 218 next_position = it.position();
232 next_position = this->position();
233 break;
234 default:
235 UNREACHABLE();
236 next_position = this->statement_position();
237 } 219 }
238 // Check if this break point is closer that what was previously found.
239 if (position <= next_position && next_position - position < distance) { 220 if (position <= next_position && next_position - position < distance) {
240 closest_break_point = break_point(); 221 closest_break = it.break_index();
241 distance = next_position - position; 222 distance = next_position - position;
242 // Check whether we can't get any closer. 223 // Check whether we can't get any closer.
243 if (distance == 0) break; 224 if (distance == 0) break;
244 } 225 }
245 Next();
246 } 226 }
247 227
248 // Move to the break point found. 228 Iterator it(debug_info, type);
249 Reset(); 229 it.SkipTo(closest_break);
250 Next(closest_break_point); 230 return it.GetBreakLocation();
251 } 231 }
252 232
253 233
254 void BreakLocationIterator::Reset() { 234 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) {
255 // Create relocation iterators for the two code objects.
256 if (reloc_iterator_ != NULL) delete reloc_iterator_;
257 if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
258 reloc_iterator_ = new RelocIterator(
259 debug_info_->code(),
260 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
261 reloc_iterator_original_ = new RelocIterator(
262 debug_info_->original_code(),
263 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
264
265 // Position at the first break point.
266 break_point_ = -1;
267 position_ = 1;
268 statement_position_ = 1;
269 Next();
270 }
271
272
273 bool BreakLocationIterator::Done() const {
274 return RinfoDone();
275 }
276
277
278 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
279 // If there is not already a real break point here patch code with debug 235 // If there is not already a real break point here patch code with debug
280 // break. 236 // break.
281 if (!HasBreakPoint()) SetDebugBreak(); 237 if (!HasBreakPoint()) SetDebugBreak();
282 DCHECK(IsDebugBreak() || IsDebuggerStatement()); 238 DCHECK(IsDebugBreak() || IsDebuggerStatement());
283 // Set the break point information. 239 // Set the break point information.
284 DebugInfo::SetBreakPoint(debug_info_, code_position(), 240 DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_,
285 position(), statement_position(), 241 statement_position_, break_point_object);
286 break_point_object);
287 } 242 }
288 243
289 244
290 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) { 245 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
291 // Clear the break point information. 246 // Clear the break point information.
292 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object); 247 DebugInfo::ClearBreakPoint(debug_info_, pc_offset_, break_point_object);
293 // If there are no more break points here remove the debug break. 248 // If there are no more break points here remove the debug break.
294 if (!HasBreakPoint()) { 249 if (!HasBreakPoint()) {
295 ClearDebugBreak(); 250 ClearDebugBreak();
296 DCHECK(!IsDebugBreak()); 251 DCHECK(!IsDebugBreak());
297 } 252 }
298 } 253 }
299 254
300 255
301 void BreakLocationIterator::SetOneShot() { 256 void BreakLocation::SetOneShot() {
302 // Debugger statement always calls debugger. No need to modify it. 257 // Debugger statement always calls debugger. No need to modify it.
303 if (IsDebuggerStatement()) return; 258 if (IsDebuggerStatement()) return;
304 259
305 // If there is a real break point here no more to do. 260 // If there is a real break point here no more to do.
306 if (HasBreakPoint()) { 261 if (HasBreakPoint()) {
307 DCHECK(IsDebugBreak()); 262 DCHECK(IsDebugBreak());
308 return; 263 return;
309 } 264 }
310 265
311 // Patch code with debug break. 266 // Patch code with debug break.
312 SetDebugBreak(); 267 SetDebugBreak();
313 } 268 }
314 269
315 270
316 void BreakLocationIterator::ClearOneShot() { 271 void BreakLocation::ClearOneShot() {
317 // Debugger statement always calls debugger. No need to modify it. 272 // Debugger statement always calls debugger. No need to modify it.
318 if (IsDebuggerStatement()) return; 273 if (IsDebuggerStatement()) return;
319 274
320 // If there is a real break point here no more to do. 275 // If there is a real break point here no more to do.
321 if (HasBreakPoint()) { 276 if (HasBreakPoint()) {
322 DCHECK(IsDebugBreak()); 277 DCHECK(IsDebugBreak());
323 return; 278 return;
324 } 279 }
325 280
326 // Patch code removing debug break. 281 // Patch code removing debug break.
327 ClearDebugBreak(); 282 ClearDebugBreak();
328 DCHECK(!IsDebugBreak()); 283 DCHECK(!IsDebugBreak());
329 } 284 }
330 285
331 286
332 void BreakLocationIterator::SetDebugBreak() { 287 void BreakLocation::SetDebugBreak() {
333 // Debugger statement always calls debugger. No need to modify it. 288 // Debugger statement always calls debugger. No need to modify it.
334 if (IsDebuggerStatement()) return; 289 if (IsDebuggerStatement()) return;
335 290
336 // If there is already a break point here just return. This might happen if 291 // If there is already a break point here just return. This might happen if
337 // the same code is flooded with break points twice. Flooding the same 292 // the same code is flooded with break points twice. Flooding the same
338 // function twice might happen when stepping in a function with an exception 293 // function twice might happen when stepping in a function with an exception
339 // handler as the handler and the function is the same. 294 // handler as the handler and the function is the same.
340 if (IsDebugBreak()) return; 295 if (IsDebugBreak()) return;
341 296
342 if (RelocInfo::IsJSReturn(rmode())) { 297 if (IsExit()) {
343 // Patch the frame exit code with a break point. 298 // Patch the frame exit code with a break point.
344 SetDebugBreakAtReturn(); 299 SetDebugBreakAtReturn();
345 } else if (IsDebugBreakSlot()) { 300 } else if (IsDebugBreakSlot()) {
346 // Patch the code in the break slot. 301 // Patch the code in the break slot.
347 SetDebugBreakAtSlot(); 302 SetDebugBreakAtSlot();
348 } else { 303 } else {
349 // Patch the IC call. 304 // Patch the IC call.
350 SetDebugBreakAtIC(); 305 SetDebugBreakAtIC();
351 } 306 }
352 DCHECK(IsDebugBreak()); 307 DCHECK(IsDebugBreak());
353 } 308 }
354 309
355 310
356 void BreakLocationIterator::ClearDebugBreak() { 311 void BreakLocation::ClearDebugBreak() {
357 // Debugger statement always calls debugger. No need to modify it. 312 // Debugger statement always calls debugger. No need to modify it.
358 if (IsDebuggerStatement()) return; 313 if (IsDebuggerStatement()) return;
359 314
360 if (RelocInfo::IsJSReturn(rmode())) { 315 if (IsExit()) {
361 // Restore the frame exit code. 316 // Restore the frame exit code with a break point.
362 ClearDebugBreakAtReturn(); 317 RestoreFromOriginal(Assembler::kJSReturnSequenceLength);
363 } else if (IsDebugBreakSlot()) { 318 } else if (IsDebugBreakSlot()) {
364 // Restore the code in the break slot. 319 // Restore the code in the break slot.
365 ClearDebugBreakAtSlot(); 320 RestoreFromOriginal(Assembler::kDebugBreakSlotLength);
366 } else { 321 } else {
367 // Patch the IC call. 322 // Restore the IC call.
368 ClearDebugBreakAtIC(); 323 rinfo().set_target_address(original_rinfo().target_address());
369 } 324 }
370 DCHECK(!IsDebugBreak()); 325 DCHECK(!IsDebugBreak());
371 } 326 }
372 327
373 328
374 bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) { 329 void BreakLocation::RestoreFromOriginal(int length_in_bytes) {
375 if (RelocInfo::IsConstructCall(original_rmode())) { 330 memcpy(pc(), original_pc(), length_in_bytes);
376 return true; 331 CpuFeatures::FlushICache(pc(), length_in_bytes);
377 } else if (RelocInfo::IsCodeTarget(rmode())) { 332 }
333
334
335 bool BreakLocation::IsStepInLocation() const {
336 if (IsConstructCall()) return true;
337 if (RelocInfo::IsCodeTarget(rmode())) {
378 HandleScope scope(debug_info_->GetIsolate()); 338 HandleScope scope(debug_info_->GetIsolate());
379 Address target = original_rinfo()->target_address(); 339 Handle<Code> target_code = CodeTarget();
380 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
381 if (target_code->kind() == Code::STUB) {
382 return CodeStub::GetMajorKey(*target_code) == CodeStub::CallFunction;
383 }
384 return target_code->is_call_stub(); 340 return target_code->is_call_stub();
385 } 341 }
386 return false; 342 return false;
387 } 343 }
388 344
389 345
390 // Check whether the break point is at a position which will exit the function. 346 bool BreakLocation::IsDebugBreak() const {
391 bool BreakLocationIterator::IsExit() const { 347 if (IsExit()) {
392 return (RelocInfo::IsJSReturn(rmode())); 348 return rinfo().IsPatchedReturnSequence();
393 }
394
395
396 bool BreakLocationIterator::HasBreakPoint() {
397 return debug_info_->HasBreakPoint(code_position());
398 }
399
400
401 // Check whether there is a debug break at the current position.
402 bool BreakLocationIterator::IsDebugBreak() {
403 if (RelocInfo::IsJSReturn(rmode())) {
404 return IsDebugBreakAtReturn();
405 } else if (IsDebugBreakSlot()) { 349 } else if (IsDebugBreakSlot()) {
406 return IsDebugBreakAtSlot(); 350 return rinfo().IsPatchedDebugBreakSlotSequence();
407 } else { 351 } else {
408 return Debug::IsDebugBreak(rinfo()->target_address()); 352 return Debug::IsDebugBreak(rinfo().target_address());
409 } 353 }
410 } 354 }
411 355
412 356
413 // Find the builtin to use for invoking the debug break 357 // Find the builtin to use for invoking the debug break
414 static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) { 358 static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
415 Isolate* isolate = code->GetIsolate(); 359 Isolate* isolate = code->GetIsolate();
416 360
417 // Find the builtin debug break function matching the calling convention 361 // Find the builtin debug break function matching the calling convention
418 // used by the call site. 362 // used by the call site.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 if (code->kind() == Code::STUB) { 394 if (code->kind() == Code::STUB) {
451 DCHECK(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction); 395 DCHECK(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction);
452 return isolate->builtins()->CallFunctionStub_DebugBreak(); 396 return isolate->builtins()->CallFunctionStub_DebugBreak();
453 } 397 }
454 398
455 UNREACHABLE(); 399 UNREACHABLE();
456 return Handle<Code>::null(); 400 return Handle<Code>::null();
457 } 401 }
458 402
459 403
460 void BreakLocationIterator::SetDebugBreakAtIC() { 404 void BreakLocation::SetDebugBreakAtIC() {
461 // Patch the original code with the current address as the current address 405 // Patch the original code with the current address as the current address
462 // might have changed by the inline caching since the code was copied. 406 // might have changed by the inline caching since the code was copied.
463 original_rinfo()->set_target_address(rinfo()->target_address()); 407 original_rinfo().set_target_address(rinfo().target_address());
464 408
465 RelocInfo::Mode mode = rmode(); 409 if (RelocInfo::IsCodeTarget(rmode_)) {
466 if (RelocInfo::IsCodeTarget(mode)) { 410 Handle<Code> target_code = CodeTarget();
467 Address target = rinfo()->target_address();
468 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
469 411
470 // Patch the code to invoke the builtin debug break function matching the 412 // Patch the code to invoke the builtin debug break function matching the
471 // calling convention used by the call site. 413 // calling convention used by the call site.
472 Handle<Code> dbgbrk_code = DebugBreakForIC(target_code, mode); 414 Handle<Code> debug_break_code = DebugBreakForIC(target_code, rmode_);
473 rinfo()->set_target_address(dbgbrk_code->entry()); 415 rinfo().set_target_address(debug_break_code->entry());
474 } 416 }
475 } 417 }
476 418
477 419
478 void BreakLocationIterator::ClearDebugBreakAtIC() { 420 Handle<Object> BreakLocation::BreakPointObjects() const {
479 // Patch the code to the original invoke. 421 return debug_info_->GetBreakPointObjects(pc_offset_);
480 rinfo()->set_target_address(original_rinfo()->target_address());
481 } 422 }
482 423
483 424
484 bool BreakLocationIterator::IsDebuggerStatement() { 425 Handle<Code> BreakLocation::CodeTarget() const {
485 return RelocInfo::DEBUG_BREAK == rmode(); 426 DCHECK(IsCodeTarget());
427 Address target = rinfo().target_address();
428 return Handle<Code>(Code::GetCodeFromTargetAddress(target));
486 } 429 }
487 430
488 431
489 bool BreakLocationIterator::IsDebugBreakSlot() { 432 Handle<Code> BreakLocation::OriginalCodeTarget() const {
490 return RelocInfo::DEBUG_BREAK_SLOT == rmode(); 433 DCHECK(IsCodeTarget());
434 Address target = original_rinfo().target_address();
435 return Handle<Code>(Code::GetCodeFromTargetAddress(target));
491 } 436 }
492 437
493 438
494 Object* BreakLocationIterator::BreakPointObjects() { 439 bool BreakLocation::Iterator::RinfoDone() const {
495 return debug_info_->GetBreakPointObjects(code_position()); 440 DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
441 return reloc_iterator_.done();
496 } 442 }
497 443
498 444
499 // Clear out all the debug break code. This is ONLY supposed to be used when 445 void BreakLocation::Iterator::RinfoNext() {
500 // shutting down the debugger as it will leave the break point information in 446 reloc_iterator_.next();
501 // DebugInfo even though the code is patched back to the non break point state. 447 reloc_iterator_original_.next();
502 void BreakLocationIterator::ClearAllDebugBreak() {
503 while (!Done()) {
504 ClearDebugBreak();
505 Next();
506 }
507 }
508
509
510 bool BreakLocationIterator::RinfoDone() const {
511 DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done());
512 return reloc_iterator_->done();
513 }
514
515
516 void BreakLocationIterator::RinfoNext() {
517 reloc_iterator_->next();
518 reloc_iterator_original_->next();
519 #ifdef DEBUG 448 #ifdef DEBUG
520 DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done()); 449 DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
521 if (!reloc_iterator_->done()) { 450 DCHECK(reloc_iterator_.done() || rmode() == original_rmode());
522 DCHECK(rmode() == original_rmode());
523 }
524 #endif 451 #endif
525 } 452 }
526 453
527 454
528 // Threading support. 455 // Threading support.
529 void Debug::ThreadInit() { 456 void Debug::ThreadInit() {
530 thread_local_.break_count_ = 0; 457 thread_local_.break_count_ = 0;
531 thread_local_.break_id_ = 0; 458 thread_local_.break_id_ = 0;
532 thread_local_.break_frame_id_ = StackFrame::NO_ID; 459 thread_local_.break_frame_id_ = StackFrame::NO_ID;
533 thread_local_.last_step_action_ = StepNone; 460 thread_local_.last_step_action_ = StepNone;
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 774
848 // Postpone interrupt during breakpoint processing. 775 // Postpone interrupt during breakpoint processing.
849 PostponeInterruptsScope postpone(isolate_); 776 PostponeInterruptsScope postpone(isolate_);
850 777
851 // Get the debug info (create it if it does not exist). 778 // Get the debug info (create it if it does not exist).
852 Handle<SharedFunctionInfo> shared = 779 Handle<SharedFunctionInfo> shared =
853 Handle<SharedFunctionInfo>(frame->function()->shared()); 780 Handle<SharedFunctionInfo>(frame->function()->shared());
854 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 781 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
855 782
856 // Find the break point where execution has stopped. 783 // Find the break point where execution has stopped.
857 BreakLocationIterator break_location_iterator(debug_info, 784 // PC points to the instruction after the current one, possibly a break
858 ALL_BREAK_LOCATIONS);
859 // pc points to the instruction after the current one, possibly a break
860 // location as well. So the "- 1" to exclude it from the search. 785 // location as well. So the "- 1" to exclude it from the search.
861 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1); 786 Address call_pc = frame->pc() - 1;
787 BreakLocation break_location =
788 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
862 789
863 // Check whether step next reached a new statement. 790 // Check whether step next reached a new statement.
864 if (!StepNextContinue(&break_location_iterator, frame)) { 791 if (!StepNextContinue(&break_location, frame)) {
865 // Decrease steps left if performing multiple steps. 792 // Decrease steps left if performing multiple steps.
866 if (thread_local_.step_count_ > 0) { 793 if (thread_local_.step_count_ > 0) {
867 thread_local_.step_count_--; 794 thread_local_.step_count_--;
868 } 795 }
869 } 796 }
870 797
871 // If there is one or more real break points check whether any of these are 798 // If there is one or more real break points check whether any of these are
872 // triggered. 799 // triggered.
873 Handle<Object> break_points_hit(heap->undefined_value(), isolate_); 800 Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
874 if (break_location_iterator.HasBreakPoint()) { 801 if (break_location.HasBreakPoint()) {
875 Handle<Object> break_point_objects = 802 Handle<Object> break_point_objects = break_location.BreakPointObjects();
876 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_);
877 break_points_hit = CheckBreakPoints(break_point_objects); 803 break_points_hit = CheckBreakPoints(break_point_objects);
878 } 804 }
879 805
880 // If step out is active skip everything until the frame where we need to step 806 // If step out is active skip everything until the frame where we need to step
881 // out to is reached, unless real breakpoint is hit. 807 // out to is reached, unless real breakpoint is hit.
882 if (StepOutActive() && 808 if (StepOutActive() &&
883 frame->fp() != thread_local_.step_out_fp_ && 809 frame->fp() != thread_local_.step_out_fp_ &&
884 break_points_hit->IsUndefined() ) { 810 break_points_hit->IsUndefined() ) {
885 // Step count should always be 0 for StepOut. 811 // Step count should always be 0 for StepOut.
886 DCHECK(thread_local_.step_count_ == 0); 812 DCHECK(thread_local_.step_count_ == 0);
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 if (!EnsureDebugInfo(shared, function)) { 977 if (!EnsureDebugInfo(shared, function)) {
1052 // Return if retrieving debug info failed. 978 // Return if retrieving debug info failed.
1053 return true; 979 return true;
1054 } 980 }
1055 981
1056 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 982 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1057 // Source positions starts with zero. 983 // Source positions starts with zero.
1058 DCHECK(*source_position >= 0); 984 DCHECK(*source_position >= 0);
1059 985
1060 // Find the break point and change it. 986 // Find the break point and change it.
1061 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); 987 BreakLocation location = BreakLocation::FromPosition(
1062 it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED); 988 debug_info, SOURCE_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED);
1063 it.SetBreakPoint(break_point_object); 989 *source_position = location.statement_position();
1064 990 location.SetBreakPoint(break_point_object);
1065 *source_position = it.statement_position();
1066 991
1067 // At least one active break point now. 992 // At least one active break point now.
1068 return debug_info->GetBreakPointCount() > 0; 993 return debug_info->GetBreakPointCount() > 0;
1069 } 994 }
1070 995
1071 996
1072 bool Debug::SetBreakPointForScript(Handle<Script> script, 997 bool Debug::SetBreakPointForScript(Handle<Script> script,
1073 Handle<Object> break_point_object, 998 Handle<Object> break_point_object,
1074 int* source_position, 999 int* source_position,
1075 BreakPositionAlignment alignment) { 1000 BreakPositionAlignment alignment) {
1076 HandleScope scope(isolate_); 1001 HandleScope scope(isolate_);
1077 1002
1078 PrepareForBreakPoints(); 1003 PrepareForBreakPoints();
1079 1004
1080 // Obtain shared function info for the function. 1005 // Obtain shared function info for the function.
1081 Object* result = FindSharedFunctionInfoInScript(script, *source_position); 1006 Handle<Object> result =
1007 FindSharedFunctionInfoInScript(script, *source_position);
1082 if (result->IsUndefined()) return false; 1008 if (result->IsUndefined()) return false;
1083 1009
1084 // Make sure the function has set up the debug info. 1010 // Make sure the function has set up the debug info.
1085 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result)); 1011 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
1086 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { 1012 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1087 // Return if retrieving debug info failed. 1013 // Return if retrieving debug info failed.
1088 return false; 1014 return false;
1089 } 1015 }
1090 1016
1091 // Find position within function. The script position might be before the 1017 // Find position within function. The script position might be before the
1092 // source position of the first function. 1018 // source position of the first function.
1093 int position; 1019 int position;
1094 if (shared->start_position() > *source_position) { 1020 if (shared->start_position() > *source_position) {
1095 position = 0; 1021 position = 0;
1096 } else { 1022 } else {
1097 position = *source_position - shared->start_position(); 1023 position = *source_position - shared->start_position();
1098 } 1024 }
1099 1025
1100 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 1026 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1101 // Source positions starts with zero. 1027 // Source positions starts with zero.
1102 DCHECK(position >= 0); 1028 DCHECK(position >= 0);
1103 1029
1104 // Find the break point and change it. 1030 // Find the break point and change it.
1105 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); 1031 BreakLocation location = BreakLocation::FromPosition(
1106 it.FindBreakLocationFromPosition(position, alignment); 1032 debug_info, SOURCE_BREAK_LOCATIONS, position, alignment);
1107 it.SetBreakPoint(break_point_object); 1033 location.SetBreakPoint(break_point_object);
1108 1034
1109 position = (alignment == STATEMENT_ALIGNED) ? it.statement_position() 1035 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position()
1110 : it.position(); 1036 : location.position();
1111 1037
1112 *source_position = position + shared->start_position(); 1038 *source_position = position + shared->start_position();
1113 1039
1114 // At least one active break point now. 1040 // At least one active break point now.
1115 DCHECK(debug_info->GetBreakPointCount() > 0); 1041 DCHECK(debug_info->GetBreakPointCount() > 0);
1116 return true; 1042 return true;
1117 } 1043 }
1118 1044
1119 1045
1120 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { 1046 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1121 HandleScope scope(isolate_); 1047 HandleScope scope(isolate_);
1122 1048
1123 DebugInfoListNode* node = debug_info_list_; 1049 DebugInfoListNode* node = debug_info_list_;
1124 while (node != NULL) { 1050 while (node != NULL) {
1125 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(), 1051 Handle<Object> result =
1126 break_point_object); 1052 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
1127 if (!result->IsUndefined()) { 1053 if (!result->IsUndefined()) {
1128 // Get information in the break point. 1054 // Get information in the break point.
1129 BreakPointInfo* break_point_info = BreakPointInfo::cast(result); 1055 Handle<BreakPointInfo> break_point_info =
1056 Handle<BreakPointInfo>::cast(result);
1130 Handle<DebugInfo> debug_info = node->debug_info(); 1057 Handle<DebugInfo> debug_info = node->debug_info();
1131 1058
1132 // Find the break point and clear it. 1059 // Find the break point and clear it.
1133 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); 1060 Address pc = debug_info->code()->entry() +
1134 it.FindBreakLocationFromAddress(debug_info->code()->entry() + 1061 break_point_info->code_position()->value();
1135 break_point_info->code_position()->value()); 1062
1136 it.ClearBreakPoint(break_point_object); 1063 BreakLocation location =
1064 BreakLocation::FromAddress(debug_info, SOURCE_BREAK_LOCATIONS, pc);
1065 location.ClearBreakPoint(break_point_object);
1137 1066
1138 // If there are no more break points left remove the debug info for this 1067 // If there are no more break points left remove the debug info for this
1139 // function. 1068 // function.
1140 if (debug_info->GetBreakPointCount() == 0) { 1069 if (debug_info->GetBreakPointCount() == 0) {
1141 RemoveDebugInfoAndClearFromShared(debug_info); 1070 RemoveDebugInfoAndClearFromShared(debug_info);
1142 } 1071 }
1143 1072
1144 return; 1073 return;
1145 } 1074 }
1146 node = node->next(); 1075 node = node->next();
1147 } 1076 }
1148 } 1077 }
1149 1078
1150 1079
1080 // Clear out all the debug break code. This is ONLY supposed to be used when
1081 // shutting down the debugger as it will leave the break point information in
1082 // DebugInfo even though the code is patched back to the non break point state.
1151 void Debug::ClearAllBreakPoints() { 1083 void Debug::ClearAllBreakPoints() {
1152 DebugInfoListNode* node = debug_info_list_; 1084 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
1153 while (node != NULL) { 1085 node = node->next()) {
1154 // Remove all debug break code. 1086 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1155 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); 1087 !it.Done(); it.Next()) {
1156 it.ClearAllDebugBreak(); 1088 it.GetBreakLocation().ClearDebugBreak();
1157 node = node->next(); 1089 }
1158 } 1090 }
1159
1160 // Remove all debug info. 1091 // Remove all debug info.
1161 while (debug_info_list_ != NULL) { 1092 while (debug_info_list_ != NULL) {
1162 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); 1093 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
1163 } 1094 }
1164 } 1095 }
1165 1096
1166 1097
1167 void Debug::FloodWithOneShot(Handle<JSFunction> function, 1098 void Debug::FloodWithOneShot(Handle<JSFunction> function,
1168 BreakLocatorType type) { 1099 BreakLocatorType type) {
1169 // Do not ever break in native functions. 1100 // Do not ever break in native functions.
1170 if (function->IsFromNativeScript()) return; 1101 if (function->IsFromNativeScript()) return;
1171 1102
1172 PrepareForBreakPoints(); 1103 PrepareForBreakPoints();
1173 1104
1174 // Make sure the function is compiled and has set up the debug info. 1105 // Make sure the function is compiled and has set up the debug info.
1175 Handle<SharedFunctionInfo> shared(function->shared()); 1106 Handle<SharedFunctionInfo> shared(function->shared());
1176 if (!EnsureDebugInfo(shared, function)) { 1107 if (!EnsureDebugInfo(shared, function)) {
1177 // Return if we failed to retrieve the debug info. 1108 // Return if we failed to retrieve the debug info.
1178 return; 1109 return;
1179 } 1110 }
1180 1111
1181 // Flood the function with break points. 1112 // Flood the function with break points.
1182 BreakLocationIterator it(GetDebugInfo(shared), type); 1113 for (BreakLocation::Iterator it(GetDebugInfo(shared), type); !it.Done();
1183 while (!it.Done()) { 1114 it.Next()) {
1184 it.SetOneShot(); 1115 it.GetBreakLocation().SetOneShot();
1185 it.Next();
1186 } 1116 }
1187 } 1117 }
1188 1118
1189 1119
1190 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) { 1120 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
1191 Handle<FixedArray> new_bindings(function->function_bindings()); 1121 Handle<FixedArray> new_bindings(function->function_bindings());
1192 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex), 1122 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
1193 isolate_); 1123 isolate_);
1194 1124
1195 if (!bindee.is_null() && bindee->IsJSFunction() && 1125 if (!bindee.is_null() && bindee->IsJSFunction() &&
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1334 if (!EnsureDebugInfo(shared, function)) { 1264 if (!EnsureDebugInfo(shared, function)) {
1335 // Return if ensuring debug info failed. 1265 // Return if ensuring debug info failed.
1336 return; 1266 return;
1337 } 1267 }
1338 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 1268 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1339 1269
1340 // Compute whether or not the target is a call target. 1270 // Compute whether or not the target is a call target.
1341 bool is_load_or_store = false; 1271 bool is_load_or_store = false;
1342 bool is_inline_cache_stub = false; 1272 bool is_inline_cache_stub = false;
1343 bool is_at_restarted_function = false; 1273 bool is_at_restarted_function = false;
1344 bool is_exit = false;
1345 bool is_construct_call = false;
1346 Handle<Code> call_function_stub; 1274 Handle<Code> call_function_stub;
1347 1275
1348 { 1276 // PC points to the instruction after the current one, possibly a break
1349 // Find the break location where execution has stopped. 1277 // location as well. So the "- 1" to exclude it from the search.
1350 DisallowHeapAllocation no_gc; 1278 Address call_pc = frame->pc() - 1;
1351 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS); 1279 BreakLocation location =
1280 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
1352 1281
1353 // pc points to the instruction after the current one, possibly a break 1282 if (thread_local_.restarter_frame_function_pointer_ == NULL) {
1354 // location as well. So the "- 1" to exclude it from the search. 1283 if (location.IsCodeTarget()) {
1355 it.FindBreakLocationFromAddress(frame->pc() - 1); 1284 Handle<Code> target_code = location.CodeTarget();
1285 is_inline_cache_stub = target_code->is_inline_cache_stub();
1286 is_load_or_store = is_inline_cache_stub && !target_code->is_call_stub();
1356 1287
1357 is_exit = it.IsExit(); 1288 // Check if target code is CallFunction stub.
1358 is_construct_call = RelocInfo::IsConstructCall(it.rmode()); 1289 Handle<Code> maybe_call_function_stub = target_code;
1359 1290 // If there is a breakpoint at this line look at the original code to
1360 if (thread_local_.restarter_frame_function_pointer_ == NULL) { 1291 // check if it is a CallFunction stub.
1361 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) { 1292 if (location.IsDebugBreak()) {
1362 bool is_call_target = false; 1293 maybe_call_function_stub = location.OriginalCodeTarget();
1363 Address target = it.rinfo()->target_address();
1364 Code* code = Code::GetCodeFromTargetAddress(target);
1365
1366 is_call_target = code->is_call_stub();
1367 is_inline_cache_stub = code->is_inline_cache_stub();
1368 is_load_or_store = is_inline_cache_stub && !is_call_target;
1369
1370 // Check if target code is CallFunction stub.
1371 Code* maybe_call_function_stub = code;
1372 // If there is a breakpoint at this line look at the original code to
1373 // check if it is a CallFunction stub.
1374 if (it.IsDebugBreak()) {
1375 Address original_target = it.original_rinfo()->target_address();
1376 maybe_call_function_stub =
1377 Code::GetCodeFromTargetAddress(original_target);
1378 }
1379 if ((maybe_call_function_stub->kind() == Code::STUB &&
1380 CodeStub::GetMajorKey(maybe_call_function_stub) ==
1381 CodeStub::CallFunction) ||
1382 maybe_call_function_stub->is_call_stub()) {
1383 // Save reference to the code as we may need it to find out arguments
1384 // count for 'step in' later.
1385 call_function_stub = Handle<Code>(maybe_call_function_stub);
1386 }
1387 } 1294 }
1388 } else { 1295 if ((maybe_call_function_stub->kind() == Code::STUB &&
1389 is_at_restarted_function = true; 1296 CodeStub::GetMajorKey(*maybe_call_function_stub) ==
1297 CodeStub::CallFunction) ||
1298 maybe_call_function_stub->is_call_stub()) {
1299 // Save reference to the code as we may need it to find out arguments
1300 // count for 'step in' later.
1301 call_function_stub = maybe_call_function_stub;
1302 }
1390 } 1303 }
1304 } else {
1305 is_at_restarted_function = true;
1391 } 1306 }
1392 1307
1393 // If this is the last break code target step out is the only possibility. 1308 // If this is the last break code target step out is the only possibility.
1394 if (is_exit || step_action == StepOut) { 1309 if (location.IsExit() || step_action == StepOut) {
1395 if (step_action == StepOut) { 1310 if (step_action == StepOut) {
1396 // Skip step_count frames starting with the current one. 1311 // Skip step_count frames starting with the current one.
1397 while (step_count-- > 0 && !frames_it.done()) { 1312 while (step_count-- > 0 && !frames_it.done()) {
1398 frames_it.Advance(); 1313 frames_it.Advance();
1399 } 1314 }
1400 } else { 1315 } else {
1401 DCHECK(is_exit); 1316 DCHECK(location.IsExit());
1402 frames_it.Advance(); 1317 frames_it.Advance();
1403 } 1318 }
1404 // Skip builtin functions on the stack. 1319 // Skip builtin functions on the stack.
1405 while (!frames_it.done() && 1320 while (!frames_it.done() &&
1406 frames_it.frame()->function()->IsFromNativeScript()) { 1321 frames_it.frame()->function()->IsFromNativeScript()) {
1407 frames_it.Advance(); 1322 frames_it.Advance();
1408 } 1323 }
1409 // Step out: If there is a JavaScript caller frame, we need to 1324 // Step out: If there is a JavaScript caller frame, we need to
1410 // flood it with breakpoints. 1325 // flood it with breakpoints.
1411 if (!frames_it.done()) { 1326 if (!frames_it.done()) {
1412 // Fill the function to return to with one-shot break points. 1327 // Fill the function to return to with one-shot break points.
1413 JSFunction* function = frames_it.frame()->function(); 1328 JSFunction* function = frames_it.frame()->function();
1414 FloodWithOneShot(Handle<JSFunction>(function)); 1329 FloodWithOneShot(Handle<JSFunction>(function));
1415 // Set target frame pointer. 1330 // Set target frame pointer.
1416 ActivateStepOut(frames_it.frame()); 1331 ActivateStepOut(frames_it.frame());
1417 } 1332 }
1418 } else if (!(is_inline_cache_stub || is_construct_call || 1333 } else if (!(is_inline_cache_stub || location.IsConstructCall() ||
1419 !call_function_stub.is_null() || is_at_restarted_function) || 1334 !call_function_stub.is_null() || is_at_restarted_function) ||
1420 step_action == StepNext || step_action == StepMin) { 1335 step_action == StepNext || step_action == StepMin) {
1421 // Step next or step min. 1336 // Step next or step min.
1422 1337
1423 // Fill the current function with one-shot break points. 1338 // Fill the current function with one-shot break points.
1424 // If we are stepping into another frame, only fill calls and returns. 1339 // If we are stepping into another frame, only fill calls and returns.
1425 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS 1340 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
1426 : ALL_BREAK_LOCATIONS); 1341 : ALL_BREAK_LOCATIONS);
1427 1342
1428 // Remember source position and frame to handle step next. 1343 // Remember source position and frame to handle step next.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 } 1419 }
1505 1420
1506 // Step in or Step in min 1421 // Step in or Step in min
1507 // Step in through construct call requires no changes to the running code. 1422 // Step in through construct call requires no changes to the running code.
1508 // Step in through getters/setters should already be prepared as well 1423 // Step in through getters/setters should already be prepared as well
1509 // because caller of this function (Debug::PrepareStep) is expected to 1424 // because caller of this function (Debug::PrepareStep) is expected to
1510 // flood the top frame's function with one shot breakpoints. 1425 // flood the top frame's function with one shot breakpoints.
1511 // Step in through CallFunction stub should also be prepared by caller of 1426 // Step in through CallFunction stub should also be prepared by caller of
1512 // this function (Debug::PrepareStep) which should flood target function 1427 // this function (Debug::PrepareStep) which should flood target function
1513 // with breakpoints. 1428 // with breakpoints.
1514 DCHECK(is_construct_call || is_inline_cache_stub || 1429 DCHECK(location.IsConstructCall() || is_inline_cache_stub ||
1515 !call_function_stub.is_null() || is_at_restarted_function); 1430 !call_function_stub.is_null() || is_at_restarted_function);
1516 ActivateStepIn(frame); 1431 ActivateStepIn(frame);
1517 } 1432 }
1518 } 1433 }
1519 1434
1520 1435
1521 // Check whether the current debug break should be reported to the debugger. It 1436 // Check whether the current debug break should be reported to the debugger. It
1522 // is used to have step next and step in only report break back to the debugger 1437 // is used to have step next and step in only report break back to the debugger
1523 // if on a different frame or in a different statement. In some situations 1438 // if on a different frame or in a different statement. In some situations
1524 // there will be several break points in the same statement when the code is 1439 // there will be several break points in the same statement when the code is
1525 // flooded with one-shot break points. This function helps to perform several 1440 // flooded with one-shot break points. This function helps to perform several
1526 // steps before reporting break back to the debugger. 1441 // steps before reporting break back to the debugger.
1527 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator, 1442 bool Debug::StepNextContinue(BreakLocation* break_location,
1528 JavaScriptFrame* frame) { 1443 JavaScriptFrame* frame) {
1529 // StepNext and StepOut shouldn't bring us deeper in code, so last frame 1444 // StepNext and StepOut shouldn't bring us deeper in code, so last frame
1530 // shouldn't be a parent of current frame. 1445 // shouldn't be a parent of current frame.
1531 StepAction step_action = thread_local_.last_step_action_; 1446 StepAction step_action = thread_local_.last_step_action_;
1532 1447
1533 if (step_action == StepNext || step_action == StepOut) { 1448 if (step_action == StepNext || step_action == StepOut) {
1534 if (frame->fp() < thread_local_.last_fp_) return true; 1449 if (frame->fp() < thread_local_.last_fp_) return true;
1535 } 1450 }
1536 1451
1537 // We stepped into a new frame if the frame pointer changed. 1452 // We stepped into a new frame if the frame pointer changed.
1538 if (step_action == StepFrame) { 1453 if (step_action == StepFrame) {
1539 return frame->UnpaddedFP() == thread_local_.last_fp_; 1454 return frame->UnpaddedFP() == thread_local_.last_fp_;
1540 } 1455 }
1541 1456
1542 // If the step last action was step next or step in make sure that a new 1457 // If the step last action was step next or step in make sure that a new
1543 // statement is hit. 1458 // statement is hit.
1544 if (step_action == StepNext || step_action == StepIn) { 1459 if (step_action == StepNext || step_action == StepIn) {
1545 // Never continue if returning from function. 1460 // Never continue if returning from function.
1546 if (break_location_iterator->IsExit()) return false; 1461 if (break_location->IsExit()) return false;
1547 1462
1548 // Continue if we are still on the same frame and in the same statement. 1463 // Continue if we are still on the same frame and in the same statement.
1549 int current_statement_position = 1464 int current_statement_position =
1550 break_location_iterator->code()->SourceStatementPosition(frame->pc()); 1465 break_location->code()->SourceStatementPosition(frame->pc());
1551 return thread_local_.last_fp_ == frame->UnpaddedFP() && 1466 return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1552 thread_local_.last_statement_position_ == current_statement_position; 1467 thread_local_.last_statement_position_ == current_statement_position;
1553 } 1468 }
1554 1469
1555 // No step next action - don't continue. 1470 // No step next action - don't continue.
1556 return false; 1471 return false;
1557 } 1472 }
1558 1473
1559 1474
1560 // Check whether the code object at the specified address is a debug break code 1475 // Check whether the code object at the specified address is a debug break code
1561 // object. 1476 // object.
1562 bool Debug::IsDebugBreak(Address addr) { 1477 bool Debug::IsDebugBreak(Address addr) {
1563 Code* code = Code::GetCodeFromTargetAddress(addr); 1478 Code* code = Code::GetCodeFromTargetAddress(addr);
1564 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK; 1479 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK;
1565 } 1480 }
1566 1481
1567 1482
1568
1569
1570
1571 // Simple function for returning the source positions for active break points. 1483 // Simple function for returning the source positions for active break points.
1572 Handle<Object> Debug::GetSourceBreakLocations( 1484 Handle<Object> Debug::GetSourceBreakLocations(
1573 Handle<SharedFunctionInfo> shared, 1485 Handle<SharedFunctionInfo> shared,
1574 BreakPositionAlignment position_alignment) { 1486 BreakPositionAlignment position_alignment) {
1575 Isolate* isolate = shared->GetIsolate(); 1487 Isolate* isolate = shared->GetIsolate();
1576 Heap* heap = isolate->heap(); 1488 Heap* heap = isolate->heap();
1577 if (!HasDebugInfo(shared)) { 1489 if (!HasDebugInfo(shared)) {
1578 return Handle<Object>(heap->undefined_value(), isolate); 1490 return Handle<Object>(heap->undefined_value(), isolate);
1579 } 1491 }
1580 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 1492 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1648 } 1560 }
1649 1561
1650 1562
1651 // Clears all the one-shot break points that are currently set. Normally this 1563 // Clears all the one-shot break points that are currently set. Normally this
1652 // function is called each time a break point is hit as one shot break points 1564 // function is called each time a break point is hit as one shot break points
1653 // are used to support stepping. 1565 // are used to support stepping.
1654 void Debug::ClearOneShot() { 1566 void Debug::ClearOneShot() {
1655 // The current implementation just runs through all the breakpoints. When the 1567 // The current implementation just runs through all the breakpoints. When the
1656 // last break point for a function is removed that function is automatically 1568 // last break point for a function is removed that function is automatically
1657 // removed from the list. 1569 // removed from the list.
1658 1570 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
1659 DebugInfoListNode* node = debug_info_list_; 1571 node = node->next()) {
1660 while (node != NULL) { 1572 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1661 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); 1573 !it.Done(); it.Next()) {
1662 while (!it.Done()) { 1574 it.GetBreakLocation().ClearOneShot();
1663 it.ClearOneShot();
1664 it.Next();
1665 } 1575 }
1666 node = node->next();
1667 } 1576 }
1668 } 1577 }
1669 1578
1670 1579
1671 void Debug::ActivateStepIn(StackFrame* frame) { 1580 void Debug::ActivateStepIn(StackFrame* frame) {
1672 DCHECK(!StepOutActive()); 1581 DCHECK(!StepOutActive());
1673 thread_local_.step_into_fp_ = frame->UnpaddedFP(); 1582 thread_local_.step_into_fp_ = frame->UnpaddedFP();
1674 } 1583 }
1675 1584
1676 1585
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
2073 RedirectActivationsToRecompiledCodeOnThread(isolate_, 1982 RedirectActivationsToRecompiledCodeOnThread(isolate_,
2074 isolate_->thread_local_top()); 1983 isolate_->thread_local_top());
2075 1984
2076 ActiveFunctionsRedirector active_functions_redirector; 1985 ActiveFunctionsRedirector active_functions_redirector;
2077 isolate_->thread_manager()->IterateArchivedThreads( 1986 isolate_->thread_manager()->IterateArchivedThreads(
2078 &active_functions_redirector); 1987 &active_functions_redirector);
2079 } 1988 }
2080 } 1989 }
2081 1990
2082 1991
2083 Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script, 1992 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2084 int position) { 1993 int position) {
2085 // Iterate the heap looking for SharedFunctionInfo generated from the 1994 // Iterate the heap looking for SharedFunctionInfo generated from the
2086 // script. The inner most SharedFunctionInfo containing the source position 1995 // script. The inner most SharedFunctionInfo containing the source position
2087 // for the requested break point is found. 1996 // for the requested break point is found.
2088 // NOTE: This might require several heap iterations. If the SharedFunctionInfo 1997 // NOTE: This might require several heap iterations. If the SharedFunctionInfo
2089 // which is found is not compiled it is compiled and the heap is iterated 1998 // which is found is not compiled it is compiled and the heap is iterated
2090 // again as the compilation might create inner functions from the newly 1999 // again as the compilation might create inner functions from the newly
2091 // compiled function and the actual requested break point might be in one of 2000 // compiled function and the actual requested break point might be in one of
2092 // these functions. 2001 // these functions.
2093 // NOTE: The below fix-point iteration depends on all functions that cannot be 2002 // NOTE: The below fix-point iteration depends on all functions that cannot be
2094 // compiled lazily without a context to not be compiled at all. Compilation 2003 // compiled lazily without a context to not be compiled at all. Compilation
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2157 target_start_position = start_position; 2066 target_start_position = start_position;
2158 target_function = function; 2067 target_function = function;
2159 target = shared; 2068 target = shared;
2160 } 2069 }
2161 } 2070 }
2162 } 2071 }
2163 } 2072 }
2164 } // End for loop. 2073 } // End for loop.
2165 } // End no-allocation scope. 2074 } // End no-allocation scope.
2166 2075
2167 if (target.is_null()) return heap->undefined_value(); 2076 if (target.is_null()) return isolate_->factory()->undefined_value();
2168 2077
2169 // There will be at least one break point when we are done. 2078 // There will be at least one break point when we are done.
2170 has_break_points_ = true; 2079 has_break_points_ = true;
2171 2080
2172 // If the candidate found is compiled we are done. 2081 // If the candidate found is compiled we are done.
2173 done = target->is_compiled(); 2082 done = target->is_compiled();
2174 if (!done) { 2083 if (!done) {
2175 // If the candidate is not compiled, compile it to reveal any inner 2084 // If the candidate is not compiled, compile it to reveal any inner
2176 // functions which might contain the requested source position. This 2085 // functions which might contain the requested source position. This
2177 // will compile all inner functions that cannot be compiled without a 2086 // will compile all inner functions that cannot be compiled without a
2178 // context, because Compiler::BuildFunctionInfo checks whether the 2087 // context, because Compiler::BuildFunctionInfo checks whether the
2179 // debugger is active. 2088 // debugger is active.
2180 MaybeHandle<Code> maybe_result = target_function.is_null() 2089 MaybeHandle<Code> maybe_result = target_function.is_null()
2181 ? Compiler::GetUnoptimizedCode(target) 2090 ? Compiler::GetUnoptimizedCode(target)
2182 : Compiler::GetUnoptimizedCode(target_function); 2091 : Compiler::GetUnoptimizedCode(target_function);
2183 if (maybe_result.is_null()) return isolate_->heap()->undefined_value(); 2092 if (maybe_result.is_null()) return isolate_->factory()->undefined_value();
2184 } 2093 }
2185 } // End while loop. 2094 } // End while loop.
2186 2095
2187 return *target; 2096 return target;
2188 } 2097 }
2189 2098
2190 2099
2191 // Ensures the debug information is present for shared. 2100 // Ensures the debug information is present for shared.
2192 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, 2101 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2193 Handle<JSFunction> function) { 2102 Handle<JSFunction> function) {
2194 Isolate* isolate = shared->GetIsolate(); 2103 Isolate* isolate = shared->GetIsolate();
2195 2104
2196 // Return if we already have the debug info for shared. 2105 // Return if we already have the debug info for shared.
2197 if (HasDebugInfo(shared)) { 2106 if (HasDebugInfo(shared)) {
(...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after
3472 logger_->DebugEvent("Put", message.text()); 3381 logger_->DebugEvent("Put", message.text());
3473 } 3382 }
3474 3383
3475 3384
3476 void LockingCommandMessageQueue::Clear() { 3385 void LockingCommandMessageQueue::Clear() {
3477 base::LockGuard<base::Mutex> lock_guard(&mutex_); 3386 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3478 queue_.Clear(); 3387 queue_.Clear();
3479 } 3388 }
3480 3389
3481 } } // namespace v8::internal 3390 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/debug.h ('k') | src/ia32/assembler-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698