| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 BreakLocatorType type) { | 66 BreakLocatorType type) { |
| 67 debug_info_ = debug_info; | 67 debug_info_ = debug_info; |
| 68 type_ = type; | 68 type_ = type; |
| 69 reloc_iterator_ = NULL; | 69 reloc_iterator_ = NULL; |
| 70 reloc_iterator_original_ = NULL; | 70 reloc_iterator_original_ = NULL; |
| 71 Reset(); // Initialize the rest of the member variables. | 71 Reset(); // Initialize the rest of the member variables. |
| 72 } | 72 } |
| 73 | 73 |
| 74 | 74 |
| 75 BreakLocationIterator::~BreakLocationIterator() { | 75 BreakLocationIterator::~BreakLocationIterator() { |
| 76 ASSERT(reloc_iterator_ != NULL); | 76 DCHECK(reloc_iterator_ != NULL); |
| 77 ASSERT(reloc_iterator_original_ != NULL); | 77 DCHECK(reloc_iterator_original_ != NULL); |
| 78 delete reloc_iterator_; | 78 delete reloc_iterator_; |
| 79 delete reloc_iterator_original_; | 79 delete reloc_iterator_original_; |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 // Check whether a code stub with the specified major key is a possible break | 83 // Check whether a code stub with the specified major key is a possible break |
| 84 // point location when looking for source break locations. | 84 // point location when looking for source break locations. |
| 85 static bool IsSourceBreakStub(Code* code) { | 85 static bool IsSourceBreakStub(Code* code) { |
| 86 CodeStub::Major major_key = CodeStub::GetMajorKey(code); | 86 CodeStub::Major major_key = CodeStub::GetMajorKey(code); |
| 87 return major_key == CodeStub::CallFunction; | 87 return major_key == CodeStub::CallFunction; |
| 88 } | 88 } |
| 89 | 89 |
| 90 | 90 |
| 91 // Check whether a code stub with the specified major key is a possible break | 91 // Check whether a code stub with the specified major key is a possible break |
| 92 // location. | 92 // location. |
| 93 static bool IsBreakStub(Code* code) { | 93 static bool IsBreakStub(Code* code) { |
| 94 CodeStub::Major major_key = CodeStub::GetMajorKey(code); | 94 CodeStub::Major major_key = CodeStub::GetMajorKey(code); |
| 95 return major_key == CodeStub::CallFunction; | 95 return major_key == CodeStub::CallFunction; |
| 96 } | 96 } |
| 97 | 97 |
| 98 | 98 |
| 99 void BreakLocationIterator::Next() { | 99 void BreakLocationIterator::Next() { |
| 100 DisallowHeapAllocation no_gc; | 100 DisallowHeapAllocation no_gc; |
| 101 ASSERT(!RinfoDone()); | 101 DCHECK(!RinfoDone()); |
| 102 | 102 |
| 103 // Iterate through reloc info for code and original code stopping at each | 103 // Iterate through reloc info for code and original code stopping at each |
| 104 // breakable code target. | 104 // breakable code target. |
| 105 bool first = break_point_ == -1; | 105 bool first = break_point_ == -1; |
| 106 while (!RinfoDone()) { | 106 while (!RinfoDone()) { |
| 107 if (!first) RinfoNext(); | 107 if (!first) RinfoNext(); |
| 108 first = false; | 108 first = false; |
| 109 if (RinfoDone()) return; | 109 if (RinfoDone()) return; |
| 110 | 110 |
| 111 // Whenever a statement position or (plain) position is passed update the | 111 // Whenever a statement position or (plain) position is passed update the |
| 112 // current value of these. | 112 // current value of these. |
| 113 if (RelocInfo::IsPosition(rmode())) { | 113 if (RelocInfo::IsPosition(rmode())) { |
| 114 if (RelocInfo::IsStatementPosition(rmode())) { | 114 if (RelocInfo::IsStatementPosition(rmode())) { |
| 115 statement_position_ = static_cast<int>( | 115 statement_position_ = static_cast<int>( |
| 116 rinfo()->data() - debug_info_->shared()->start_position()); | 116 rinfo()->data() - debug_info_->shared()->start_position()); |
| 117 } | 117 } |
| 118 // Always update the position as we don't want that to be before the | 118 // Always update the position as we don't want that to be before the |
| 119 // statement position. | 119 // statement position. |
| 120 position_ = static_cast<int>( | 120 position_ = static_cast<int>( |
| 121 rinfo()->data() - debug_info_->shared()->start_position()); | 121 rinfo()->data() - debug_info_->shared()->start_position()); |
| 122 ASSERT(position_ >= 0); | 122 DCHECK(position_ >= 0); |
| 123 ASSERT(statement_position_ >= 0); | 123 DCHECK(statement_position_ >= 0); |
| 124 } | 124 } |
| 125 | 125 |
| 126 if (IsDebugBreakSlot()) { | 126 if (IsDebugBreakSlot()) { |
| 127 // There is always a possible break point at a debug break slot. | 127 // There is always a possible break point at a debug break slot. |
| 128 break_point_++; | 128 break_point_++; |
| 129 return; | 129 return; |
| 130 } else if (RelocInfo::IsCodeTarget(rmode())) { | 130 } else if (RelocInfo::IsCodeTarget(rmode())) { |
| 131 // Check for breakable code target. Look in the original code as setting | 131 // Check for breakable code target. Look in the original code as setting |
| 132 // break points can cause the code targets in the running (debugged) code | 132 // break points can cause the code targets in the running (debugged) code |
| 133 // to be of a different kind than in the original code. | 133 // to be of a different kind than in the original code. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 144 if (code->kind() == Code::STUB) { | 144 if (code->kind() == Code::STUB) { |
| 145 if (IsDebuggerStatement()) { | 145 if (IsDebuggerStatement()) { |
| 146 break_point_++; | 146 break_point_++; |
| 147 return; | 147 return; |
| 148 } else if (type_ == ALL_BREAK_LOCATIONS) { | 148 } else if (type_ == ALL_BREAK_LOCATIONS) { |
| 149 if (IsBreakStub(code)) { | 149 if (IsBreakStub(code)) { |
| 150 break_point_++; | 150 break_point_++; |
| 151 return; | 151 return; |
| 152 } | 152 } |
| 153 } else { | 153 } else { |
| 154 ASSERT(type_ == SOURCE_BREAK_LOCATIONS); | 154 DCHECK(type_ == SOURCE_BREAK_LOCATIONS); |
| 155 if (IsSourceBreakStub(code)) { | 155 if (IsSourceBreakStub(code)) { |
| 156 break_point_++; | 156 break_point_++; |
| 157 return; | 157 return; |
| 158 } | 158 } |
| 159 } | 159 } |
| 160 } | 160 } |
| 161 } | 161 } |
| 162 | 162 |
| 163 // Check for break at return. | 163 // Check for break at return. |
| 164 if (RelocInfo::IsJSReturn(rmode())) { | 164 if (RelocInfo::IsJSReturn(rmode())) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 | 266 |
| 267 bool BreakLocationIterator::Done() const { | 267 bool BreakLocationIterator::Done() const { |
| 268 return RinfoDone(); | 268 return RinfoDone(); |
| 269 } | 269 } |
| 270 | 270 |
| 271 | 271 |
| 272 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) { | 272 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) { |
| 273 // If there is not already a real break point here patch code with debug | 273 // If there is not already a real break point here patch code with debug |
| 274 // break. | 274 // break. |
| 275 if (!HasBreakPoint()) SetDebugBreak(); | 275 if (!HasBreakPoint()) SetDebugBreak(); |
| 276 ASSERT(IsDebugBreak() || IsDebuggerStatement()); | 276 DCHECK(IsDebugBreak() || IsDebuggerStatement()); |
| 277 // Set the break point information. | 277 // Set the break point information. |
| 278 DebugInfo::SetBreakPoint(debug_info_, code_position(), | 278 DebugInfo::SetBreakPoint(debug_info_, code_position(), |
| 279 position(), statement_position(), | 279 position(), statement_position(), |
| 280 break_point_object); | 280 break_point_object); |
| 281 } | 281 } |
| 282 | 282 |
| 283 | 283 |
| 284 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) { | 284 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) { |
| 285 // Clear the break point information. | 285 // Clear the break point information. |
| 286 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object); | 286 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object); |
| 287 // If there are no more break points here remove the debug break. | 287 // If there are no more break points here remove the debug break. |
| 288 if (!HasBreakPoint()) { | 288 if (!HasBreakPoint()) { |
| 289 ClearDebugBreak(); | 289 ClearDebugBreak(); |
| 290 ASSERT(!IsDebugBreak()); | 290 DCHECK(!IsDebugBreak()); |
| 291 } | 291 } |
| 292 } | 292 } |
| 293 | 293 |
| 294 | 294 |
| 295 void BreakLocationIterator::SetOneShot() { | 295 void BreakLocationIterator::SetOneShot() { |
| 296 // Debugger statement always calls debugger. No need to modify it. | 296 // Debugger statement always calls debugger. No need to modify it. |
| 297 if (IsDebuggerStatement()) return; | 297 if (IsDebuggerStatement()) return; |
| 298 | 298 |
| 299 // If there is a real break point here no more to do. | 299 // If there is a real break point here no more to do. |
| 300 if (HasBreakPoint()) { | 300 if (HasBreakPoint()) { |
| 301 ASSERT(IsDebugBreak()); | 301 DCHECK(IsDebugBreak()); |
| 302 return; | 302 return; |
| 303 } | 303 } |
| 304 | 304 |
| 305 // Patch code with debug break. | 305 // Patch code with debug break. |
| 306 SetDebugBreak(); | 306 SetDebugBreak(); |
| 307 } | 307 } |
| 308 | 308 |
| 309 | 309 |
| 310 void BreakLocationIterator::ClearOneShot() { | 310 void BreakLocationIterator::ClearOneShot() { |
| 311 // Debugger statement always calls debugger. No need to modify it. | 311 // Debugger statement always calls debugger. No need to modify it. |
| 312 if (IsDebuggerStatement()) return; | 312 if (IsDebuggerStatement()) return; |
| 313 | 313 |
| 314 // If there is a real break point here no more to do. | 314 // If there is a real break point here no more to do. |
| 315 if (HasBreakPoint()) { | 315 if (HasBreakPoint()) { |
| 316 ASSERT(IsDebugBreak()); | 316 DCHECK(IsDebugBreak()); |
| 317 return; | 317 return; |
| 318 } | 318 } |
| 319 | 319 |
| 320 // Patch code removing debug break. | 320 // Patch code removing debug break. |
| 321 ClearDebugBreak(); | 321 ClearDebugBreak(); |
| 322 ASSERT(!IsDebugBreak()); | 322 DCHECK(!IsDebugBreak()); |
| 323 } | 323 } |
| 324 | 324 |
| 325 | 325 |
| 326 void BreakLocationIterator::SetDebugBreak() { | 326 void BreakLocationIterator::SetDebugBreak() { |
| 327 // Debugger statement always calls debugger. No need to modify it. | 327 // Debugger statement always calls debugger. No need to modify it. |
| 328 if (IsDebuggerStatement()) return; | 328 if (IsDebuggerStatement()) return; |
| 329 | 329 |
| 330 // If there is already a break point here just return. This might happen if | 330 // If there is already a break point here just return. This might happen if |
| 331 // the same code is flooded with break points twice. Flooding the same | 331 // the same code is flooded with break points twice. Flooding the same |
| 332 // function twice might happen when stepping in a function with an exception | 332 // function twice might happen when stepping in a function with an exception |
| 333 // handler as the handler and the function is the same. | 333 // handler as the handler and the function is the same. |
| 334 if (IsDebugBreak()) return; | 334 if (IsDebugBreak()) return; |
| 335 | 335 |
| 336 if (RelocInfo::IsJSReturn(rmode())) { | 336 if (RelocInfo::IsJSReturn(rmode())) { |
| 337 // Patch the frame exit code with a break point. | 337 // Patch the frame exit code with a break point. |
| 338 SetDebugBreakAtReturn(); | 338 SetDebugBreakAtReturn(); |
| 339 } else if (IsDebugBreakSlot()) { | 339 } else if (IsDebugBreakSlot()) { |
| 340 // Patch the code in the break slot. | 340 // Patch the code in the break slot. |
| 341 SetDebugBreakAtSlot(); | 341 SetDebugBreakAtSlot(); |
| 342 } else { | 342 } else { |
| 343 // Patch the IC call. | 343 // Patch the IC call. |
| 344 SetDebugBreakAtIC(); | 344 SetDebugBreakAtIC(); |
| 345 } | 345 } |
| 346 ASSERT(IsDebugBreak()); | 346 DCHECK(IsDebugBreak()); |
| 347 } | 347 } |
| 348 | 348 |
| 349 | 349 |
| 350 void BreakLocationIterator::ClearDebugBreak() { | 350 void BreakLocationIterator::ClearDebugBreak() { |
| 351 // Debugger statement always calls debugger. No need to modify it. | 351 // Debugger statement always calls debugger. No need to modify it. |
| 352 if (IsDebuggerStatement()) return; | 352 if (IsDebuggerStatement()) return; |
| 353 | 353 |
| 354 if (RelocInfo::IsJSReturn(rmode())) { | 354 if (RelocInfo::IsJSReturn(rmode())) { |
| 355 // Restore the frame exit code. | 355 // Restore the frame exit code. |
| 356 ClearDebugBreakAtReturn(); | 356 ClearDebugBreakAtReturn(); |
| 357 } else if (IsDebugBreakSlot()) { | 357 } else if (IsDebugBreakSlot()) { |
| 358 // Restore the code in the break slot. | 358 // Restore the code in the break slot. |
| 359 ClearDebugBreakAtSlot(); | 359 ClearDebugBreakAtSlot(); |
| 360 } else { | 360 } else { |
| 361 // Patch the IC call. | 361 // Patch the IC call. |
| 362 ClearDebugBreakAtIC(); | 362 ClearDebugBreakAtIC(); |
| 363 } | 363 } |
| 364 ASSERT(!IsDebugBreak()); | 364 DCHECK(!IsDebugBreak()); |
| 365 } | 365 } |
| 366 | 366 |
| 367 | 367 |
| 368 bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) { | 368 bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) { |
| 369 if (RelocInfo::IsConstructCall(original_rmode())) { | 369 if (RelocInfo::IsConstructCall(original_rmode())) { |
| 370 return true; | 370 return true; |
| 371 } else if (RelocInfo::IsCodeTarget(rmode())) { | 371 } else if (RelocInfo::IsCodeTarget(rmode())) { |
| 372 HandleScope scope(debug_info_->GetIsolate()); | 372 HandleScope scope(debug_info_->GetIsolate()); |
| 373 Address target = original_rinfo()->target_address(); | 373 Address target = original_rinfo()->target_address(); |
| 374 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); | 374 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 401 CodeStub::GetMajorKey(*maybe_call_function_stub) == | 401 CodeStub::GetMajorKey(*maybe_call_function_stub) == |
| 402 CodeStub::CallFunction); | 402 CodeStub::CallFunction); |
| 403 | 403 |
| 404 // Step in through construct call requires no changes to the running code. | 404 // Step in through construct call requires no changes to the running code. |
| 405 // Step in through getters/setters should already be prepared as well | 405 // Step in through getters/setters should already be prepared as well |
| 406 // because caller of this function (Debug::PrepareStep) is expected to | 406 // because caller of this function (Debug::PrepareStep) is expected to |
| 407 // flood the top frame's function with one shot breakpoints. | 407 // flood the top frame's function with one shot breakpoints. |
| 408 // Step in through CallFunction stub should also be prepared by caller of | 408 // Step in through CallFunction stub should also be prepared by caller of |
| 409 // this function (Debug::PrepareStep) which should flood target function | 409 // this function (Debug::PrepareStep) which should flood target function |
| 410 // with breakpoints. | 410 // with breakpoints. |
| 411 ASSERT(RelocInfo::IsConstructCall(rmode()) || | 411 DCHECK(RelocInfo::IsConstructCall(rmode()) || |
| 412 target_code->is_inline_cache_stub() || | 412 target_code->is_inline_cache_stub() || |
| 413 is_call_function_stub); | 413 is_call_function_stub); |
| 414 #endif | 414 #endif |
| 415 } | 415 } |
| 416 | 416 |
| 417 | 417 |
| 418 // Check whether the break point is at a position which will exit the function. | 418 // Check whether the break point is at a position which will exit the function. |
| 419 bool BreakLocationIterator::IsExit() const { | 419 bool BreakLocationIterator::IsExit() const { |
| 420 return (RelocInfo::IsJSReturn(rmode())); | 420 return (RelocInfo::IsJSReturn(rmode())); |
| 421 } | 421 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 } | 469 } |
| 470 } | 470 } |
| 471 if (RelocInfo::IsConstructCall(mode)) { | 471 if (RelocInfo::IsConstructCall(mode)) { |
| 472 if (code->has_function_cache()) { | 472 if (code->has_function_cache()) { |
| 473 return isolate->builtins()->CallConstructStub_Recording_DebugBreak(); | 473 return isolate->builtins()->CallConstructStub_Recording_DebugBreak(); |
| 474 } else { | 474 } else { |
| 475 return isolate->builtins()->CallConstructStub_DebugBreak(); | 475 return isolate->builtins()->CallConstructStub_DebugBreak(); |
| 476 } | 476 } |
| 477 } | 477 } |
| 478 if (code->kind() == Code::STUB) { | 478 if (code->kind() == Code::STUB) { |
| 479 ASSERT(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction); | 479 DCHECK(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction); |
| 480 return isolate->builtins()->CallFunctionStub_DebugBreak(); | 480 return isolate->builtins()->CallFunctionStub_DebugBreak(); |
| 481 } | 481 } |
| 482 | 482 |
| 483 UNREACHABLE(); | 483 UNREACHABLE(); |
| 484 return Handle<Code>::null(); | 484 return Handle<Code>::null(); |
| 485 } | 485 } |
| 486 | 486 |
| 487 | 487 |
| 488 void BreakLocationIterator::SetDebugBreakAtIC() { | 488 void BreakLocationIterator::SetDebugBreakAtIC() { |
| 489 // Patch the original code with the current address as the current address | 489 // Patch the original code with the current address as the current address |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 // DebugInfo even though the code is patched back to the non break point state. | 529 // DebugInfo even though the code is patched back to the non break point state. |
| 530 void BreakLocationIterator::ClearAllDebugBreak() { | 530 void BreakLocationIterator::ClearAllDebugBreak() { |
| 531 while (!Done()) { | 531 while (!Done()) { |
| 532 ClearDebugBreak(); | 532 ClearDebugBreak(); |
| 533 Next(); | 533 Next(); |
| 534 } | 534 } |
| 535 } | 535 } |
| 536 | 536 |
| 537 | 537 |
| 538 bool BreakLocationIterator::RinfoDone() const { | 538 bool BreakLocationIterator::RinfoDone() const { |
| 539 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); | 539 DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done()); |
| 540 return reloc_iterator_->done(); | 540 return reloc_iterator_->done(); |
| 541 } | 541 } |
| 542 | 542 |
| 543 | 543 |
| 544 void BreakLocationIterator::RinfoNext() { | 544 void BreakLocationIterator::RinfoNext() { |
| 545 reloc_iterator_->next(); | 545 reloc_iterator_->next(); |
| 546 reloc_iterator_original_->next(); | 546 reloc_iterator_original_->next(); |
| 547 #ifdef DEBUG | 547 #ifdef DEBUG |
| 548 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); | 548 DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done()); |
| 549 if (!reloc_iterator_->done()) { | 549 if (!reloc_iterator_->done()) { |
| 550 ASSERT(rmode() == original_rmode()); | 550 DCHECK(rmode() == original_rmode()); |
| 551 } | 551 } |
| 552 #endif | 552 #endif |
| 553 } | 553 } |
| 554 | 554 |
| 555 | 555 |
| 556 // Threading support. | 556 // Threading support. |
| 557 void Debug::ThreadInit() { | 557 void Debug::ThreadInit() { |
| 558 thread_local_.break_count_ = 0; | 558 thread_local_.break_count_ = 0; |
| 559 thread_local_.break_id_ = 0; | 559 thread_local_.break_id_ = 0; |
| 560 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 560 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 GlobalHandles* global_handles = isolate_->global_handles(); | 619 GlobalHandles* global_handles = isolate_->global_handles(); |
| 620 // Create an entry in the hash map for the script. | 620 // Create an entry in the hash map for the script. |
| 621 int id = script->id()->value(); | 621 int id = script->id()->value(); |
| 622 HashMap::Entry* entry = | 622 HashMap::Entry* entry = |
| 623 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true); | 623 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true); |
| 624 if (entry->value != NULL) { | 624 if (entry->value != NULL) { |
| 625 #ifdef DEBUG | 625 #ifdef DEBUG |
| 626 // The code deserializer may introduce duplicate Script objects. | 626 // The code deserializer may introduce duplicate Script objects. |
| 627 // Assert that the Script objects with the same id have the same name. | 627 // Assert that the Script objects with the same id have the same name. |
| 628 Handle<Script> found(reinterpret_cast<Script**>(entry->value)); | 628 Handle<Script> found(reinterpret_cast<Script**>(entry->value)); |
| 629 ASSERT(script->id() == found->id()); | 629 DCHECK(script->id() == found->id()); |
| 630 ASSERT(!script->name()->IsString() || | 630 DCHECK(!script->name()->IsString() || |
| 631 String::cast(script->name())->Equals(String::cast(found->name()))); | 631 String::cast(script->name())->Equals(String::cast(found->name()))); |
| 632 #endif | 632 #endif |
| 633 return; | 633 return; |
| 634 } | 634 } |
| 635 // Globalize the script object, make it weak and use the location of the | 635 // Globalize the script object, make it weak and use the location of the |
| 636 // global handle as the value in the hash map. | 636 // global handle as the value in the hash map. |
| 637 Handle<Script> script_ = | 637 Handle<Script> script_ = |
| 638 Handle<Script>::cast(global_handles->Create(*script)); | 638 Handle<Script>::cast(global_handles->Create(*script)); |
| 639 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()), | 639 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()), |
| 640 this, | 640 this, |
| 641 ScriptCache::HandleWeakScript); | 641 ScriptCache::HandleWeakScript); |
| 642 entry->value = script_.location(); | 642 entry->value = script_.location(); |
| 643 } | 643 } |
| 644 | 644 |
| 645 | 645 |
| 646 Handle<FixedArray> ScriptCache::GetScripts() { | 646 Handle<FixedArray> ScriptCache::GetScripts() { |
| 647 Factory* factory = isolate_->factory(); | 647 Factory* factory = isolate_->factory(); |
| 648 Handle<FixedArray> instances = factory->NewFixedArray(occupancy()); | 648 Handle<FixedArray> instances = factory->NewFixedArray(occupancy()); |
| 649 int count = 0; | 649 int count = 0; |
| 650 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) { | 650 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) { |
| 651 ASSERT(entry->value != NULL); | 651 DCHECK(entry->value != NULL); |
| 652 if (entry->value != NULL) { | 652 if (entry->value != NULL) { |
| 653 instances->set(count, *reinterpret_cast<Script**>(entry->value)); | 653 instances->set(count, *reinterpret_cast<Script**>(entry->value)); |
| 654 count++; | 654 count++; |
| 655 } | 655 } |
| 656 } | 656 } |
| 657 return instances; | 657 return instances; |
| 658 } | 658 } |
| 659 | 659 |
| 660 | 660 |
| 661 void ScriptCache::Clear() { | 661 void ScriptCache::Clear() { |
| 662 // Iterate the script cache to get rid of all the weak handles. | 662 // Iterate the script cache to get rid of all the weak handles. |
| 663 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) { | 663 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) { |
| 664 ASSERT(entry != NULL); | 664 DCHECK(entry != NULL); |
| 665 Object** location = reinterpret_cast<Object**>(entry->value); | 665 Object** location = reinterpret_cast<Object**>(entry->value); |
| 666 ASSERT((*location)->IsScript()); | 666 DCHECK((*location)->IsScript()); |
| 667 GlobalHandles::ClearWeakness(location); | 667 GlobalHandles::ClearWeakness(location); |
| 668 GlobalHandles::Destroy(location); | 668 GlobalHandles::Destroy(location); |
| 669 } | 669 } |
| 670 // Clear the content of the hash map. | 670 // Clear the content of the hash map. |
| 671 HashMap::Clear(); | 671 HashMap::Clear(); |
| 672 } | 672 } |
| 673 | 673 |
| 674 | 674 |
| 675 void ScriptCache::HandleWeakScript( | 675 void ScriptCache::HandleWeakScript( |
| 676 const v8::WeakCallbackData<v8::Value, void>& data) { | 676 const v8::WeakCallbackData<v8::Value, void>& data) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 701 // original code and avoid patching the code twice later because | 701 // original code and avoid patching the code twice later because |
| 702 // the function will live in the heap until next gc, and can be found by | 702 // the function will live in the heap until next gc, and can be found by |
| 703 // Debug::FindSharedFunctionInfoInScript. | 703 // Debug::FindSharedFunctionInfoInScript. |
| 704 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | 704 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); |
| 705 it.ClearAllDebugBreak(); | 705 it.ClearAllDebugBreak(); |
| 706 debug->RemoveDebugInfo(node->debug_info()); | 706 debug->RemoveDebugInfo(node->debug_info()); |
| 707 #ifdef DEBUG | 707 #ifdef DEBUG |
| 708 for (DebugInfoListNode* n = debug->debug_info_list_; | 708 for (DebugInfoListNode* n = debug->debug_info_list_; |
| 709 n != NULL; | 709 n != NULL; |
| 710 n = n->next()) { | 710 n = n->next()) { |
| 711 ASSERT(n != node); | 711 DCHECK(n != node); |
| 712 } | 712 } |
| 713 #endif | 713 #endif |
| 714 } | 714 } |
| 715 | 715 |
| 716 | 716 |
| 717 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { | 717 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { |
| 718 // Globalize the request debug info object and make it weak. | 718 // Globalize the request debug info object and make it weak. |
| 719 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); | 719 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); |
| 720 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info)); | 720 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info)); |
| 721 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()), | 721 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()), |
| (...skipping 23 matching lines...) Expand all Loading... |
| 745 Handle<Context> context = isolate->native_context(); | 745 Handle<Context> context = isolate->native_context(); |
| 746 | 746 |
| 747 // Compile the script. | 747 // Compile the script. |
| 748 Handle<SharedFunctionInfo> function_info; | 748 Handle<SharedFunctionInfo> function_info; |
| 749 function_info = Compiler::CompileScript( | 749 function_info = Compiler::CompileScript( |
| 750 source_code, script_name, 0, 0, false, context, NULL, NULL, | 750 source_code, script_name, 0, 0, false, context, NULL, NULL, |
| 751 ScriptCompiler::kNoCompileOptions, NATIVES_CODE); | 751 ScriptCompiler::kNoCompileOptions, NATIVES_CODE); |
| 752 | 752 |
| 753 // Silently ignore stack overflows during compilation. | 753 // Silently ignore stack overflows during compilation. |
| 754 if (function_info.is_null()) { | 754 if (function_info.is_null()) { |
| 755 ASSERT(isolate->has_pending_exception()); | 755 DCHECK(isolate->has_pending_exception()); |
| 756 isolate->clear_pending_exception(); | 756 isolate->clear_pending_exception(); |
| 757 return false; | 757 return false; |
| 758 } | 758 } |
| 759 | 759 |
| 760 // Execute the shared function in the debugger context. | 760 // Execute the shared function in the debugger context. |
| 761 Handle<JSFunction> function = | 761 Handle<JSFunction> function = |
| 762 factory->NewFunctionFromSharedFunctionInfo(function_info, context); | 762 factory->NewFunctionFromSharedFunctionInfo(function_info, context); |
| 763 | 763 |
| 764 Handle<Object> exception; | 764 Handle<Object> exception; |
| 765 MaybeHandle<Object> result = | 765 MaybeHandle<Object> result = |
| 766 Execution::TryCall(function, | 766 Execution::TryCall(function, |
| 767 handle(context->global_proxy()), | 767 handle(context->global_proxy()), |
| 768 0, | 768 0, |
| 769 NULL, | 769 NULL, |
| 770 &exception); | 770 &exception); |
| 771 | 771 |
| 772 // Check for caught exceptions. | 772 // Check for caught exceptions. |
| 773 if (result.is_null()) { | 773 if (result.is_null()) { |
| 774 ASSERT(!isolate->has_pending_exception()); | 774 DCHECK(!isolate->has_pending_exception()); |
| 775 MessageLocation computed_location; | 775 MessageLocation computed_location; |
| 776 isolate->ComputeLocation(&computed_location); | 776 isolate->ComputeLocation(&computed_location); |
| 777 Handle<Object> message = MessageHandler::MakeMessageObject( | 777 Handle<Object> message = MessageHandler::MakeMessageObject( |
| 778 isolate, "error_loading_debugger", &computed_location, | 778 isolate, "error_loading_debugger", &computed_location, |
| 779 Vector<Handle<Object> >::empty(), Handle<JSArray>()); | 779 Vector<Handle<Object> >::empty(), Handle<JSArray>()); |
| 780 ASSERT(!isolate->has_pending_exception()); | 780 DCHECK(!isolate->has_pending_exception()); |
| 781 if (!exception.is_null()) { | 781 if (!exception.is_null()) { |
| 782 isolate->set_pending_exception(*exception); | 782 isolate->set_pending_exception(*exception); |
| 783 MessageHandler::ReportMessage(isolate, NULL, message); | 783 MessageHandler::ReportMessage(isolate, NULL, message); |
| 784 isolate->clear_pending_exception(); | 784 isolate->clear_pending_exception(); |
| 785 } | 785 } |
| 786 return false; | 786 return false; |
| 787 } | 787 } |
| 788 | 788 |
| 789 // Mark this script as native and return successfully. | 789 // Mark this script as native and return successfully. |
| 790 Handle<Script> script(Script::cast(function->shared()->script())); | 790 Handle<Script> script(Script::cast(function->shared()->script())); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 869 | 869 |
| 870 // Clear debugger context global handle. | 870 // Clear debugger context global handle. |
| 871 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); | 871 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); |
| 872 debug_context_ = Handle<Context>(); | 872 debug_context_ = Handle<Context>(); |
| 873 } | 873 } |
| 874 | 874 |
| 875 | 875 |
| 876 void Debug::Break(Arguments args, JavaScriptFrame* frame) { | 876 void Debug::Break(Arguments args, JavaScriptFrame* frame) { |
| 877 Heap* heap = isolate_->heap(); | 877 Heap* heap = isolate_->heap(); |
| 878 HandleScope scope(isolate_); | 878 HandleScope scope(isolate_); |
| 879 ASSERT(args.length() == 0); | 879 DCHECK(args.length() == 0); |
| 880 | 880 |
| 881 // Initialize LiveEdit. | 881 // Initialize LiveEdit. |
| 882 LiveEdit::InitializeThreadLocal(this); | 882 LiveEdit::InitializeThreadLocal(this); |
| 883 | 883 |
| 884 // Just continue if breaks are disabled or debugger cannot be loaded. | 884 // Just continue if breaks are disabled or debugger cannot be loaded. |
| 885 if (break_disabled_) return; | 885 if (break_disabled_) return; |
| 886 | 886 |
| 887 // Enter the debugger. | 887 // Enter the debugger. |
| 888 DebugScope debug_scope(this); | 888 DebugScope debug_scope(this); |
| 889 if (debug_scope.failed()) return; | 889 if (debug_scope.failed()) return; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 919 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_); | 919 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_); |
| 920 break_points_hit = CheckBreakPoints(break_point_objects); | 920 break_points_hit = CheckBreakPoints(break_point_objects); |
| 921 } | 921 } |
| 922 | 922 |
| 923 // If step out is active skip everything until the frame where we need to step | 923 // If step out is active skip everything until the frame where we need to step |
| 924 // out to is reached, unless real breakpoint is hit. | 924 // out to is reached, unless real breakpoint is hit. |
| 925 if (StepOutActive() && | 925 if (StepOutActive() && |
| 926 frame->fp() != thread_local_.step_out_fp_ && | 926 frame->fp() != thread_local_.step_out_fp_ && |
| 927 break_points_hit->IsUndefined() ) { | 927 break_points_hit->IsUndefined() ) { |
| 928 // Step count should always be 0 for StepOut. | 928 // Step count should always be 0 for StepOut. |
| 929 ASSERT(thread_local_.step_count_ == 0); | 929 DCHECK(thread_local_.step_count_ == 0); |
| 930 } else if (!break_points_hit->IsUndefined() || | 930 } else if (!break_points_hit->IsUndefined() || |
| 931 (thread_local_.last_step_action_ != StepNone && | 931 (thread_local_.last_step_action_ != StepNone && |
| 932 thread_local_.step_count_ == 0)) { | 932 thread_local_.step_count_ == 0)) { |
| 933 // Notify debugger if a real break point is triggered or if performing | 933 // Notify debugger if a real break point is triggered or if performing |
| 934 // single stepping with no more steps to perform. Otherwise do another step. | 934 // single stepping with no more steps to perform. Otherwise do another step. |
| 935 | 935 |
| 936 // Clear all current stepping setup. | 936 // Clear all current stepping setup. |
| 937 ClearStepping(); | 937 ClearStepping(); |
| 938 | 938 |
| 939 if (thread_local_.queued_step_count_ > 0) { | 939 if (thread_local_.queued_step_count_ > 0) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 // Check the break point objects for whether one or more are actually | 998 // Check the break point objects for whether one or more are actually |
| 999 // triggered. This function returns a JSArray with the break point objects | 999 // triggered. This function returns a JSArray with the break point objects |
| 1000 // which is triggered. | 1000 // which is triggered. |
| 1001 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { | 1001 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { |
| 1002 Factory* factory = isolate_->factory(); | 1002 Factory* factory = isolate_->factory(); |
| 1003 | 1003 |
| 1004 // Count the number of break points hit. If there are multiple break points | 1004 // Count the number of break points hit. If there are multiple break points |
| 1005 // they are in a FixedArray. | 1005 // they are in a FixedArray. |
| 1006 Handle<FixedArray> break_points_hit; | 1006 Handle<FixedArray> break_points_hit; |
| 1007 int break_points_hit_count = 0; | 1007 int break_points_hit_count = 0; |
| 1008 ASSERT(!break_point_objects->IsUndefined()); | 1008 DCHECK(!break_point_objects->IsUndefined()); |
| 1009 if (break_point_objects->IsFixedArray()) { | 1009 if (break_point_objects->IsFixedArray()) { |
| 1010 Handle<FixedArray> array(FixedArray::cast(*break_point_objects)); | 1010 Handle<FixedArray> array(FixedArray::cast(*break_point_objects)); |
| 1011 break_points_hit = factory->NewFixedArray(array->length()); | 1011 break_points_hit = factory->NewFixedArray(array->length()); |
| 1012 for (int i = 0; i < array->length(); i++) { | 1012 for (int i = 0; i < array->length(); i++) { |
| 1013 Handle<Object> o(array->get(i), isolate_); | 1013 Handle<Object> o(array->get(i), isolate_); |
| 1014 if (CheckBreakPoint(o)) { | 1014 if (CheckBreakPoint(o)) { |
| 1015 break_points_hit->set(break_points_hit_count++, *o); | 1015 break_points_hit->set(break_points_hit_count++, *o); |
| 1016 } | 1016 } |
| 1017 } | 1017 } |
| 1018 } else { | 1018 } else { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 | 1070 |
| 1071 // Check whether the function has debug information. | 1071 // Check whether the function has debug information. |
| 1072 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) { | 1072 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) { |
| 1073 return !shared->debug_info()->IsUndefined(); | 1073 return !shared->debug_info()->IsUndefined(); |
| 1074 } | 1074 } |
| 1075 | 1075 |
| 1076 | 1076 |
| 1077 // Return the debug info for this function. EnsureDebugInfo must be called | 1077 // Return the debug info for this function. EnsureDebugInfo must be called |
| 1078 // prior to ensure the debug info has been generated for shared. | 1078 // prior to ensure the debug info has been generated for shared. |
| 1079 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) { | 1079 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) { |
| 1080 ASSERT(HasDebugInfo(shared)); | 1080 DCHECK(HasDebugInfo(shared)); |
| 1081 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info())); | 1081 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info())); |
| 1082 } | 1082 } |
| 1083 | 1083 |
| 1084 | 1084 |
| 1085 bool Debug::SetBreakPoint(Handle<JSFunction> function, | 1085 bool Debug::SetBreakPoint(Handle<JSFunction> function, |
| 1086 Handle<Object> break_point_object, | 1086 Handle<Object> break_point_object, |
| 1087 int* source_position) { | 1087 int* source_position) { |
| 1088 HandleScope scope(isolate_); | 1088 HandleScope scope(isolate_); |
| 1089 | 1089 |
| 1090 PrepareForBreakPoints(); | 1090 PrepareForBreakPoints(); |
| 1091 | 1091 |
| 1092 // Make sure the function is compiled and has set up the debug info. | 1092 // Make sure the function is compiled and has set up the debug info. |
| 1093 Handle<SharedFunctionInfo> shared(function->shared()); | 1093 Handle<SharedFunctionInfo> shared(function->shared()); |
| 1094 if (!EnsureDebugInfo(shared, function)) { | 1094 if (!EnsureDebugInfo(shared, function)) { |
| 1095 // Return if retrieving debug info failed. | 1095 // Return if retrieving debug info failed. |
| 1096 return true; | 1096 return true; |
| 1097 } | 1097 } |
| 1098 | 1098 |
| 1099 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 1099 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
| 1100 // Source positions starts with zero. | 1100 // Source positions starts with zero. |
| 1101 ASSERT(*source_position >= 0); | 1101 DCHECK(*source_position >= 0); |
| 1102 | 1102 |
| 1103 // Find the break point and change it. | 1103 // Find the break point and change it. |
| 1104 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); | 1104 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); |
| 1105 it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED); | 1105 it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED); |
| 1106 it.SetBreakPoint(break_point_object); | 1106 it.SetBreakPoint(break_point_object); |
| 1107 | 1107 |
| 1108 *source_position = it.position(); | 1108 *source_position = it.position(); |
| 1109 | 1109 |
| 1110 // At least one active break point now. | 1110 // At least one active break point now. |
| 1111 return debug_info->GetBreakPointCount() > 0; | 1111 return debug_info->GetBreakPointCount() > 0; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1135 // source position of the first function. | 1135 // source position of the first function. |
| 1136 int position; | 1136 int position; |
| 1137 if (shared->start_position() > *source_position) { | 1137 if (shared->start_position() > *source_position) { |
| 1138 position = 0; | 1138 position = 0; |
| 1139 } else { | 1139 } else { |
| 1140 position = *source_position - shared->start_position(); | 1140 position = *source_position - shared->start_position(); |
| 1141 } | 1141 } |
| 1142 | 1142 |
| 1143 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 1143 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
| 1144 // Source positions starts with zero. | 1144 // Source positions starts with zero. |
| 1145 ASSERT(position >= 0); | 1145 DCHECK(position >= 0); |
| 1146 | 1146 |
| 1147 // Find the break point and change it. | 1147 // Find the break point and change it. |
| 1148 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); | 1148 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); |
| 1149 it.FindBreakLocationFromPosition(position, alignment); | 1149 it.FindBreakLocationFromPosition(position, alignment); |
| 1150 it.SetBreakPoint(break_point_object); | 1150 it.SetBreakPoint(break_point_object); |
| 1151 | 1151 |
| 1152 *source_position = it.position() + shared->start_position(); | 1152 *source_position = it.position() + shared->start_position(); |
| 1153 | 1153 |
| 1154 // At least one active break point now. | 1154 // At least one active break point now. |
| 1155 ASSERT(debug_info->GetBreakPointCount() > 0); | 1155 DCHECK(debug_info->GetBreakPointCount() > 0); |
| 1156 return true; | 1156 return true; |
| 1157 } | 1157 } |
| 1158 | 1158 |
| 1159 | 1159 |
| 1160 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { | 1160 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { |
| 1161 HandleScope scope(isolate_); | 1161 HandleScope scope(isolate_); |
| 1162 | 1162 |
| 1163 DebugInfoListNode* node = debug_info_list_; | 1163 DebugInfoListNode* node = debug_info_list_; |
| 1164 while (node != NULL) { | 1164 while (node != NULL) { |
| 1165 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(), | 1165 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(), |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1332 } | 1332 } |
| 1333 | 1333 |
| 1334 | 1334 |
| 1335 void Debug::PrepareStep(StepAction step_action, | 1335 void Debug::PrepareStep(StepAction step_action, |
| 1336 int step_count, | 1336 int step_count, |
| 1337 StackFrame::Id frame_id) { | 1337 StackFrame::Id frame_id) { |
| 1338 HandleScope scope(isolate_); | 1338 HandleScope scope(isolate_); |
| 1339 | 1339 |
| 1340 PrepareForBreakPoints(); | 1340 PrepareForBreakPoints(); |
| 1341 | 1341 |
| 1342 ASSERT(in_debug_scope()); | 1342 DCHECK(in_debug_scope()); |
| 1343 | 1343 |
| 1344 // Remember this step action and count. | 1344 // Remember this step action and count. |
| 1345 thread_local_.last_step_action_ = step_action; | 1345 thread_local_.last_step_action_ = step_action; |
| 1346 if (step_action == StepOut) { | 1346 if (step_action == StepOut) { |
| 1347 // For step out target frame will be found on the stack so there is no need | 1347 // For step out target frame will be found on the stack so there is no need |
| 1348 // to set step counter for it. It's expected to always be 0 for StepOut. | 1348 // to set step counter for it. It's expected to always be 0 for StepOut. |
| 1349 thread_local_.step_count_ = 0; | 1349 thread_local_.step_count_ = 0; |
| 1350 } else { | 1350 } else { |
| 1351 thread_local_.step_count_ = step_count; | 1351 thread_local_.step_count_ = step_count; |
| 1352 } | 1352 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1440 } | 1440 } |
| 1441 | 1441 |
| 1442 // If this is the last break code target step out is the only possibility. | 1442 // If this is the last break code target step out is the only possibility. |
| 1443 if (it.IsExit() || step_action == StepOut) { | 1443 if (it.IsExit() || step_action == StepOut) { |
| 1444 if (step_action == StepOut) { | 1444 if (step_action == StepOut) { |
| 1445 // Skip step_count frames starting with the current one. | 1445 // Skip step_count frames starting with the current one. |
| 1446 while (step_count-- > 0 && !frames_it.done()) { | 1446 while (step_count-- > 0 && !frames_it.done()) { |
| 1447 frames_it.Advance(); | 1447 frames_it.Advance(); |
| 1448 } | 1448 } |
| 1449 } else { | 1449 } else { |
| 1450 ASSERT(it.IsExit()); | 1450 DCHECK(it.IsExit()); |
| 1451 frames_it.Advance(); | 1451 frames_it.Advance(); |
| 1452 } | 1452 } |
| 1453 // Skip builtin functions on the stack. | 1453 // Skip builtin functions on the stack. |
| 1454 while (!frames_it.done() && | 1454 while (!frames_it.done() && |
| 1455 frames_it.frame()->function()->IsFromNativeScript()) { | 1455 frames_it.frame()->function()->IsFromNativeScript()) { |
| 1456 frames_it.Advance(); | 1456 frames_it.Advance(); |
| 1457 } | 1457 } |
| 1458 // Step out: If there is a JavaScript caller frame, we need to | 1458 // Step out: If there is a JavaScript caller frame, we need to |
| 1459 // flood it with breakpoints. | 1459 // flood it with breakpoints. |
| 1460 if (!frames_it.done()) { | 1460 if (!frames_it.done()) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1490 | 1490 |
| 1491 // Find out number of arguments from the stub minor key. | 1491 // Find out number of arguments from the stub minor key. |
| 1492 uint32_t key = call_function_stub->stub_key(); | 1492 uint32_t key = call_function_stub->stub_key(); |
| 1493 // Argc in the stub is the number of arguments passed - not the | 1493 // Argc in the stub is the number of arguments passed - not the |
| 1494 // expected arguments of the called function. | 1494 // expected arguments of the called function. |
| 1495 int call_function_arg_count = is_call_ic | 1495 int call_function_arg_count = is_call_ic |
| 1496 ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key)) | 1496 ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key)) |
| 1497 : CallFunctionStub::ExtractArgcFromMinorKey( | 1497 : CallFunctionStub::ExtractArgcFromMinorKey( |
| 1498 CodeStub::MinorKeyFromKey(key)); | 1498 CodeStub::MinorKeyFromKey(key)); |
| 1499 | 1499 |
| 1500 ASSERT(is_call_ic || | 1500 DCHECK(is_call_ic || |
| 1501 CodeStub::GetMajorKey(*call_function_stub) == | 1501 CodeStub::GetMajorKey(*call_function_stub) == |
| 1502 CodeStub::MajorKeyFromKey(key)); | 1502 CodeStub::MajorKeyFromKey(key)); |
| 1503 | 1503 |
| 1504 // Find target function on the expression stack. | 1504 // Find target function on the expression stack. |
| 1505 // Expression stack looks like this (top to bottom): | 1505 // Expression stack looks like this (top to bottom): |
| 1506 // argN | 1506 // argN |
| 1507 // ... | 1507 // ... |
| 1508 // arg0 | 1508 // arg0 |
| 1509 // Receiver | 1509 // Receiver |
| 1510 // Function to call | 1510 // Function to call |
| 1511 int expressions_count = frame->ComputeExpressionsCount(); | 1511 int expressions_count = frame->ComputeExpressionsCount(); |
| 1512 ASSERT(expressions_count - 2 - call_function_arg_count >= 0); | 1512 DCHECK(expressions_count - 2 - call_function_arg_count >= 0); |
| 1513 Object* fun = frame->GetExpression( | 1513 Object* fun = frame->GetExpression( |
| 1514 expressions_count - 2 - call_function_arg_count); | 1514 expressions_count - 2 - call_function_arg_count); |
| 1515 | 1515 |
| 1516 // Flood the actual target of call/apply. | 1516 // Flood the actual target of call/apply. |
| 1517 if (fun->IsJSFunction()) { | 1517 if (fun->IsJSFunction()) { |
| 1518 Isolate* isolate = JSFunction::cast(fun)->GetIsolate(); | 1518 Isolate* isolate = JSFunction::cast(fun)->GetIsolate(); |
| 1519 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply); | 1519 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply); |
| 1520 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall); | 1520 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall); |
| 1521 while (fun->IsJSFunction()) { | 1521 while (fun->IsJSFunction()) { |
| 1522 Code* code = JSFunction::cast(fun)->shared()->code(); | 1522 Code* code = JSFunction::cast(fun)->shared()->code(); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1653 Handle<Object> holder, | 1653 Handle<Object> holder, |
| 1654 Address fp, | 1654 Address fp, |
| 1655 bool is_constructor) { | 1655 bool is_constructor) { |
| 1656 Isolate* isolate = function->GetIsolate(); | 1656 Isolate* isolate = function->GetIsolate(); |
| 1657 // If the frame pointer is not supplied by the caller find it. | 1657 // If the frame pointer is not supplied by the caller find it. |
| 1658 if (fp == 0) { | 1658 if (fp == 0) { |
| 1659 StackFrameIterator it(isolate); | 1659 StackFrameIterator it(isolate); |
| 1660 it.Advance(); | 1660 it.Advance(); |
| 1661 // For constructor functions skip another frame. | 1661 // For constructor functions skip another frame. |
| 1662 if (is_constructor) { | 1662 if (is_constructor) { |
| 1663 ASSERT(it.frame()->is_construct()); | 1663 DCHECK(it.frame()->is_construct()); |
| 1664 it.Advance(); | 1664 it.Advance(); |
| 1665 } | 1665 } |
| 1666 fp = it.frame()->fp(); | 1666 fp = it.frame()->fp(); |
| 1667 } | 1667 } |
| 1668 | 1668 |
| 1669 // Flood the function with one-shot break points if it is called from where | 1669 // Flood the function with one-shot break points if it is called from where |
| 1670 // step into was requested. | 1670 // step into was requested. |
| 1671 if (fp == thread_local_.step_into_fp_) { | 1671 if (fp == thread_local_.step_into_fp_) { |
| 1672 if (function->shared()->bound()) { | 1672 if (function->shared()->bound()) { |
| 1673 // Handle Function.prototype.bind | 1673 // Handle Function.prototype.bind |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1725 while (!it.Done()) { | 1725 while (!it.Done()) { |
| 1726 it.ClearOneShot(); | 1726 it.ClearOneShot(); |
| 1727 it.Next(); | 1727 it.Next(); |
| 1728 } | 1728 } |
| 1729 node = node->next(); | 1729 node = node->next(); |
| 1730 } | 1730 } |
| 1731 } | 1731 } |
| 1732 | 1732 |
| 1733 | 1733 |
| 1734 void Debug::ActivateStepIn(StackFrame* frame) { | 1734 void Debug::ActivateStepIn(StackFrame* frame) { |
| 1735 ASSERT(!StepOutActive()); | 1735 DCHECK(!StepOutActive()); |
| 1736 thread_local_.step_into_fp_ = frame->UnpaddedFP(); | 1736 thread_local_.step_into_fp_ = frame->UnpaddedFP(); |
| 1737 } | 1737 } |
| 1738 | 1738 |
| 1739 | 1739 |
| 1740 void Debug::ClearStepIn() { | 1740 void Debug::ClearStepIn() { |
| 1741 thread_local_.step_into_fp_ = 0; | 1741 thread_local_.step_into_fp_ = 0; |
| 1742 } | 1742 } |
| 1743 | 1743 |
| 1744 | 1744 |
| 1745 void Debug::ActivateStepOut(StackFrame* frame) { | 1745 void Debug::ActivateStepOut(StackFrame* frame) { |
| 1746 ASSERT(!StepInActive()); | 1746 DCHECK(!StepInActive()); |
| 1747 thread_local_.step_out_fp_ = frame->UnpaddedFP(); | 1747 thread_local_.step_out_fp_ = frame->UnpaddedFP(); |
| 1748 } | 1748 } |
| 1749 | 1749 |
| 1750 | 1750 |
| 1751 void Debug::ClearStepOut() { | 1751 void Debug::ClearStepOut() { |
| 1752 thread_local_.step_out_fp_ = 0; | 1752 thread_local_.step_out_fp_ = 0; |
| 1753 } | 1753 } |
| 1754 | 1754 |
| 1755 | 1755 |
| 1756 void Debug::ClearStepNext() { | 1756 void Debug::ClearStepNext() { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1774 if (frame->is_optimized()) { | 1774 if (frame->is_optimized()) { |
| 1775 List<JSFunction*> functions(FLAG_max_inlining_levels + 1); | 1775 List<JSFunction*> functions(FLAG_max_inlining_levels + 1); |
| 1776 frame->GetFunctions(&functions); | 1776 frame->GetFunctions(&functions); |
| 1777 for (int i = 0; i < functions.length(); i++) { | 1777 for (int i = 0; i < functions.length(); i++) { |
| 1778 JSFunction* function = functions[i]; | 1778 JSFunction* function = functions[i]; |
| 1779 active_functions->Add(Handle<JSFunction>(function)); | 1779 active_functions->Add(Handle<JSFunction>(function)); |
| 1780 function->shared()->code()->set_gc_metadata(active_code_marker); | 1780 function->shared()->code()->set_gc_metadata(active_code_marker); |
| 1781 } | 1781 } |
| 1782 } else if (frame->function()->IsJSFunction()) { | 1782 } else if (frame->function()->IsJSFunction()) { |
| 1783 JSFunction* function = frame->function(); | 1783 JSFunction* function = frame->function(); |
| 1784 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION); | 1784 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); |
| 1785 active_functions->Add(Handle<JSFunction>(function)); | 1785 active_functions->Add(Handle<JSFunction>(function)); |
| 1786 function->shared()->code()->set_gc_metadata(active_code_marker); | 1786 function->shared()->code()->set_gc_metadata(active_code_marker); |
| 1787 } | 1787 } |
| 1788 } | 1788 } |
| 1789 } | 1789 } |
| 1790 | 1790 |
| 1791 | 1791 |
| 1792 // Figure out how many bytes of "pc_offset" correspond to actual code by | 1792 // Figure out how many bytes of "pc_offset" correspond to actual code by |
| 1793 // subtracting off the bytes that correspond to constant/veneer pools. See | 1793 // subtracting off the bytes that correspond to constant/veneer pools. See |
| 1794 // Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this | 1794 // Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this |
| 1795 // is only useful for architectures using constant pools or veneer pools. | 1795 // is only useful for architectures using constant pools or veneer pools. |
| 1796 static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) { | 1796 static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) { |
| 1797 ASSERT_EQ(code->kind(), Code::FUNCTION); | 1797 DCHECK_EQ(code->kind(), Code::FUNCTION); |
| 1798 ASSERT(!code->has_debug_break_slots()); | 1798 DCHECK(!code->has_debug_break_slots()); |
| 1799 ASSERT_LE(0, pc_offset); | 1799 DCHECK_LE(0, pc_offset); |
| 1800 ASSERT_LT(pc_offset, code->instruction_end() - code->instruction_start()); | 1800 DCHECK_LT(pc_offset, code->instruction_end() - code->instruction_start()); |
| 1801 | 1801 |
| 1802 int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) | | 1802 int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) | |
| 1803 RelocInfo::ModeMask(RelocInfo::VENEER_POOL); | 1803 RelocInfo::ModeMask(RelocInfo::VENEER_POOL); |
| 1804 byte *pc = code->instruction_start() + pc_offset; | 1804 byte *pc = code->instruction_start() + pc_offset; |
| 1805 int code_offset = pc_offset; | 1805 int code_offset = pc_offset; |
| 1806 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 1806 for (RelocIterator it(code, mask); !it.done(); it.next()) { |
| 1807 RelocInfo* info = it.rinfo(); | 1807 RelocInfo* info = it.rinfo(); |
| 1808 if (info->pc() >= pc) break; | 1808 if (info->pc() >= pc) break; |
| 1809 ASSERT(RelocInfo::IsConstPool(info->rmode())); | 1809 DCHECK(RelocInfo::IsConstPool(info->rmode())); |
| 1810 code_offset -= static_cast<int>(info->data()); | 1810 code_offset -= static_cast<int>(info->data()); |
| 1811 ASSERT_LE(0, code_offset); | 1811 DCHECK_LE(0, code_offset); |
| 1812 } | 1812 } |
| 1813 | 1813 |
| 1814 return code_offset; | 1814 return code_offset; |
| 1815 } | 1815 } |
| 1816 | 1816 |
| 1817 | 1817 |
| 1818 // The inverse of ComputeCodeOffsetFromPcOffset. | 1818 // The inverse of ComputeCodeOffsetFromPcOffset. |
| 1819 static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) { | 1819 static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) { |
| 1820 ASSERT_EQ(code->kind(), Code::FUNCTION); | 1820 DCHECK_EQ(code->kind(), Code::FUNCTION); |
| 1821 | 1821 |
| 1822 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | | 1822 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | |
| 1823 RelocInfo::ModeMask(RelocInfo::CONST_POOL) | | 1823 RelocInfo::ModeMask(RelocInfo::CONST_POOL) | |
| 1824 RelocInfo::ModeMask(RelocInfo::VENEER_POOL); | 1824 RelocInfo::ModeMask(RelocInfo::VENEER_POOL); |
| 1825 int reloc = 0; | 1825 int reloc = 0; |
| 1826 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 1826 for (RelocIterator it(code, mask); !it.done(); it.next()) { |
| 1827 RelocInfo* info = it.rinfo(); | 1827 RelocInfo* info = it.rinfo(); |
| 1828 if (info->pc() - code->instruction_start() - reloc >= code_offset) break; | 1828 if (info->pc() - code->instruction_start() - reloc >= code_offset) break; |
| 1829 if (RelocInfo::IsDebugBreakSlot(info->rmode())) { | 1829 if (RelocInfo::IsDebugBreakSlot(info->rmode())) { |
| 1830 reloc += Assembler::kDebugBreakSlotLength; | 1830 reloc += Assembler::kDebugBreakSlotLength; |
| 1831 } else { | 1831 } else { |
| 1832 ASSERT(RelocInfo::IsConstPool(info->rmode())); | 1832 DCHECK(RelocInfo::IsConstPool(info->rmode())); |
| 1833 reloc += static_cast<int>(info->data()); | 1833 reloc += static_cast<int>(info->data()); |
| 1834 } | 1834 } |
| 1835 } | 1835 } |
| 1836 | 1836 |
| 1837 int pc_offset = code_offset + reloc; | 1837 int pc_offset = code_offset + reloc; |
| 1838 | 1838 |
| 1839 ASSERT_LT(code->instruction_start() + pc_offset, code->instruction_end()); | 1839 DCHECK_LT(code->instruction_start() + pc_offset, code->instruction_end()); |
| 1840 | 1840 |
| 1841 return pc_offset; | 1841 return pc_offset; |
| 1842 } | 1842 } |
| 1843 | 1843 |
| 1844 | 1844 |
| 1845 static void RedirectActivationsToRecompiledCodeOnThread( | 1845 static void RedirectActivationsToRecompiledCodeOnThread( |
| 1846 Isolate* isolate, | 1846 Isolate* isolate, |
| 1847 ThreadLocalTop* top) { | 1847 ThreadLocalTop* top) { |
| 1848 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { | 1848 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { |
| 1849 JavaScriptFrame* frame = it.frame(); | 1849 JavaScriptFrame* frame = it.frame(); |
| 1850 | 1850 |
| 1851 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue; | 1851 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue; |
| 1852 | 1852 |
| 1853 JSFunction* function = frame->function(); | 1853 JSFunction* function = frame->function(); |
| 1854 | 1854 |
| 1855 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION); | 1855 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); |
| 1856 | 1856 |
| 1857 Handle<Code> frame_code(frame->LookupCode()); | 1857 Handle<Code> frame_code(frame->LookupCode()); |
| 1858 if (frame_code->has_debug_break_slots()) continue; | 1858 if (frame_code->has_debug_break_slots()) continue; |
| 1859 | 1859 |
| 1860 Handle<Code> new_code(function->shared()->code()); | 1860 Handle<Code> new_code(function->shared()->code()); |
| 1861 if (new_code->kind() != Code::FUNCTION || | 1861 if (new_code->kind() != Code::FUNCTION || |
| 1862 !new_code->has_debug_break_slots()) { | 1862 !new_code->has_debug_break_slots()) { |
| 1863 continue; | 1863 continue; |
| 1864 } | 1864 } |
| 1865 | 1865 |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2056 } else { | 2056 } else { |
| 2057 function->ReplaceCode(*lazy_compile); | 2057 function->ReplaceCode(*lazy_compile); |
| 2058 function->shared()->ReplaceCode(*lazy_compile); | 2058 function->shared()->ReplaceCode(*lazy_compile); |
| 2059 } | 2059 } |
| 2060 } | 2060 } |
| 2061 } else if (obj->IsJSGeneratorObject()) { | 2061 } else if (obj->IsJSGeneratorObject()) { |
| 2062 JSGeneratorObject* gen = JSGeneratorObject::cast(obj); | 2062 JSGeneratorObject* gen = JSGeneratorObject::cast(obj); |
| 2063 if (!gen->is_suspended()) continue; | 2063 if (!gen->is_suspended()) continue; |
| 2064 | 2064 |
| 2065 JSFunction* fun = gen->function(); | 2065 JSFunction* fun = gen->function(); |
| 2066 ASSERT_EQ(fun->code()->kind(), Code::FUNCTION); | 2066 DCHECK_EQ(fun->code()->kind(), Code::FUNCTION); |
| 2067 if (fun->code()->has_debug_break_slots()) continue; | 2067 if (fun->code()->has_debug_break_slots()) continue; |
| 2068 | 2068 |
| 2069 int pc_offset = gen->continuation(); | 2069 int pc_offset = gen->continuation(); |
| 2070 ASSERT_LT(0, pc_offset); | 2070 DCHECK_LT(0, pc_offset); |
| 2071 | 2071 |
| 2072 int code_offset = | 2072 int code_offset = |
| 2073 ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset); | 2073 ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset); |
| 2074 | 2074 |
| 2075 // This will be fixed after we recompile the functions. | 2075 // This will be fixed after we recompile the functions. |
| 2076 gen->set_continuation(code_offset); | 2076 gen->set_continuation(code_offset); |
| 2077 | 2077 |
| 2078 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_)); | 2078 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_)); |
| 2079 } | 2079 } |
| 2080 } | 2080 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2150 { // Extra scope for iterator. | 2150 { // Extra scope for iterator. |
| 2151 HeapIterator iterator(heap); | 2151 HeapIterator iterator(heap); |
| 2152 for (HeapObject* obj = iterator.next(); | 2152 for (HeapObject* obj = iterator.next(); |
| 2153 obj != NULL; obj = iterator.next()) { | 2153 obj != NULL; obj = iterator.next()) { |
| 2154 bool found_next_candidate = false; | 2154 bool found_next_candidate = false; |
| 2155 Handle<JSFunction> function; | 2155 Handle<JSFunction> function; |
| 2156 Handle<SharedFunctionInfo> shared; | 2156 Handle<SharedFunctionInfo> shared; |
| 2157 if (obj->IsJSFunction()) { | 2157 if (obj->IsJSFunction()) { |
| 2158 function = Handle<JSFunction>(JSFunction::cast(obj)); | 2158 function = Handle<JSFunction>(JSFunction::cast(obj)); |
| 2159 shared = Handle<SharedFunctionInfo>(function->shared()); | 2159 shared = Handle<SharedFunctionInfo>(function->shared()); |
| 2160 ASSERT(shared->allows_lazy_compilation() || shared->is_compiled()); | 2160 DCHECK(shared->allows_lazy_compilation() || shared->is_compiled()); |
| 2161 found_next_candidate = true; | 2161 found_next_candidate = true; |
| 2162 } else if (obj->IsSharedFunctionInfo()) { | 2162 } else if (obj->IsSharedFunctionInfo()) { |
| 2163 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj)); | 2163 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj)); |
| 2164 // Skip functions that we cannot compile lazily without a context, | 2164 // Skip functions that we cannot compile lazily without a context, |
| 2165 // which is not available here, because there is no closure. | 2165 // which is not available here, because there is no closure. |
| 2166 found_next_candidate = shared->is_compiled() || | 2166 found_next_candidate = shared->is_compiled() || |
| 2167 shared->allows_lazy_compilation_without_context(); | 2167 shared->allows_lazy_compilation_without_context(); |
| 2168 } | 2168 } |
| 2169 if (!found_next_candidate) continue; | 2169 if (!found_next_candidate) continue; |
| 2170 if (shared->script() == *script) { | 2170 if (shared->script() == *script) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2232 } | 2232 } |
| 2233 | 2233 |
| 2234 | 2234 |
| 2235 // Ensures the debug information is present for shared. | 2235 // Ensures the debug information is present for shared. |
| 2236 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, | 2236 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, |
| 2237 Handle<JSFunction> function) { | 2237 Handle<JSFunction> function) { |
| 2238 Isolate* isolate = shared->GetIsolate(); | 2238 Isolate* isolate = shared->GetIsolate(); |
| 2239 | 2239 |
| 2240 // Return if we already have the debug info for shared. | 2240 // Return if we already have the debug info for shared. |
| 2241 if (HasDebugInfo(shared)) { | 2241 if (HasDebugInfo(shared)) { |
| 2242 ASSERT(shared->is_compiled()); | 2242 DCHECK(shared->is_compiled()); |
| 2243 return true; | 2243 return true; |
| 2244 } | 2244 } |
| 2245 | 2245 |
| 2246 // There will be at least one break point when we are done. | 2246 // There will be at least one break point when we are done. |
| 2247 has_break_points_ = true; | 2247 has_break_points_ = true; |
| 2248 | 2248 |
| 2249 // Ensure function is compiled. Return false if this failed. | 2249 // Ensure function is compiled. Return false if this failed. |
| 2250 if (!function.is_null() && | 2250 if (!function.is_null() && |
| 2251 !Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) { | 2251 !Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) { |
| 2252 return false; | 2252 return false; |
| 2253 } | 2253 } |
| 2254 | 2254 |
| 2255 // Create the debug info object. | 2255 // Create the debug info object. |
| 2256 Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared); | 2256 Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared); |
| 2257 | 2257 |
| 2258 // Add debug info to the list. | 2258 // Add debug info to the list. |
| 2259 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); | 2259 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); |
| 2260 node->set_next(debug_info_list_); | 2260 node->set_next(debug_info_list_); |
| 2261 debug_info_list_ = node; | 2261 debug_info_list_ = node; |
| 2262 | 2262 |
| 2263 return true; | 2263 return true; |
| 2264 } | 2264 } |
| 2265 | 2265 |
| 2266 | 2266 |
| 2267 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) { | 2267 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) { |
| 2268 ASSERT(debug_info_list_ != NULL); | 2268 DCHECK(debug_info_list_ != NULL); |
| 2269 // Run through the debug info objects to find this one and remove it. | 2269 // Run through the debug info objects to find this one and remove it. |
| 2270 DebugInfoListNode* prev = NULL; | 2270 DebugInfoListNode* prev = NULL; |
| 2271 DebugInfoListNode* current = debug_info_list_; | 2271 DebugInfoListNode* current = debug_info_list_; |
| 2272 while (current != NULL) { | 2272 while (current != NULL) { |
| 2273 if (*current->debug_info() == *debug_info) { | 2273 if (*current->debug_info() == *debug_info) { |
| 2274 // Unlink from list. If prev is NULL we are looking at the first element. | 2274 // Unlink from list. If prev is NULL we are looking at the first element. |
| 2275 if (prev == NULL) { | 2275 if (prev == NULL) { |
| 2276 debug_info_list_ = current->next(); | 2276 debug_info_list_ = current->next(); |
| 2277 } else { | 2277 } else { |
| 2278 prev->set_next(current->next()); | 2278 prev->set_next(current->next()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2309 if (!EnsureDebugInfo(shared, function)) { | 2309 if (!EnsureDebugInfo(shared, function)) { |
| 2310 // Return if we failed to retrieve the debug info. | 2310 // Return if we failed to retrieve the debug info. |
| 2311 return; | 2311 return; |
| 2312 } | 2312 } |
| 2313 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 2313 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
| 2314 Handle<Code> code(debug_info->code()); | 2314 Handle<Code> code(debug_info->code()); |
| 2315 Handle<Code> original_code(debug_info->original_code()); | 2315 Handle<Code> original_code(debug_info->original_code()); |
| 2316 #ifdef DEBUG | 2316 #ifdef DEBUG |
| 2317 // Get the code which is actually executing. | 2317 // Get the code which is actually executing. |
| 2318 Handle<Code> frame_code(frame->LookupCode()); | 2318 Handle<Code> frame_code(frame->LookupCode()); |
| 2319 ASSERT(frame_code.is_identical_to(code)); | 2319 DCHECK(frame_code.is_identical_to(code)); |
| 2320 #endif | 2320 #endif |
| 2321 | 2321 |
| 2322 // Find the call address in the running code. This address holds the call to | 2322 // Find the call address in the running code. This address holds the call to |
| 2323 // either a DebugBreakXXX or to the debug break return entry code if the | 2323 // either a DebugBreakXXX or to the debug break return entry code if the |
| 2324 // break point is still active after processing the break point. | 2324 // break point is still active after processing the break point. |
| 2325 Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset; | 2325 Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset; |
| 2326 | 2326 |
| 2327 // Check if the location is at JS exit or debug break slot. | 2327 // Check if the location is at JS exit or debug break slot. |
| 2328 bool at_js_return = false; | 2328 bool at_js_return = false; |
| 2329 bool break_at_js_return_active = false; | 2329 bool break_at_js_return_active = false; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2402 Handle<SharedFunctionInfo> shared(function->shared()); | 2402 Handle<SharedFunctionInfo> shared(function->shared()); |
| 2403 if (!EnsureDebugInfo(shared, function)) { | 2403 if (!EnsureDebugInfo(shared, function)) { |
| 2404 // Return if we failed to retrieve the debug info. | 2404 // Return if we failed to retrieve the debug info. |
| 2405 return false; | 2405 return false; |
| 2406 } | 2406 } |
| 2407 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 2407 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
| 2408 Handle<Code> code(debug_info->code()); | 2408 Handle<Code> code(debug_info->code()); |
| 2409 #ifdef DEBUG | 2409 #ifdef DEBUG |
| 2410 // Get the code which is actually executing. | 2410 // Get the code which is actually executing. |
| 2411 Handle<Code> frame_code(frame->LookupCode()); | 2411 Handle<Code> frame_code(frame->LookupCode()); |
| 2412 ASSERT(frame_code.is_identical_to(code)); | 2412 DCHECK(frame_code.is_identical_to(code)); |
| 2413 #endif | 2413 #endif |
| 2414 | 2414 |
| 2415 // Find the call address in the running code. | 2415 // Find the call address in the running code. |
| 2416 Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset; | 2416 Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset; |
| 2417 | 2417 |
| 2418 // Check if the location is at JS return. | 2418 // Check if the location is at JS return. |
| 2419 RelocIterator it(debug_info->code()); | 2419 RelocIterator it(debug_info->code()); |
| 2420 while (!it.done()) { | 2420 while (!it.done()) { |
| 2421 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) { | 2421 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) { |
| 2422 return (it.rinfo()->pc() == | 2422 return (it.rinfo()->pc() == |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2493 | 2493 |
| 2494 | 2494 |
| 2495 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name, | 2495 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name, |
| 2496 int argc, | 2496 int argc, |
| 2497 Handle<Object> argv[]) { | 2497 Handle<Object> argv[]) { |
| 2498 AssertDebugContext(); | 2498 AssertDebugContext(); |
| 2499 // Create the execution state object. | 2499 // Create the execution state object. |
| 2500 Handle<GlobalObject> global(isolate_->global_object()); | 2500 Handle<GlobalObject> global(isolate_->global_object()); |
| 2501 Handle<Object> constructor = Object::GetProperty( | 2501 Handle<Object> constructor = Object::GetProperty( |
| 2502 isolate_, global, constructor_name).ToHandleChecked(); | 2502 isolate_, global, constructor_name).ToHandleChecked(); |
| 2503 ASSERT(constructor->IsJSFunction()); | 2503 DCHECK(constructor->IsJSFunction()); |
| 2504 if (!constructor->IsJSFunction()) return MaybeHandle<Object>(); | 2504 if (!constructor->IsJSFunction()) return MaybeHandle<Object>(); |
| 2505 // We do not handle interrupts here. In particular, termination interrupts. | 2505 // We do not handle interrupts here. In particular, termination interrupts. |
| 2506 PostponeInterruptsScope no_interrupts(isolate_); | 2506 PostponeInterruptsScope no_interrupts(isolate_); |
| 2507 return Execution::TryCall(Handle<JSFunction>::cast(constructor), | 2507 return Execution::TryCall(Handle<JSFunction>::cast(constructor), |
| 2508 handle(debug_context()->global_proxy()), | 2508 handle(debug_context()->global_proxy()), |
| 2509 argc, | 2509 argc, |
| 2510 argv); | 2510 argv); |
| 2511 } | 2511 } |
| 2512 | 2512 |
| 2513 | 2513 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2675 Handle<String> update_script_break_points_string = | 2675 Handle<String> update_script_break_points_string = |
| 2676 isolate_->factory()->InternalizeOneByteString( | 2676 isolate_->factory()->InternalizeOneByteString( |
| 2677 STATIC_ASCII_VECTOR("UpdateScriptBreakPoints")); | 2677 STATIC_ASCII_VECTOR("UpdateScriptBreakPoints")); |
| 2678 Handle<GlobalObject> debug_global(debug_context()->global_object()); | 2678 Handle<GlobalObject> debug_global(debug_context()->global_object()); |
| 2679 Handle<Object> update_script_break_points = | 2679 Handle<Object> update_script_break_points = |
| 2680 Object::GetProperty( | 2680 Object::GetProperty( |
| 2681 debug_global, update_script_break_points_string).ToHandleChecked(); | 2681 debug_global, update_script_break_points_string).ToHandleChecked(); |
| 2682 if (!update_script_break_points->IsJSFunction()) { | 2682 if (!update_script_break_points->IsJSFunction()) { |
| 2683 return; | 2683 return; |
| 2684 } | 2684 } |
| 2685 ASSERT(update_script_break_points->IsJSFunction()); | 2685 DCHECK(update_script_break_points->IsJSFunction()); |
| 2686 | 2686 |
| 2687 // Wrap the script object in a proper JS object before passing it | 2687 // Wrap the script object in a proper JS object before passing it |
| 2688 // to JavaScript. | 2688 // to JavaScript. |
| 2689 Handle<Object> wrapper = Script::GetWrapper(script); | 2689 Handle<Object> wrapper = Script::GetWrapper(script); |
| 2690 | 2690 |
| 2691 // Call UpdateScriptBreakPoints expect no exceptions. | 2691 // Call UpdateScriptBreakPoints expect no exceptions. |
| 2692 Handle<Object> argv[] = { wrapper }; | 2692 Handle<Object> argv[] = { wrapper }; |
| 2693 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points), | 2693 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points), |
| 2694 isolate_->js_builtins_object(), | 2694 isolate_->js_builtins_object(), |
| 2695 ARRAY_SIZE(argv), | 2695 ARRAY_SIZE(argv), |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2792 // Invoke the C debug event listener. | 2792 // Invoke the C debug event listener. |
| 2793 v8::Debug::EventCallback callback = | 2793 v8::Debug::EventCallback callback = |
| 2794 FUNCTION_CAST<v8::Debug::EventCallback>( | 2794 FUNCTION_CAST<v8::Debug::EventCallback>( |
| 2795 Handle<Foreign>::cast(event_listener_)->foreign_address()); | 2795 Handle<Foreign>::cast(event_listener_)->foreign_address()); |
| 2796 EventDetailsImpl event_details(event, | 2796 EventDetailsImpl event_details(event, |
| 2797 Handle<JSObject>::cast(exec_state), | 2797 Handle<JSObject>::cast(exec_state), |
| 2798 Handle<JSObject>::cast(event_data), | 2798 Handle<JSObject>::cast(event_data), |
| 2799 event_listener_data_, | 2799 event_listener_data_, |
| 2800 client_data); | 2800 client_data); |
| 2801 callback(event_details); | 2801 callback(event_details); |
| 2802 ASSERT(!isolate_->has_scheduled_exception()); | 2802 DCHECK(!isolate_->has_scheduled_exception()); |
| 2803 } else { | 2803 } else { |
| 2804 // Invoke the JavaScript debug event listener. | 2804 // Invoke the JavaScript debug event listener. |
| 2805 ASSERT(event_listener_->IsJSFunction()); | 2805 DCHECK(event_listener_->IsJSFunction()); |
| 2806 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), | 2806 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), |
| 2807 exec_state, | 2807 exec_state, |
| 2808 event_data, | 2808 event_data, |
| 2809 event_listener_data_ }; | 2809 event_listener_data_ }; |
| 2810 Handle<JSReceiver> global(isolate_->global_proxy()); | 2810 Handle<JSReceiver> global(isolate_->global_proxy()); |
| 2811 Execution::TryCall(Handle<JSFunction>::cast(event_listener_), | 2811 Execution::TryCall(Handle<JSFunction>::cast(event_listener_), |
| 2812 global, ARRAY_SIZE(argv), argv); | 2812 global, ARRAY_SIZE(argv), argv); |
| 2813 } | 2813 } |
| 2814 } | 2814 } |
| 2815 | 2815 |
| 2816 | 2816 |
| 2817 Handle<Context> Debug::GetDebugContext() { | 2817 Handle<Context> Debug::GetDebugContext() { |
| 2818 DebugScope debug_scope(this); | 2818 DebugScope debug_scope(this); |
| 2819 // The global handle may be destroyed soon after. Return it reboxed. | 2819 // The global handle may be destroyed soon after. Return it reboxed. |
| 2820 return handle(*debug_context(), isolate_); | 2820 return handle(*debug_context(), isolate_); |
| 2821 } | 2821 } |
| 2822 | 2822 |
| 2823 | 2823 |
| 2824 void Debug::NotifyMessageHandler(v8::DebugEvent event, | 2824 void Debug::NotifyMessageHandler(v8::DebugEvent event, |
| 2825 Handle<JSObject> exec_state, | 2825 Handle<JSObject> exec_state, |
| 2826 Handle<JSObject> event_data, | 2826 Handle<JSObject> event_data, |
| 2827 bool auto_continue) { | 2827 bool auto_continue) { |
| 2828 // Prevent other interrupts from triggering, for example API callbacks, | 2828 // Prevent other interrupts from triggering, for example API callbacks, |
| 2829 // while dispatching message handler callbacks. | 2829 // while dispatching message handler callbacks. |
| 2830 PostponeInterruptsScope no_interrupts(isolate_); | 2830 PostponeInterruptsScope no_interrupts(isolate_); |
| 2831 ASSERT(is_active_); | 2831 DCHECK(is_active_); |
| 2832 HandleScope scope(isolate_); | 2832 HandleScope scope(isolate_); |
| 2833 // Process the individual events. | 2833 // Process the individual events. |
| 2834 bool sendEventMessage = false; | 2834 bool sendEventMessage = false; |
| 2835 switch (event) { | 2835 switch (event) { |
| 2836 case v8::Break: | 2836 case v8::Break: |
| 2837 case v8::BreakForCommand: | 2837 case v8::BreakForCommand: |
| 2838 sendEventMessage = !auto_continue; | 2838 sendEventMessage = !auto_continue; |
| 2839 break; | 2839 break; |
| 2840 case v8::Exception: | 2840 case v8::Exception: |
| 2841 sendEventMessage = true; | 2841 sendEventMessage = true; |
| 2842 break; | 2842 break; |
| 2843 case v8::BeforeCompile: | 2843 case v8::BeforeCompile: |
| 2844 break; | 2844 break; |
| 2845 case v8::AfterCompile: | 2845 case v8::AfterCompile: |
| 2846 sendEventMessage = true; | 2846 sendEventMessage = true; |
| 2847 break; | 2847 break; |
| 2848 case v8::NewFunction: | 2848 case v8::NewFunction: |
| 2849 break; | 2849 break; |
| 2850 default: | 2850 default: |
| 2851 UNREACHABLE(); | 2851 UNREACHABLE(); |
| 2852 } | 2852 } |
| 2853 | 2853 |
| 2854 // The debug command interrupt flag might have been set when the command was | 2854 // The debug command interrupt flag might have been set when the command was |
| 2855 // added. It should be enough to clear the flag only once while we are in the | 2855 // added. It should be enough to clear the flag only once while we are in the |
| 2856 // debugger. | 2856 // debugger. |
| 2857 ASSERT(in_debug_scope()); | 2857 DCHECK(in_debug_scope()); |
| 2858 isolate_->stack_guard()->ClearDebugCommand(); | 2858 isolate_->stack_guard()->ClearDebugCommand(); |
| 2859 | 2859 |
| 2860 // Notify the debugger that a debug event has occurred unless auto continue is | 2860 // Notify the debugger that a debug event has occurred unless auto continue is |
| 2861 // active in which case no event is send. | 2861 // active in which case no event is send. |
| 2862 if (sendEventMessage) { | 2862 if (sendEventMessage) { |
| 2863 MessageImpl message = MessageImpl::NewEvent( | 2863 MessageImpl message = MessageImpl::NewEvent( |
| 2864 event, | 2864 event, |
| 2865 auto_continue, | 2865 auto_continue, |
| 2866 Handle<JSObject>::cast(exec_state), | 2866 Handle<JSObject>::cast(exec_state), |
| 2867 Handle<JSObject>::cast(event_data)); | 2867 Handle<JSObject>::cast(event_data)); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3058 if (isolate_->bootstrapper()->IsActive()) return; | 3058 if (isolate_->bootstrapper()->IsActive()) return; |
| 3059 // Just continue if breaks are disabled. | 3059 // Just continue if breaks are disabled. |
| 3060 if (break_disabled_) return; | 3060 if (break_disabled_) return; |
| 3061 // Ignore debug break if debugger is not active. | 3061 // Ignore debug break if debugger is not active. |
| 3062 if (!is_active()) return; | 3062 if (!is_active()) return; |
| 3063 | 3063 |
| 3064 StackLimitCheck check(isolate_); | 3064 StackLimitCheck check(isolate_); |
| 3065 if (check.HasOverflowed()) return; | 3065 if (check.HasOverflowed()) return; |
| 3066 | 3066 |
| 3067 { JavaScriptFrameIterator it(isolate_); | 3067 { JavaScriptFrameIterator it(isolate_); |
| 3068 ASSERT(!it.done()); | 3068 DCHECK(!it.done()); |
| 3069 Object* fun = it.frame()->function(); | 3069 Object* fun = it.frame()->function(); |
| 3070 if (fun && fun->IsJSFunction()) { | 3070 if (fun && fun->IsJSFunction()) { |
| 3071 // Don't stop in builtin functions. | 3071 // Don't stop in builtin functions. |
| 3072 if (JSFunction::cast(fun)->IsBuiltin()) return; | 3072 if (JSFunction::cast(fun)->IsBuiltin()) return; |
| 3073 GlobalObject* global = JSFunction::cast(fun)->context()->global_object(); | 3073 GlobalObject* global = JSFunction::cast(fun)->context()->global_object(); |
| 3074 // Don't stop in debugger functions. | 3074 // Don't stop in debugger functions. |
| 3075 if (IsDebugGlobal(global)) return; | 3075 if (IsDebugGlobal(global)) return; |
| 3076 } | 3076 } |
| 3077 } | 3077 } |
| 3078 | 3078 |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3251 } else { | 3251 } else { |
| 3252 return v8::Utils::ToLocal(response_json_); | 3252 return v8::Utils::ToLocal(response_json_); |
| 3253 } | 3253 } |
| 3254 } | 3254 } |
| 3255 | 3255 |
| 3256 | 3256 |
| 3257 v8::Handle<v8::Context> MessageImpl::GetEventContext() const { | 3257 v8::Handle<v8::Context> MessageImpl::GetEventContext() const { |
| 3258 Isolate* isolate = event_data_->GetIsolate(); | 3258 Isolate* isolate = event_data_->GetIsolate(); |
| 3259 v8::Handle<v8::Context> context = GetDebugEventContext(isolate); | 3259 v8::Handle<v8::Context> context = GetDebugEventContext(isolate); |
| 3260 // Isolate::context() may be NULL when "script collected" event occures. | 3260 // Isolate::context() may be NULL when "script collected" event occures. |
| 3261 ASSERT(!context.IsEmpty()); | 3261 DCHECK(!context.IsEmpty()); |
| 3262 return context; | 3262 return context; |
| 3263 } | 3263 } |
| 3264 | 3264 |
| 3265 | 3265 |
| 3266 v8::Debug::ClientData* MessageImpl::GetClientData() const { | 3266 v8::Debug::ClientData* MessageImpl::GetClientData() const { |
| 3267 return client_data_; | 3267 return client_data_; |
| 3268 } | 3268 } |
| 3269 | 3269 |
| 3270 | 3270 |
| 3271 EventDetailsImpl::EventDetailsImpl(DebugEvent event, | 3271 EventDetailsImpl::EventDetailsImpl(DebugEvent event, |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3341 } | 3341 } |
| 3342 | 3342 |
| 3343 | 3343 |
| 3344 CommandMessageQueue::~CommandMessageQueue() { | 3344 CommandMessageQueue::~CommandMessageQueue() { |
| 3345 while (!IsEmpty()) Get().Dispose(); | 3345 while (!IsEmpty()) Get().Dispose(); |
| 3346 DeleteArray(messages_); | 3346 DeleteArray(messages_); |
| 3347 } | 3347 } |
| 3348 | 3348 |
| 3349 | 3349 |
| 3350 CommandMessage CommandMessageQueue::Get() { | 3350 CommandMessage CommandMessageQueue::Get() { |
| 3351 ASSERT(!IsEmpty()); | 3351 DCHECK(!IsEmpty()); |
| 3352 int result = start_; | 3352 int result = start_; |
| 3353 start_ = (start_ + 1) % size_; | 3353 start_ = (start_ + 1) % size_; |
| 3354 return messages_[result]; | 3354 return messages_[result]; |
| 3355 } | 3355 } |
| 3356 | 3356 |
| 3357 | 3357 |
| 3358 void CommandMessageQueue::Put(const CommandMessage& message) { | 3358 void CommandMessageQueue::Put(const CommandMessage& message) { |
| 3359 if ((end_ + 1) % size_ == start_) { | 3359 if ((end_ + 1) % size_ == start_) { |
| 3360 Expand(); | 3360 Expand(); |
| 3361 } | 3361 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3402 logger_->DebugEvent("Put", message.text()); | 3402 logger_->DebugEvent("Put", message.text()); |
| 3403 } | 3403 } |
| 3404 | 3404 |
| 3405 | 3405 |
| 3406 void LockingCommandMessageQueue::Clear() { | 3406 void LockingCommandMessageQueue::Clear() { |
| 3407 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 3407 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 3408 queue_.Clear(); | 3408 queue_.Clear(); |
| 3409 } | 3409 } |
| 3410 | 3410 |
| 3411 } } // namespace v8::internal | 3411 } } // namespace v8::internal |
| OLD | NEW |