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
3 // found in the LICENSE file.
4
5 #include "src/v8.h"
6
7 #include "src/api.h"
8 #include "src/arguments.h"
9 #include "src/bootstrapper.h"
10 #include "src/code-stubs.h"
11 #include "src/codegen.h"
12 #include "src/compilation-cache.h"
13 #include "src/compiler.h"
14 #include "src/debug.h"
15 #include "src/deoptimizer.h"
16 #include "src/execution.h"
17 #include "src/full-codegen.h"
18 #include "src/global-handles.h"
19 #include "src/ic.h"
20 #include "src/ic-inl.h"
21 #include "src/isolate-inl.h"
22 #include "src/list.h"
23 #include "src/messages.h"
24 #include "src/natives.h"
25 #include "src/stub-cache.h"
26 #include "src/log.h"
27
28 #include "include/v8-debug.h"
29
30 namespace v8 {
31 namespace internal {
32
Debug(Isolate * isolate)33 Debug::Debug(Isolate* isolate)
34 : debug_context_(Handle<Context>()),
35 event_listener_(Handle<Object>()),
36 event_listener_data_(Handle<Object>()),
37 message_handler_(NULL),
38 command_received_(0),
39 command_queue_(isolate->logger(), kQueueInitialSize),
40 event_command_queue_(isolate->logger(), kQueueInitialSize),
41 is_active_(false),
42 is_suppressed_(false),
43 live_edit_enabled_(true), // TODO(yangguo): set to false by default.
44 has_break_points_(false),
45 break_disabled_(false),
46 break_on_exception_(false),
47 break_on_uncaught_exception_(false),
48 script_cache_(NULL),
49 debug_info_list_(NULL),
50 isolate_(isolate) {
51 ThreadInit();
52 }
53
54
GetDebugEventContext(Isolate * isolate)55 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
56 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
57 // Isolate::context() may have been NULL when "script collected" event
58 // occured.
59 if (context.is_null()) return v8::Local<v8::Context>();
60 Handle<Context> native_context(context->native_context());
61 return v8::Utils::ToLocal(native_context);
62 }
63
64
BreakLocationIterator(Handle<DebugInfo> debug_info,BreakLocatorType type)65 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
66 BreakLocatorType type) {
67 debug_info_ = debug_info;
68 type_ = type;
69 reloc_iterator_ = NULL;
70 reloc_iterator_original_ = NULL;
71 Reset(); // Initialize the rest of the member variables.
72 }
73
74
~BreakLocationIterator()75 BreakLocationIterator::~BreakLocationIterator() {
76 ASSERT(reloc_iterator_ != NULL);
77 ASSERT(reloc_iterator_original_ != NULL);
78 delete reloc_iterator_;
79 delete reloc_iterator_original_;
80 }
81
82
83 // Check whether a code stub with the specified major key is a possible break
84 // point location when looking for source break locations.
IsSourceBreakStub(Code * code)85 static bool IsSourceBreakStub(Code* code) {
86 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
87 return major_key == CodeStub::CallFunction;
88 }
89
90
91 // Check whether a code stub with the specified major key is a possible break
92 // location.
IsBreakStub(Code * code)93 static bool IsBreakStub(Code* code) {
94 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
95 return major_key == CodeStub::CallFunction;
96 }
97
98
Next()99 void BreakLocationIterator::Next() {
100 DisallowHeapAllocation no_gc;
101 ASSERT(!RinfoDone());
102
103 // Iterate through reloc info for code and original code stopping at each
104 // breakable code target.
105 bool first = break_point_ == -1;
106 while (!RinfoDone()) {
107 if (!first) RinfoNext();
108 first = false;
109 if (RinfoDone()) return;
110
111 // Whenever a statement position or (plain) position is passed update the
112 // current value of these.
113 if (RelocInfo::IsPosition(rmode())) {
114 if (RelocInfo::IsStatementPosition(rmode())) {
115 statement_position_ = static_cast<int>(
116 rinfo()->data() - debug_info_->shared()->start_position());
117 }
118 // Always update the position as we don't want that to be before the
119 // statement position.
120 position_ = static_cast<int>(
121 rinfo()->data() - debug_info_->shared()->start_position());
122 ASSERT(position_ >= 0);
123 ASSERT(statement_position_ >= 0);
124 }
125
126 if (IsDebugBreakSlot()) {
127 // There is always a possible break point at a debug break slot.
128 break_point_++;
129 return;
130 } else if (RelocInfo::IsCodeTarget(rmode())) {
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
133 // to be of a different kind than in the original code.
134 Address target = original_rinfo()->target_address();
135 Code* code = Code::GetCodeFromTargetAddress(target);
136 if ((code->is_inline_cache_stub() &&
137 !code->is_binary_op_stub() &&
138 !code->is_compare_ic_stub() &&
139 !code->is_to_boolean_ic_stub()) ||
140 RelocInfo::IsConstructCall(rmode())) {
141 break_point_++;
142 return;
143 }
144 if (code->kind() == Code::STUB) {
145 if (IsDebuggerStatement()) {
146 break_point_++;
147 return;
148 } else if (type_ == ALL_BREAK_LOCATIONS) {
149 if (IsBreakStub(code)) {
150 break_point_++;
151 return;
152 }
153 } else {
154 ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
155 if (IsSourceBreakStub(code)) {
156 break_point_++;
157 return;
158 }
159 }
160 }
161 }
162
163 // Check for break at return.
164 if (RelocInfo::IsJSReturn(rmode())) {
165 // Set the positions to the end of the function.
166 if (debug_info_->shared()->HasSourceCode()) {
167 position_ = debug_info_->shared()->end_position() -
168 debug_info_->shared()->start_position() - 1;
169 } else {
170 position_ = 0;
171 }
172 statement_position_ = position_;
173 break_point_++;
174 return;
175 }
176 }
177 }
178
179
Next(int count)180 void BreakLocationIterator::Next(int count) {
181 while (count > 0) {
182 Next();
183 count--;
184 }
185 }
186
187
188 // Find the break point at the supplied address, or the closest one before
189 // the address.
FindBreakLocationFromAddress(Address pc)190 void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
191 // Run through all break points to locate the one closest to the address.
192 int closest_break_point = 0;
193 int distance = kMaxInt;
194 while (!Done()) {
195 // Check if this break point is closer that what was previously found.
196 if (this->pc() <= pc && pc - this->pc() < distance) {
197 closest_break_point = break_point();
198 distance = static_cast<int>(pc - this->pc());
199 // Check whether we can't get any closer.
200 if (distance == 0) break;
201 }
202 Next();
203 }
204
205 // Move to the break point found.
206 Reset();
207 Next(closest_break_point);
208 }
209
210
211 // Find the break point closest to the supplied source position.
FindBreakLocationFromPosition(int position,BreakPositionAlignment alignment)212 void BreakLocationIterator::FindBreakLocationFromPosition(int position,
213 BreakPositionAlignment alignment) {
214 // Run through all break points to locate the one closest to the source
215 // position.
216 int closest_break_point = 0;
217 int distance = kMaxInt;
218
219 while (!Done()) {
220 int next_position;
221 switch (alignment) {
222 case STATEMENT_ALIGNED:
223 next_position = this->statement_position();
224 break;
225 case BREAK_POSITION_ALIGNED:
226 next_position = this->position();
227 break;
228 default:
229 UNREACHABLE();
230 next_position = this->statement_position();
231 }
232 // Check if this break point is closer that what was previously found.
233 if (position <= next_position && next_position - position < distance) {
234 closest_break_point = break_point();
235 distance = next_position - position;
236 // Check whether we can't get any closer.
237 if (distance == 0) break;
238 }
239 Next();
240 }
241
242 // Move to the break point found.
243 Reset();
244 Next(closest_break_point);
245 }
246
247
Reset()248 void BreakLocationIterator::Reset() {
249 // Create relocation iterators for the two code objects.
250 if (reloc_iterator_ != NULL) delete reloc_iterator_;
251 if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
252 reloc_iterator_ = new RelocIterator(
253 debug_info_->code(),
254 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
255 reloc_iterator_original_ = new RelocIterator(
256 debug_info_->original_code(),
257 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
258
259 // Position at the first break point.
260 break_point_ = -1;
261 position_ = 1;
262 statement_position_ = 1;
263 Next();
264 }
265
266
Done() const267 bool BreakLocationIterator::Done() const {
268 return RinfoDone();
269 }
270
271
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
274 // break.
275 if (!HasBreakPoint()) SetDebugBreak();
276 ASSERT(IsDebugBreak() || IsDebuggerStatement());
277 // Set the break point information.
278 DebugInfo::SetBreakPoint(debug_info_, code_position(),
279 position(), statement_position(),
280 break_point_object);
281 }
282
283
ClearBreakPoint(Handle<Object> break_point_object)284 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
285 // Clear the break point information.
286 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
287 // If there are no more break points here remove the debug break.
288 if (!HasBreakPoint()) {
289 ClearDebugBreak();
290 ASSERT(!IsDebugBreak());
291 }
292 }
293
294
SetOneShot()295 void BreakLocationIterator::SetOneShot() {
296 // Debugger statement always calls debugger. No need to modify it.
297 if (IsDebuggerStatement()) return;
298
299 // If there is a real break point here no more to do.
300 if (HasBreakPoint()) {
301 ASSERT(IsDebugBreak());
302 return;
303 }
304
305 // Patch code with debug break.
306 SetDebugBreak();
307 }
308
309
ClearOneShot()310 void BreakLocationIterator::ClearOneShot() {
311 // Debugger statement always calls debugger. No need to modify it.
312 if (IsDebuggerStatement()) return;
313
314 // If there is a real break point here no more to do.
315 if (HasBreakPoint()) {
316 ASSERT(IsDebugBreak());
317 return;
318 }
319
320 // Patch code removing debug break.
321 ClearDebugBreak();
322 ASSERT(!IsDebugBreak());
323 }
324
325
SetDebugBreak()326 void BreakLocationIterator::SetDebugBreak() {
327 // Debugger statement always calls debugger. No need to modify it.
328 if (IsDebuggerStatement()) return;
329
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
332 // function twice might happen when stepping in a function with an exception
333 // handler as the handler and the function is the same.
334 if (IsDebugBreak()) return;
335
336 if (RelocInfo::IsJSReturn(rmode())) {
337 // Patch the frame exit code with a break point.
338 SetDebugBreakAtReturn();
339 } else if (IsDebugBreakSlot()) {
340 // Patch the code in the break slot.
341 SetDebugBreakAtSlot();
342 } else {
343 // Patch the IC call.
344 SetDebugBreakAtIC();
345 }
346 ASSERT(IsDebugBreak());
347 }
348
349
ClearDebugBreak()350 void BreakLocationIterator::ClearDebugBreak() {
351 // Debugger statement always calls debugger. No need to modify it.
352 if (IsDebuggerStatement()) return;
353
354 if (RelocInfo::IsJSReturn(rmode())) {
355 // Restore the frame exit code.
356 ClearDebugBreakAtReturn();
357 } else if (IsDebugBreakSlot()) {
358 // Restore the code in the break slot.
359 ClearDebugBreakAtSlot();
360 } else {
361 // Patch the IC call.
362 ClearDebugBreakAtIC();
363 }
364 ASSERT(!IsDebugBreak());
365 }
366
367
IsStepInLocation(Isolate * isolate)368 bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
369 if (RelocInfo::IsConstructCall(original_rmode())) {
370 return true;
371 } else if (RelocInfo::IsCodeTarget(rmode())) {
372 HandleScope scope(debug_info_->GetIsolate());
373 Address target = original_rinfo()->target_address();
374 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
375 if (target_code->kind() == Code::STUB) {
376 return target_code->major_key() == CodeStub::CallFunction;
377 }
378 return target_code->is_call_stub();
379 }
380 return false;
381 }
382
383
PrepareStepIn(Isolate * isolate)384 void BreakLocationIterator::PrepareStepIn(Isolate* isolate) {
385 #ifdef DEBUG
386 HandleScope scope(isolate);
387 // Step in can only be prepared if currently positioned on an IC call,
388 // construct call or CallFunction stub call.
389 Address target = rinfo()->target_address();
390 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
391 // All the following stuff is needed only for assertion checks so the code
392 // is wrapped in ifdef.
393 Handle<Code> maybe_call_function_stub = target_code;
394 if (IsDebugBreak()) {
395 Address original_target = original_rinfo()->target_address();
396 maybe_call_function_stub =
397 Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
398 }
399 bool is_call_function_stub =
400 (maybe_call_function_stub->kind() == Code::STUB &&
401 maybe_call_function_stub->major_key() == CodeStub::CallFunction);
402
403 // Step in through construct call requires no changes to the running code.
404 // Step in through getters/setters should already be prepared as well
405 // because caller of this function (Debug::PrepareStep) is expected to
406 // flood the top frame's function with one shot breakpoints.
407 // Step in through CallFunction stub should also be prepared by caller of
408 // this function (Debug::PrepareStep) which should flood target function
409 // with breakpoints.
410 ASSERT(RelocInfo::IsConstructCall(rmode()) ||
411 target_code->is_inline_cache_stub() ||
412 is_call_function_stub);
413 #endif
414 }
415
416
417 // Check whether the break point is at a position which will exit the function.
IsExit() const418 bool BreakLocationIterator::IsExit() const {
419 return (RelocInfo::IsJSReturn(rmode()));
420 }
421
422
HasBreakPoint()423 bool BreakLocationIterator::HasBreakPoint() {
424 return debug_info_->HasBreakPoint(code_position());
425 }
426
427
428 // Check whether there is a debug break at the current position.
IsDebugBreak()429 bool BreakLocationIterator::IsDebugBreak() {
430 if (RelocInfo::IsJSReturn(rmode())) {
431 return IsDebugBreakAtReturn();
432 } else if (IsDebugBreakSlot()) {
433 return IsDebugBreakAtSlot();
434 } else {
435 return Debug::IsDebugBreak(rinfo()->target_address());
436 }
437 }
438
439
440 // Find the builtin to use for invoking the debug break
DebugBreakForIC(Handle<Code> code,RelocInfo::Mode mode)441 static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
442 Isolate* isolate = code->GetIsolate();
443
444 // Find the builtin debug break function matching the calling convention
445 // used by the call site.
446 if (code->is_inline_cache_stub()) {
447 switch (code->kind()) {
448 case Code::CALL_IC:
449 return isolate->builtins()->CallICStub_DebugBreak();
450
451 case Code::LOAD_IC:
452 return isolate->builtins()->LoadIC_DebugBreak();
453
454 case Code::STORE_IC:
455 return isolate->builtins()->StoreIC_DebugBreak();
456
457 case Code::KEYED_LOAD_IC:
458 return isolate->builtins()->KeyedLoadIC_DebugBreak();
459
460 case Code::KEYED_STORE_IC:
461 return isolate->builtins()->KeyedStoreIC_DebugBreak();
462
463 case Code::COMPARE_NIL_IC:
464 return isolate->builtins()->CompareNilIC_DebugBreak();
465
466 default:
467 UNREACHABLE();
468 }
469 }
470 if (RelocInfo::IsConstructCall(mode)) {
471 if (code->has_function_cache()) {
472 return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
473 } else {
474 return isolate->builtins()->CallConstructStub_DebugBreak();
475 }
476 }
477 if (code->kind() == Code::STUB) {
478 ASSERT(code->major_key() == CodeStub::CallFunction);
479 return isolate->builtins()->CallFunctionStub_DebugBreak();
480 }
481
482 UNREACHABLE();
483 return Handle<Code>::null();
484 }
485
486
SetDebugBreakAtIC()487 void BreakLocationIterator::SetDebugBreakAtIC() {
488 // Patch the original code with the current address as the current address
489 // might have changed by the inline caching since the code was copied.
490 original_rinfo()->set_target_address(rinfo()->target_address());
491
492 RelocInfo::Mode mode = rmode();
493 if (RelocInfo::IsCodeTarget(mode)) {
494 Address target = rinfo()->target_address();
495 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
496
497 // Patch the code to invoke the builtin debug break function matching the
498 // calling convention used by the call site.
499 Handle<Code> dbgbrk_code = DebugBreakForIC(target_code, mode);
500 rinfo()->set_target_address(dbgbrk_code->entry());
501 }
502 }
503
504
ClearDebugBreakAtIC()505 void BreakLocationIterator::ClearDebugBreakAtIC() {
506 // Patch the code to the original invoke.
507 rinfo()->set_target_address(original_rinfo()->target_address());
508 }
509
510
IsDebuggerStatement()511 bool BreakLocationIterator::IsDebuggerStatement() {
512 return RelocInfo::DEBUG_BREAK == rmode();
513 }
514
515
IsDebugBreakSlot()516 bool BreakLocationIterator::IsDebugBreakSlot() {
517 return RelocInfo::DEBUG_BREAK_SLOT == rmode();
518 }
519
520
BreakPointObjects()521 Object* BreakLocationIterator::BreakPointObjects() {
522 return debug_info_->GetBreakPointObjects(code_position());
523 }
524
525
526 // Clear out all the debug break code. This is ONLY supposed to be used when
527 // shutting down the debugger as it will leave the break point information in
528 // DebugInfo even though the code is patched back to the non break point state.
ClearAllDebugBreak()529 void BreakLocationIterator::ClearAllDebugBreak() {
530 while (!Done()) {
531 ClearDebugBreak();
532 Next();
533 }
534 }
535
536
RinfoDone() const537 bool BreakLocationIterator::RinfoDone() const {
538 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
539 return reloc_iterator_->done();
540 }
541
542
RinfoNext()543 void BreakLocationIterator::RinfoNext() {
544 reloc_iterator_->next();
545 reloc_iterator_original_->next();
546 #ifdef DEBUG
547 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
548 if (!reloc_iterator_->done()) {
549 ASSERT(rmode() == original_rmode());
550 }
551 #endif
552 }
553
554
555 // Threading support.
ThreadInit()556 void Debug::ThreadInit() {
557 thread_local_.break_count_ = 0;
558 thread_local_.break_id_ = 0;
559 thread_local_.break_frame_id_ = StackFrame::NO_ID;
560 thread_local_.last_step_action_ = StepNone;
561 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
562 thread_local_.step_count_ = 0;
563 thread_local_.last_fp_ = 0;
564 thread_local_.queued_step_count_ = 0;
565 thread_local_.step_into_fp_ = 0;
566 thread_local_.step_out_fp_ = 0;
567 // TODO(isolates): frames_are_dropped_?
568 thread_local_.current_debug_scope_ = NULL;
569 thread_local_.restarter_frame_function_pointer_ = NULL;
570 thread_local_.promise_on_stack_ = NULL;
571 }
572
573
ArchiveDebug(char * storage)574 char* Debug::ArchiveDebug(char* storage) {
575 char* to = storage;
576 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
577 ThreadInit();
578 return storage + ArchiveSpacePerThread();
579 }
580
581
RestoreDebug(char * storage)582 char* Debug::RestoreDebug(char* storage) {
583 char* from = storage;
584 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
585 return storage + ArchiveSpacePerThread();
586 }
587
588
ArchiveSpacePerThread()589 int Debug::ArchiveSpacePerThread() {
590 return sizeof(ThreadLocal);
591 }
592
593
ScriptCache(Isolate * isolate)594 ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch),
595 isolate_(isolate),
596 collected_scripts_(10) {
597 Heap* heap = isolate_->heap();
598 HandleScope scope(isolate_);
599
600 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
601 // rid of all the cached script wrappers and the second gets rid of the
602 // scripts which are no longer referenced.
603 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache");
604 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache");
605
606 // Scan heap for Script objects.
607 HeapIterator iterator(heap);
608 DisallowHeapAllocation no_allocation;
609
610 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
611 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
612 Add(Handle<Script>(Script::cast(obj)));
613 }
614 }
615 }
616
617
Add(Handle<Script> script)618 void ScriptCache::Add(Handle<Script> script) {
619 GlobalHandles* global_handles = isolate_->global_handles();
620 // Create an entry in the hash map for the script.
621 int id = script->id()->value();
622 HashMap::Entry* entry =
623 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
624 if (entry->value != NULL) {
625 ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
626 return;
627 }
628 // Globalize the script object, make it weak and use the location of the
629 // global handle as the value in the hash map.
630 Handle<Script> script_ =
631 Handle<Script>::cast(global_handles->Create(*script));
632 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
633 this,
634 ScriptCache::HandleWeakScript);
635 entry->value = script_.location();
636 }
637
638
GetScripts()639 Handle<FixedArray> ScriptCache::GetScripts() {
640 Factory* factory = isolate_->factory();
641 Handle<FixedArray> instances = factory->NewFixedArray(occupancy());
642 int count = 0;
643 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
644 ASSERT(entry->value != NULL);
645 if (entry->value != NULL) {
646 instances->set(count, *reinterpret_cast<Script**>(entry->value));
647 count++;
648 }
649 }
650 return instances;
651 }
652
653
ProcessCollectedScripts()654 void ScriptCache::ProcessCollectedScripts() {
655 Debug* debug = isolate_->debug();
656 for (int i = 0; i < collected_scripts_.length(); i++) {
657 debug->OnScriptCollected(collected_scripts_[i]);
658 }
659 collected_scripts_.Clear();
660 }
661
662
Clear()663 void ScriptCache::Clear() {
664 // Iterate the script cache to get rid of all the weak handles.
665 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
666 ASSERT(entry != NULL);
667 Object** location = reinterpret_cast<Object**>(entry->value);
668 ASSERT((*location)->IsScript());
669 GlobalHandles::ClearWeakness(location);
670 GlobalHandles::Destroy(location);
671 }
672 // Clear the content of the hash map.
673 HashMap::Clear();
674 }
675
676
HandleWeakScript(const v8::WeakCallbackData<v8::Value,void> & data)677 void ScriptCache::HandleWeakScript(
678 const v8::WeakCallbackData<v8::Value, void>& data) {
679 // Retrieve the script identifier.
680 Handle<Object> object = Utils::OpenHandle(*data.GetValue());
681 int id = Handle<Script>::cast(object)->id()->value();
682 void* key = reinterpret_cast<void*>(id);
683 uint32_t hash = Hash(id);
684
685 // Remove the corresponding entry from the cache.
686 ScriptCache* script_cache =
687 reinterpret_cast<ScriptCache*>(data.GetParameter());
688 HashMap::Entry* entry = script_cache->Lookup(key, hash, false);
689 Object** location = reinterpret_cast<Object**>(entry->value);
690 script_cache->Remove(key, hash);
691 script_cache->collected_scripts_.Add(id);
692
693 // Clear the weak handle.
694 GlobalHandles::Destroy(location);
695 }
696
697
HandleWeakDebugInfo(const v8::WeakCallbackData<v8::Value,void> & data)698 void Debug::HandleWeakDebugInfo(
699 const v8::WeakCallbackData<v8::Value, void>& data) {
700 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug();
701 DebugInfoListNode* node =
702 reinterpret_cast<DebugInfoListNode*>(data.GetParameter());
703 // We need to clear all breakpoints associated with the function to restore
704 // original code and avoid patching the code twice later because
705 // the function will live in the heap until next gc, and can be found by
706 // Debug::FindSharedFunctionInfoInScript.
707 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
708 it.ClearAllDebugBreak();
709 debug->RemoveDebugInfo(node->debug_info());
710 #ifdef DEBUG
711 for (DebugInfoListNode* n = debug->debug_info_list_;
712 n != NULL;
713 n = n->next()) {
714 ASSERT(n != node);
715 }
716 #endif
717 }
718
719
DebugInfoListNode(DebugInfo * debug_info)720 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
721 // Globalize the request debug info object and make it weak.
722 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
723 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info));
724 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
725 this,
726 Debug::HandleWeakDebugInfo);
727 }
728
729
~DebugInfoListNode()730 DebugInfoListNode::~DebugInfoListNode() {
731 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
732 }
733
734
CompileDebuggerScript(Isolate * isolate,int index)735 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
736 Factory* factory = isolate->factory();
737 HandleScope scope(isolate);
738
739 // Bail out if the index is invalid.
740 if (index == -1) return false;
741
742 // Find source and name for the requested script.
743 Handle<String> source_code =
744 isolate->bootstrapper()->NativesSourceLookup(index);
745 Vector<const char> name = Natives::GetScriptName(index);
746 Handle<String> script_name =
747 factory->NewStringFromAscii(name).ToHandleChecked();
748 Handle<Context> context = isolate->native_context();
749
750 // Compile the script.
751 Handle<SharedFunctionInfo> function_info;
752 function_info = Compiler::CompileScript(source_code,
753 script_name, 0, 0,
754 false,
755 context,
756 NULL, NULL, NO_CACHED_DATA,
757 NATIVES_CODE);
758
759 // Silently ignore stack overflows during compilation.
760 if (function_info.is_null()) {
761 ASSERT(isolate->has_pending_exception());
762 isolate->clear_pending_exception();
763 return false;
764 }
765
766 // Execute the shared function in the debugger context.
767 Handle<JSFunction> function =
768 factory->NewFunctionFromSharedFunctionInfo(function_info, context);
769
770 Handle<Object> exception;
771 MaybeHandle<Object> result =
772 Execution::TryCall(function,
773 Handle<Object>(context->global_object(), isolate),
774 0,
775 NULL,
776 &exception);
777
778 // Check for caught exceptions.
779 if (result.is_null()) {
780 ASSERT(!isolate->has_pending_exception());
781 MessageLocation computed_location;
782 isolate->ComputeLocation(&computed_location);
783 Handle<Object> message = MessageHandler::MakeMessageObject(
784 isolate, "error_loading_debugger", &computed_location,
785 Vector<Handle<Object> >::empty(), Handle<JSArray>());
786 ASSERT(!isolate->has_pending_exception());
787 if (!exception.is_null()) {
788 isolate->set_pending_exception(*exception);
789 MessageHandler::ReportMessage(isolate, NULL, message);
790 isolate->clear_pending_exception();
791 }
792 return false;
793 }
794
795 // Mark this script as native and return successfully.
796 Handle<Script> script(Script::cast(function->shared()->script()));
797 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
798 return true;
799 }
800
801
Load()802 bool Debug::Load() {
803 // Return if debugger is already loaded.
804 if (is_loaded()) return true;
805
806 // Bail out if we're already in the process of compiling the native
807 // JavaScript source code for the debugger.
808 if (is_suppressed_) return false;
809 SuppressDebug while_loading(this);
810
811 // Disable breakpoints and interrupts while compiling and running the
812 // debugger scripts including the context creation code.
813 DisableBreak disable(this, true);
814 PostponeInterruptsScope postpone(isolate_);
815
816 // Create the debugger context.
817 HandleScope scope(isolate_);
818 ExtensionConfiguration no_extensions;
819 Handle<Context> context =
820 isolate_->bootstrapper()->CreateEnvironment(
821 Handle<Object>::null(),
822 v8::Handle<ObjectTemplate>(),
823 &no_extensions);
824
825 // Fail if no context could be created.
826 if (context.is_null()) return false;
827
828 // Use the debugger context.
829 SaveContext save(isolate_);
830 isolate_->set_context(*context);
831
832 // Expose the builtins object in the debugger context.
833 Handle<String> key = isolate_->factory()->InternalizeOneByteString(
834 STATIC_ASCII_VECTOR("builtins"));
835 Handle<GlobalObject> global =
836 Handle<GlobalObject>(context->global_object(), isolate_);
837 Handle<JSBuiltinsObject> builtin =
838 Handle<JSBuiltinsObject>(global->builtins(), isolate_);
839 RETURN_ON_EXCEPTION_VALUE(
840 isolate_,
841 JSReceiver::SetProperty(global, key, builtin, NONE, SLOPPY),
842 false);
843
844 // Compile the JavaScript for the debugger in the debugger context.
845 bool caught_exception =
846 !CompileDebuggerScript(isolate_, Natives::GetIndex("mirror")) ||
847 !CompileDebuggerScript(isolate_, Natives::GetIndex("debug"));
848
849 if (FLAG_enable_liveedit) {
850 caught_exception = caught_exception ||
851 !CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit"));
852 }
853 // Check for caught exceptions.
854 if (caught_exception) return false;
855
856 debug_context_ = Handle<Context>::cast(
857 isolate_->global_handles()->Create(*context));
858 return true;
859 }
860
861
Unload()862 void Debug::Unload() {
863 ClearAllBreakPoints();
864 ClearStepping();
865
866 // Match unmatched PromiseHandlePrologue calls.
867 while (thread_local_.promise_on_stack_) PromiseHandleEpilogue();
868
869 // Return debugger is not loaded.
870 if (!is_loaded()) return;
871
872 // Clear the script cache.
873 if (script_cache_ != NULL) {
874 delete script_cache_;
875 script_cache_ = NULL;
876 }
877
878 // Clear debugger context global handle.
879 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
880 debug_context_ = Handle<Context>();
881 }
882
883
Break(Arguments args,JavaScriptFrame * frame)884 void Debug::Break(Arguments args, JavaScriptFrame* frame) {
885 Heap* heap = isolate_->heap();
886 HandleScope scope(isolate_);
887 ASSERT(args.length() == 0);
888
889 // Initialize LiveEdit.
890 LiveEdit::InitializeThreadLocal(this);
891
892 // Just continue if breaks are disabled or debugger cannot be loaded.
893 if (break_disabled_) return;
894
895 // Enter the debugger.
896 DebugScope debug_scope(this);
897 if (debug_scope.failed()) return;
898
899 // Postpone interrupt during breakpoint processing.
900 PostponeInterruptsScope postpone(isolate_);
901
902 // Get the debug info (create it if it does not exist).
903 Handle<SharedFunctionInfo> shared =
904 Handle<SharedFunctionInfo>(frame->function()->shared());
905 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
906
907 // Find the break point where execution has stopped.
908 BreakLocationIterator break_location_iterator(debug_info,
909 ALL_BREAK_LOCATIONS);
910 // pc points to the instruction after the current one, possibly a break
911 // location as well. So the "- 1" to exclude it from the search.
912 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
913
914 // Check whether step next reached a new statement.
915 if (!StepNextContinue(&break_location_iterator, frame)) {
916 // Decrease steps left if performing multiple steps.
917 if (thread_local_.step_count_ > 0) {
918 thread_local_.step_count_--;
919 }
920 }
921
922 // If there is one or more real break points check whether any of these are
923 // triggered.
924 Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
925 if (break_location_iterator.HasBreakPoint()) {
926 Handle<Object> break_point_objects =
927 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_);
928 break_points_hit = CheckBreakPoints(break_point_objects);
929 }
930
931 // If step out is active skip everything until the frame where we need to step
932 // out to is reached, unless real breakpoint is hit.
933 if (StepOutActive() &&
934 frame->fp() != thread_local_.step_out_fp_ &&
935 break_points_hit->IsUndefined() ) {
936 // Step count should always be 0 for StepOut.
937 ASSERT(thread_local_.step_count_ == 0);
938 } else if (!break_points_hit->IsUndefined() ||
939 (thread_local_.last_step_action_ != StepNone &&
940 thread_local_.step_count_ == 0)) {
941 // Notify debugger if a real break point is triggered or if performing
942 // single stepping with no more steps to perform. Otherwise do another step.
943
944 // Clear all current stepping setup.
945 ClearStepping();
946
947 if (thread_local_.queued_step_count_ > 0) {
948 // Perform queued steps
949 int step_count = thread_local_.queued_step_count_;
950
951 // Clear queue
952 thread_local_.queued_step_count_ = 0;
953
954 PrepareStep(StepNext, step_count, StackFrame::NO_ID);
955 } else {
956 // Notify the debug event listeners.
957 OnDebugBreak(break_points_hit, false);
958 }
959 } else if (thread_local_.last_step_action_ != StepNone) {
960 // Hold on to last step action as it is cleared by the call to
961 // ClearStepping.
962 StepAction step_action = thread_local_.last_step_action_;
963 int step_count = thread_local_.step_count_;
964
965 // If StepNext goes deeper in code, StepOut until original frame
966 // and keep step count queued up in the meantime.
967 if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
968 // Count frames until target frame
969 int count = 0;
970 JavaScriptFrameIterator it(isolate_);
971 while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
972 count++;
973 it.Advance();
974 }
975
976 // Check that we indeed found the frame we are looking for.
977 CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
978 if (step_count > 1) {
979 // Save old count and action to continue stepping after StepOut.
980 thread_local_.queued_step_count_ = step_count - 1;
981 }
982
983 // Set up for StepOut to reach target frame.
984 step_action = StepOut;
985 step_count = count;
986 }
987
988 // Clear all current stepping setup.
989 ClearStepping();
990
991 // Set up for the remaining steps.
992 PrepareStep(step_action, step_count, StackFrame::NO_ID);
993 }
994 }
995
996
RUNTIME_FUNCTION(Debug_Break)997 RUNTIME_FUNCTION(Debug_Break) {
998 // Get the top-most JavaScript frame.
999 JavaScriptFrameIterator it(isolate);
1000 isolate->debug()->Break(args, it.frame());
1001 isolate->debug()->SetAfterBreakTarget(it.frame());
1002 return isolate->heap()->undefined_value();
1003 }
1004
1005
1006 // Check the break point objects for whether one or more are actually
1007 // triggered. This function returns a JSArray with the break point objects
1008 // which is triggered.
CheckBreakPoints(Handle<Object> break_point_objects)1009 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
1010 Factory* factory = isolate_->factory();
1011
1012 // Count the number of break points hit. If there are multiple break points
1013 // they are in a FixedArray.
1014 Handle<FixedArray> break_points_hit;
1015 int break_points_hit_count = 0;
1016 ASSERT(!break_point_objects->IsUndefined());
1017 if (break_point_objects->IsFixedArray()) {
1018 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
1019 break_points_hit = factory->NewFixedArray(array->length());
1020 for (int i = 0; i < array->length(); i++) {
1021 Handle<Object> o(array->get(i), isolate_);
1022 if (CheckBreakPoint(o)) {
1023 break_points_hit->set(break_points_hit_count++, *o);
1024 }
1025 }
1026 } else {
1027 break_points_hit = factory->NewFixedArray(1);
1028 if (CheckBreakPoint(break_point_objects)) {
1029 break_points_hit->set(break_points_hit_count++, *break_point_objects);
1030 }
1031 }
1032
1033 // Return undefined if no break points were triggered.
1034 if (break_points_hit_count == 0) {
1035 return factory->undefined_value();
1036 }
1037 // Return break points hit as a JSArray.
1038 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
1039 result->set_length(Smi::FromInt(break_points_hit_count));
1040 return result;
1041 }
1042
1043
1044 // Check whether a single break point object is triggered.
CheckBreakPoint(Handle<Object> break_point_object)1045 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
1046 Factory* factory = isolate_->factory();
1047 HandleScope scope(isolate_);
1048
1049 // Ignore check if break point object is not a JSObject.
1050 if (!break_point_object->IsJSObject()) return true;
1051
1052 // Get the function IsBreakPointTriggered (defined in debug-debugger.js).
1053 Handle<String> is_break_point_triggered_string =
1054 factory->InternalizeOneByteString(
1055 STATIC_ASCII_VECTOR("IsBreakPointTriggered"));
1056 Handle<GlobalObject> debug_global(debug_context()->global_object());
1057 Handle<JSFunction> check_break_point =
1058 Handle<JSFunction>::cast(Object::GetProperty(
1059 debug_global, is_break_point_triggered_string).ToHandleChecked());
1060
1061 // Get the break id as an object.
1062 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
1063
1064 // Call HandleBreakPointx.
1065 Handle<Object> argv[] = { break_id, break_point_object };
1066 Handle<Object> result;
1067 if (!Execution::TryCall(check_break_point,
1068 isolate_->js_builtins_object(),
1069 ARRAY_SIZE(argv),
1070 argv).ToHandle(&result)) {
1071 return false;
1072 }
1073
1074 // Return whether the break point is triggered.
1075 return result->IsTrue();
1076 }
1077
1078
1079 // Check whether the function has debug information.
HasDebugInfo(Handle<SharedFunctionInfo> shared)1080 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
1081 return !shared->debug_info()->IsUndefined();
1082 }
1083
1084
1085 // Return the debug info for this function. EnsureDebugInfo must be called
1086 // prior to ensure the debug info has been generated for shared.
GetDebugInfo(Handle<SharedFunctionInfo> shared)1087 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
1088 ASSERT(HasDebugInfo(shared));
1089 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
1090 }
1091
1092
SetBreakPoint(Handle<JSFunction> function,Handle<Object> break_point_object,int * source_position)1093 bool Debug::SetBreakPoint(Handle<JSFunction> function,
1094 Handle<Object> break_point_object,
1095 int* source_position) {
1096 HandleScope scope(isolate_);
1097
1098 PrepareForBreakPoints();
1099
1100 // Make sure the function is compiled and has set up the debug info.
1101 Handle<SharedFunctionInfo> shared(function->shared());
1102 if (!EnsureDebugInfo(shared, function)) {
1103 // Return if retrieving debug info failed.
1104 return true;
1105 }
1106
1107 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1108 // Source positions starts with zero.
1109 ASSERT(*source_position >= 0);
1110
1111 // Find the break point and change it.
1112 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1113 it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED);
1114 it.SetBreakPoint(break_point_object);
1115
1116 *source_position = it.position();
1117
1118 // At least one active break point now.
1119 return debug_info->GetBreakPointCount() > 0;
1120 }
1121
1122
SetBreakPointForScript(Handle<Script> script,Handle<Object> break_point_object,int * source_position,BreakPositionAlignment alignment)1123 bool Debug::SetBreakPointForScript(Handle<Script> script,
1124 Handle<Object> break_point_object,
1125 int* source_position,
1126 BreakPositionAlignment alignment) {
1127 HandleScope scope(isolate_);
1128
1129 PrepareForBreakPoints();
1130
1131 // Obtain shared function info for the function.
1132 Object* result = FindSharedFunctionInfoInScript(script, *source_position);
1133 if (result->IsUndefined()) return false;
1134
1135 // Make sure the function has set up the debug info.
1136 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
1137 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1138 // Return if retrieving debug info failed.
1139 return false;
1140 }
1141
1142 // Find position within function. The script position might be before the
1143 // source position of the first function.
1144 int position;
1145 if (shared->start_position() > *source_position) {
1146 position = 0;
1147 } else {
1148 position = *source_position - shared->start_position();
1149 }
1150
1151 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1152 // Source positions starts with zero.
1153 ASSERT(position >= 0);
1154
1155 // Find the break point and change it.
1156 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1157 it.FindBreakLocationFromPosition(position, alignment);
1158 it.SetBreakPoint(break_point_object);
1159
1160 *source_position = it.position() + shared->start_position();
1161
1162 // At least one active break point now.
1163 ASSERT(debug_info->GetBreakPointCount() > 0);
1164 return true;
1165 }
1166
1167
ClearBreakPoint(Handle<Object> break_point_object)1168 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1169 HandleScope scope(isolate_);
1170
1171 DebugInfoListNode* node = debug_info_list_;
1172 while (node != NULL) {
1173 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
1174 break_point_object);
1175 if (!result->IsUndefined()) {
1176 // Get information in the break point.
1177 BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
1178 Handle<DebugInfo> debug_info = node->debug_info();
1179
1180 // Find the break point and clear it.
1181 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1182 it.FindBreakLocationFromAddress(debug_info->code()->entry() +
1183 break_point_info->code_position()->value());
1184 it.ClearBreakPoint(break_point_object);
1185
1186 // If there are no more break points left remove the debug info for this
1187 // function.
1188 if (debug_info->GetBreakPointCount() == 0) {
1189 RemoveDebugInfo(debug_info);
1190 }
1191
1192 return;
1193 }
1194 node = node->next();
1195 }
1196 }
1197
1198
ClearAllBreakPoints()1199 void Debug::ClearAllBreakPoints() {
1200 DebugInfoListNode* node = debug_info_list_;
1201 while (node != NULL) {
1202 // Remove all debug break code.
1203 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1204 it.ClearAllDebugBreak();
1205 node = node->next();
1206 }
1207
1208 // Remove all debug info.
1209 while (debug_info_list_ != NULL) {
1210 RemoveDebugInfo(debug_info_list_->debug_info());
1211 }
1212 }
1213
1214
FloodWithOneShot(Handle<JSFunction> function)1215 void Debug::FloodWithOneShot(Handle<JSFunction> function) {
1216 PrepareForBreakPoints();
1217
1218 // Make sure the function is compiled and has set up the debug info.
1219 Handle<SharedFunctionInfo> shared(function->shared());
1220 if (!EnsureDebugInfo(shared, function)) {
1221 // Return if we failed to retrieve the debug info.
1222 return;
1223 }
1224
1225 // Flood the function with break points.
1226 BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
1227 while (!it.Done()) {
1228 it.SetOneShot();
1229 it.Next();
1230 }
1231 }
1232
1233
FloodBoundFunctionWithOneShot(Handle<JSFunction> function)1234 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
1235 Handle<FixedArray> new_bindings(function->function_bindings());
1236 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
1237 isolate_);
1238
1239 if (!bindee.is_null() && bindee->IsJSFunction() &&
1240 !JSFunction::cast(*bindee)->IsNative()) {
1241 Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
1242 Debug::FloodWithOneShot(bindee_function);
1243 }
1244 }
1245
1246
FloodHandlerWithOneShot()1247 void Debug::FloodHandlerWithOneShot() {
1248 // Iterate through the JavaScript stack looking for handlers.
1249 StackFrame::Id id = break_frame_id();
1250 if (id == StackFrame::NO_ID) {
1251 // If there is no JavaScript stack don't do anything.
1252 return;
1253 }
1254 for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
1255 JavaScriptFrame* frame = it.frame();
1256 if (frame->HasHandler()) {
1257 // Flood the function with the catch block with break points
1258 FloodWithOneShot(Handle<JSFunction>(frame->function()));
1259 return;
1260 }
1261 }
1262 }
1263
1264
ChangeBreakOnException(ExceptionBreakType type,bool enable)1265 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
1266 if (type == BreakUncaughtException) {
1267 break_on_uncaught_exception_ = enable;
1268 } else {
1269 break_on_exception_ = enable;
1270 }
1271 }
1272
1273
IsBreakOnException(ExceptionBreakType type)1274 bool Debug::IsBreakOnException(ExceptionBreakType type) {
1275 if (type == BreakUncaughtException) {
1276 return break_on_uncaught_exception_;
1277 } else {
1278 return break_on_exception_;
1279 }
1280 }
1281
1282
PromiseOnStack(Isolate * isolate,PromiseOnStack * prev,Handle<JSFunction> getter)1283 PromiseOnStack::PromiseOnStack(Isolate* isolate,
1284 PromiseOnStack* prev,
1285 Handle<JSFunction> getter)
1286 : isolate_(isolate), prev_(prev) {
1287 handler_ = StackHandler::FromAddress(
1288 Isolate::handler(isolate->thread_local_top()));
1289 getter_ = Handle<JSFunction>::cast(
1290 isolate->global_handles()->Create(*getter));
1291 }
1292
1293
~PromiseOnStack()1294 PromiseOnStack::~PromiseOnStack() {
1295 isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location());
1296 }
1297
1298
PromiseHandlePrologue(Handle<JSFunction> promise_getter)1299 void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) {
1300 PromiseOnStack* prev = thread_local_.promise_on_stack_;
1301 thread_local_.promise_on_stack_ =
1302 new PromiseOnStack(isolate_, prev, promise_getter);
1303 }
1304
1305
PromiseHandleEpilogue()1306 void Debug::PromiseHandleEpilogue() {
1307 if (thread_local_.promise_on_stack_ == NULL) return;
1308 PromiseOnStack* prev = thread_local_.promise_on_stack_->prev();
1309 delete thread_local_.promise_on_stack_;
1310 thread_local_.promise_on_stack_ = prev;
1311 }
1312
1313
GetPromiseForUncaughtException()1314 Handle<Object> Debug::GetPromiseForUncaughtException() {
1315 Handle<Object> undefined = isolate_->factory()->undefined_value();
1316 if (thread_local_.promise_on_stack_ == NULL) return undefined;
1317 Handle<JSFunction> promise_getter = thread_local_.promise_on_stack_->getter();
1318 StackHandler* promise_catch = thread_local_.promise_on_stack_->handler();
1319 // Find the top-most try-catch handler.
1320 StackHandler* handler = StackHandler::FromAddress(
1321 Isolate::handler(isolate_->thread_local_top()));
1322 while (handler != NULL && !handler->is_catch()) {
1323 handler = handler->next();
1324 }
1325 #ifdef DEBUG
1326 // Make sure that our promise catch handler is in the list of handlers,
1327 // even if it's not the top-most try-catch handler.
1328 StackHandler* temp = handler;
1329 while (temp != promise_catch && !temp->is_catch()) {
1330 temp = temp->next();
1331 CHECK(temp != NULL);
1332 }
1333 #endif // DEBUG
1334
1335 if (handler == promise_catch) {
1336 return Execution::Call(
1337 isolate_, promise_getter, undefined, 0, NULL).ToHandleChecked();
1338 }
1339 return undefined;
1340 }
1341
1342
PrepareStep(StepAction step_action,int step_count,StackFrame::Id frame_id)1343 void Debug::PrepareStep(StepAction step_action,
1344 int step_count,
1345 StackFrame::Id frame_id) {
1346 HandleScope scope(isolate_);
1347
1348 PrepareForBreakPoints();
1349
1350 ASSERT(in_debug_scope());
1351
1352 // Remember this step action and count.
1353 thread_local_.last_step_action_ = step_action;
1354 if (step_action == StepOut) {
1355 // For step out target frame will be found on the stack so there is no need
1356 // to set step counter for it. It's expected to always be 0 for StepOut.
1357 thread_local_.step_count_ = 0;
1358 } else {
1359 thread_local_.step_count_ = step_count;
1360 }
1361
1362 // Get the frame where the execution has stopped and skip the debug frame if
1363 // any. The debug frame will only be present if execution was stopped due to
1364 // hitting a break point. In other situations (e.g. unhandled exception) the
1365 // debug frame is not present.
1366 StackFrame::Id id = break_frame_id();
1367 if (id == StackFrame::NO_ID) {
1368 // If there is no JavaScript stack don't do anything.
1369 return;
1370 }
1371 if (frame_id != StackFrame::NO_ID) {
1372 id = frame_id;
1373 }
1374 JavaScriptFrameIterator frames_it(isolate_, id);
1375 JavaScriptFrame* frame = frames_it.frame();
1376
1377 // First of all ensure there is one-shot break points in the top handler
1378 // if any.
1379 FloodHandlerWithOneShot();
1380
1381 // If the function on the top frame is unresolved perform step out. This will
1382 // be the case when calling unknown functions and having the debugger stopped
1383 // in an unhandled exception.
1384 if (!frame->function()->IsJSFunction()) {
1385 // Step out: Find the calling JavaScript frame and flood it with
1386 // breakpoints.
1387 frames_it.Advance();
1388 // Fill the function to return to with one-shot break points.
1389 JSFunction* function = frames_it.frame()->function();
1390 FloodWithOneShot(Handle<JSFunction>(function));
1391 return;
1392 }
1393
1394 // Get the debug info (create it if it does not exist).
1395 Handle<JSFunction> function(frame->function());
1396 Handle<SharedFunctionInfo> shared(function->shared());
1397 if (!EnsureDebugInfo(shared, function)) {
1398 // Return if ensuring debug info failed.
1399 return;
1400 }
1401 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1402
1403 // Find the break location where execution has stopped.
1404 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1405 // pc points to the instruction after the current one, possibly a break
1406 // location as well. So the "- 1" to exclude it from the search.
1407 it.FindBreakLocationFromAddress(frame->pc() - 1);
1408
1409 // Compute whether or not the target is a call target.
1410 bool is_load_or_store = false;
1411 bool is_inline_cache_stub = false;
1412 bool is_at_restarted_function = false;
1413 Handle<Code> call_function_stub;
1414
1415 if (thread_local_.restarter_frame_function_pointer_ == NULL) {
1416 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1417 bool is_call_target = false;
1418 Address target = it.rinfo()->target_address();
1419 Code* code = Code::GetCodeFromTargetAddress(target);
1420 if (code->is_call_stub()) {
1421 is_call_target = true;
1422 }
1423 if (code->is_inline_cache_stub()) {
1424 is_inline_cache_stub = true;
1425 is_load_or_store = !is_call_target;
1426 }
1427
1428 // Check if target code is CallFunction stub.
1429 Code* maybe_call_function_stub = code;
1430 // If there is a breakpoint at this line look at the original code to
1431 // check if it is a CallFunction stub.
1432 if (it.IsDebugBreak()) {
1433 Address original_target = it.original_rinfo()->target_address();
1434 maybe_call_function_stub =
1435 Code::GetCodeFromTargetAddress(original_target);
1436 }
1437 if ((maybe_call_function_stub->kind() == Code::STUB &&
1438 maybe_call_function_stub->major_key() == CodeStub::CallFunction) ||
1439 maybe_call_function_stub->kind() == Code::CALL_IC) {
1440 // Save reference to the code as we may need it to find out arguments
1441 // count for 'step in' later.
1442 call_function_stub = Handle<Code>(maybe_call_function_stub);
1443 }
1444 }
1445 } else {
1446 is_at_restarted_function = true;
1447 }
1448
1449 // If this is the last break code target step out is the only possibility.
1450 if (it.IsExit() || step_action == StepOut) {
1451 if (step_action == StepOut) {
1452 // Skip step_count frames starting with the current one.
1453 while (step_count-- > 0 && !frames_it.done()) {
1454 frames_it.Advance();
1455 }
1456 } else {
1457 ASSERT(it.IsExit());
1458 frames_it.Advance();
1459 }
1460 // Skip builtin functions on the stack.
1461 while (!frames_it.done() && frames_it.frame()->function()->IsNative()) {
1462 frames_it.Advance();
1463 }
1464 // Step out: If there is a JavaScript caller frame, we need to
1465 // flood it with breakpoints.
1466 if (!frames_it.done()) {
1467 // Fill the function to return to with one-shot break points.
1468 JSFunction* function = frames_it.frame()->function();
1469 FloodWithOneShot(Handle<JSFunction>(function));
1470 // Set target frame pointer.
1471 ActivateStepOut(frames_it.frame());
1472 }
1473 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
1474 !call_function_stub.is_null() || is_at_restarted_function)
1475 || step_action == StepNext || step_action == StepMin) {
1476 // Step next or step min.
1477
1478 // Fill the current function with one-shot break points.
1479 FloodWithOneShot(function);
1480
1481 // Remember source position and frame to handle step next.
1482 thread_local_.last_statement_position_ =
1483 debug_info->code()->SourceStatementPosition(frame->pc());
1484 thread_local_.last_fp_ = frame->UnpaddedFP();
1485 } else {
1486 // If there's restarter frame on top of the stack, just get the pointer
1487 // to function which is going to be restarted.
1488 if (is_at_restarted_function) {
1489 Handle<JSFunction> restarted_function(
1490 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
1491 FloodWithOneShot(restarted_function);
1492 } else if (!call_function_stub.is_null()) {
1493 // If it's CallFunction stub ensure target function is compiled and flood
1494 // it with one shot breakpoints.
1495 bool is_call_ic = call_function_stub->kind() == Code::CALL_IC;
1496
1497 // Find out number of arguments from the stub minor key.
1498 // Reverse lookup required as the minor key cannot be retrieved
1499 // from the code object.
1500 Handle<Object> obj(
1501 isolate_->heap()->code_stubs()->SlowReverseLookup(
1502 *call_function_stub),
1503 isolate_);
1504 ASSERT(!obj.is_null());
1505 ASSERT(!(*obj)->IsUndefined());
1506 ASSERT(obj->IsSmi());
1507 // Get the STUB key and extract major and minor key.
1508 uint32_t key = Smi::cast(*obj)->value();
1509 // Argc in the stub is the number of arguments passed - not the
1510 // expected arguments of the called function.
1511 int call_function_arg_count = is_call_ic
1512 ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key))
1513 : CallFunctionStub::ExtractArgcFromMinorKey(
1514 CodeStub::MinorKeyFromKey(key));
1515
1516 ASSERT(is_call_ic ||
1517 call_function_stub->major_key() == CodeStub::MajorKeyFromKey(key));
1518
1519 // Find target function on the expression stack.
1520 // Expression stack looks like this (top to bottom):
1521 // argN
1522 // ...
1523 // arg0
1524 // Receiver
1525 // Function to call
1526 int expressions_count = frame->ComputeExpressionsCount();
1527 ASSERT(expressions_count - 2 - call_function_arg_count >= 0);
1528 Object* fun = frame->GetExpression(
1529 expressions_count - 2 - call_function_arg_count);
1530
1531 // Flood the actual target of call/apply.
1532 if (fun->IsJSFunction()) {
1533 Isolate* isolate = JSFunction::cast(fun)->GetIsolate();
1534 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply);
1535 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall);
1536 while (fun->IsJSFunction()) {
1537 Code* code = JSFunction::cast(fun)->shared()->code();
1538 if (code != apply && code != call) break;
1539 fun = frame->GetExpression(
1540 expressions_count - 1 - call_function_arg_count);
1541 }
1542 }
1543
1544 if (fun->IsJSFunction()) {
1545 Handle<JSFunction> js_function(JSFunction::cast(fun));
1546 if (js_function->shared()->bound()) {
1547 Debug::FloodBoundFunctionWithOneShot(js_function);
1548 } else if (!js_function->IsNative()) {
1549 // Don't step into builtins.
1550 // It will also compile target function if it's not compiled yet.
1551 FloodWithOneShot(js_function);
1552 }
1553 }
1554 }
1555
1556 // Fill the current function with one-shot break points even for step in on
1557 // a call target as the function called might be a native function for
1558 // which step in will not stop. It also prepares for stepping in
1559 // getters/setters.
1560 FloodWithOneShot(function);
1561
1562 if (is_load_or_store) {
1563 // Remember source position and frame to handle step in getter/setter. If
1564 // there is a custom getter/setter it will be handled in
1565 // Object::Get/SetPropertyWithCallback, otherwise the step action will be
1566 // propagated on the next Debug::Break.
1567 thread_local_.last_statement_position_ =
1568 debug_info->code()->SourceStatementPosition(frame->pc());
1569 thread_local_.last_fp_ = frame->UnpaddedFP();
1570 }
1571
1572 // Step in or Step in min
1573 it.PrepareStepIn(isolate_);
1574 ActivateStepIn(frame);
1575 }
1576 }
1577
1578
1579 // Check whether the current debug break should be reported to the debugger. It
1580 // is used to have step next and step in only report break back to the debugger
1581 // if on a different frame or in a different statement. In some situations
1582 // there will be several break points in the same statement when the code is
1583 // flooded with one-shot break points. This function helps to perform several
1584 // steps before reporting break back to the debugger.
StepNextContinue(BreakLocationIterator * break_location_iterator,JavaScriptFrame * frame)1585 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1586 JavaScriptFrame* frame) {
1587 // StepNext and StepOut shouldn't bring us deeper in code, so last frame
1588 // shouldn't be a parent of current frame.
1589 if (thread_local_.last_step_action_ == StepNext ||
1590 thread_local_.last_step_action_ == StepOut) {
1591 if (frame->fp() < thread_local_.last_fp_) return true;
1592 }
1593
1594 // If the step last action was step next or step in make sure that a new
1595 // statement is hit.
1596 if (thread_local_.last_step_action_ == StepNext ||
1597 thread_local_.last_step_action_ == StepIn) {
1598 // Never continue if returning from function.
1599 if (break_location_iterator->IsExit()) return false;
1600
1601 // Continue if we are still on the same frame and in the same statement.
1602 int current_statement_position =
1603 break_location_iterator->code()->SourceStatementPosition(frame->pc());
1604 return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1605 thread_local_.last_statement_position_ == current_statement_position;
1606 }
1607
1608 // No step next action - don't continue.
1609 return false;
1610 }
1611
1612
1613 // Check whether the code object at the specified address is a debug break code
1614 // object.
IsDebugBreak(Address addr)1615 bool Debug::IsDebugBreak(Address addr) {
1616 Code* code = Code::GetCodeFromTargetAddress(addr);
1617 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK;
1618 }
1619
1620
1621
1622
1623
1624 // Simple function for returning the source positions for active break points.
GetSourceBreakLocations(Handle<SharedFunctionInfo> shared,BreakPositionAlignment position_alignment)1625 Handle<Object> Debug::GetSourceBreakLocations(
1626 Handle<SharedFunctionInfo> shared,
1627 BreakPositionAlignment position_alignment) {
1628 Isolate* isolate = shared->GetIsolate();
1629 Heap* heap = isolate->heap();
1630 if (!HasDebugInfo(shared)) {
1631 return Handle<Object>(heap->undefined_value(), isolate);
1632 }
1633 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1634 if (debug_info->GetBreakPointCount() == 0) {
1635 return Handle<Object>(heap->undefined_value(), isolate);
1636 }
1637 Handle<FixedArray> locations =
1638 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1639 int count = 0;
1640 for (int i = 0; i < debug_info->break_points()->length(); i++) {
1641 if (!debug_info->break_points()->get(i)->IsUndefined()) {
1642 BreakPointInfo* break_point_info =
1643 BreakPointInfo::cast(debug_info->break_points()->get(i));
1644 if (break_point_info->GetBreakPointCount() > 0) {
1645 Smi* position;
1646 switch (position_alignment) {
1647 case STATEMENT_ALIGNED:
1648 position = break_point_info->statement_position();
1649 break;
1650 case BREAK_POSITION_ALIGNED:
1651 position = break_point_info->source_position();
1652 break;
1653 default:
1654 UNREACHABLE();
1655 position = break_point_info->statement_position();
1656 }
1657
1658 locations->set(count++, position);
1659 }
1660 }
1661 }
1662 return locations;
1663 }
1664
1665
1666 // Handle stepping into a function.
HandleStepIn(Handle<JSFunction> function,Handle<Object> holder,Address fp,bool is_constructor)1667 void Debug::HandleStepIn(Handle<JSFunction> function,
1668 Handle<Object> holder,
1669 Address fp,
1670 bool is_constructor) {
1671 Isolate* isolate = function->GetIsolate();
1672 // If the frame pointer is not supplied by the caller find it.
1673 if (fp == 0) {
1674 StackFrameIterator it(isolate);
1675 it.Advance();
1676 // For constructor functions skip another frame.
1677 if (is_constructor) {
1678 ASSERT(it.frame()->is_construct());
1679 it.Advance();
1680 }
1681 fp = it.frame()->fp();
1682 }
1683
1684 // Flood the function with one-shot break points if it is called from where
1685 // step into was requested.
1686 if (fp == thread_local_.step_into_fp_) {
1687 if (function->shared()->bound()) {
1688 // Handle Function.prototype.bind
1689 Debug::FloodBoundFunctionWithOneShot(function);
1690 } else if (!function->IsNative()) {
1691 // Don't allow step into functions in the native context.
1692 if (function->shared()->code() ==
1693 isolate->builtins()->builtin(Builtins::kFunctionApply) ||
1694 function->shared()->code() ==
1695 isolate->builtins()->builtin(Builtins::kFunctionCall)) {
1696 // Handle function.apply and function.call separately to flood the
1697 // function to be called and not the code for Builtins::FunctionApply or
1698 // Builtins::FunctionCall. The receiver of call/apply is the target
1699 // function.
1700 if (!holder.is_null() && holder->IsJSFunction()) {
1701 Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
1702 if (!js_function->IsNative()) {
1703 Debug::FloodWithOneShot(js_function);
1704 } else if (js_function->shared()->bound()) {
1705 // Handle Function.prototype.bind
1706 Debug::FloodBoundFunctionWithOneShot(js_function);
1707 }
1708 }
1709 } else {
1710 Debug::FloodWithOneShot(function);
1711 }
1712 }
1713 }
1714 }
1715
1716
ClearStepping()1717 void Debug::ClearStepping() {
1718 // Clear the various stepping setup.
1719 ClearOneShot();
1720 ClearStepIn();
1721 ClearStepOut();
1722 ClearStepNext();
1723
1724 // Clear multiple step counter.
1725 thread_local_.step_count_ = 0;
1726 }
1727
1728
1729 // Clears all the one-shot break points that are currently set. Normally this
1730 // function is called each time a break point is hit as one shot break points
1731 // are used to support stepping.
ClearOneShot()1732 void Debug::ClearOneShot() {
1733 // The current implementation just runs through all the breakpoints. When the
1734 // last break point for a function is removed that function is automatically
1735 // removed from the list.
1736
1737 DebugInfoListNode* node = debug_info_list_;
1738 while (node != NULL) {
1739 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1740 while (!it.Done()) {
1741 it.ClearOneShot();
1742 it.Next();
1743 }
1744 node = node->next();
1745 }
1746 }
1747
1748
ActivateStepIn(StackFrame * frame)1749 void Debug::ActivateStepIn(StackFrame* frame) {
1750 ASSERT(!StepOutActive());
1751 thread_local_.step_into_fp_ = frame->UnpaddedFP();
1752 }
1753
1754
ClearStepIn()1755 void Debug::ClearStepIn() {
1756 thread_local_.step_into_fp_ = 0;
1757 }
1758
1759
ActivateStepOut(StackFrame * frame)1760 void Debug::ActivateStepOut(StackFrame* frame) {
1761 ASSERT(!StepInActive());
1762 thread_local_.step_out_fp_ = frame->UnpaddedFP();
1763 }
1764
1765
ClearStepOut()1766 void Debug::ClearStepOut() {
1767 thread_local_.step_out_fp_ = 0;
1768 }
1769
1770
ClearStepNext()1771 void Debug::ClearStepNext() {
1772 thread_local_.last_step_action_ = StepNone;
1773 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1774 thread_local_.last_fp_ = 0;
1775 }
1776
1777
CollectActiveFunctionsFromThread(Isolate * isolate,ThreadLocalTop * top,List<Handle<JSFunction>> * active_functions,Object * active_code_marker)1778 static void CollectActiveFunctionsFromThread(
1779 Isolate* isolate,
1780 ThreadLocalTop* top,
1781 List<Handle<JSFunction> >* active_functions,
1782 Object* active_code_marker) {
1783 // Find all non-optimized code functions with activation frames
1784 // on the stack. This includes functions which have optimized
1785 // activations (including inlined functions) on the stack as the
1786 // non-optimized code is needed for the lazy deoptimization.
1787 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1788 JavaScriptFrame* frame = it.frame();
1789 if (frame->is_optimized()) {
1790 List<JSFunction*> functions(FLAG_max_inlining_levels + 1);
1791 frame->GetFunctions(&functions);
1792 for (int i = 0; i < functions.length(); i++) {
1793 JSFunction* function = functions[i];
1794 active_functions->Add(Handle<JSFunction>(function));
1795 function->shared()->code()->set_gc_metadata(active_code_marker);
1796 }
1797 } else if (frame->function()->IsJSFunction()) {
1798 JSFunction* function = frame->function();
1799 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1800 active_functions->Add(Handle<JSFunction>(function));
1801 function->shared()->code()->set_gc_metadata(active_code_marker);
1802 }
1803 }
1804 }
1805
1806
1807 // Figure out how many bytes of "pc_offset" correspond to actual code by
1808 // subtracting off the bytes that correspond to constant/veneer pools. See
1809 // Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this
1810 // is only useful for architectures using constant pools or veneer pools.
ComputeCodeOffsetFromPcOffset(Code * code,int pc_offset)1811 static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) {
1812 ASSERT_EQ(code->kind(), Code::FUNCTION);
1813 ASSERT(!code->has_debug_break_slots());
1814 ASSERT_LE(0, pc_offset);
1815 ASSERT_LT(pc_offset, code->instruction_end() - code->instruction_start());
1816
1817 int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1818 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1819 byte *pc = code->instruction_start() + pc_offset;
1820 int code_offset = pc_offset;
1821 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1822 RelocInfo* info = it.rinfo();
1823 if (info->pc() >= pc) break;
1824 ASSERT(RelocInfo::IsConstPool(info->rmode()));
1825 code_offset -= static_cast<int>(info->data());
1826 ASSERT_LE(0, code_offset);
1827 }
1828
1829 return code_offset;
1830 }
1831
1832
1833 // The inverse of ComputeCodeOffsetFromPcOffset.
ComputePcOffsetFromCodeOffset(Code * code,int code_offset)1834 static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) {
1835 ASSERT_EQ(code->kind(), Code::FUNCTION);
1836
1837 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
1838 RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1839 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1840 int reloc = 0;
1841 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1842 RelocInfo* info = it.rinfo();
1843 if (info->pc() - code->instruction_start() - reloc >= code_offset) break;
1844 if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
1845 reloc += Assembler::kDebugBreakSlotLength;
1846 } else {
1847 ASSERT(RelocInfo::IsConstPool(info->rmode()));
1848 reloc += static_cast<int>(info->data());
1849 }
1850 }
1851
1852 int pc_offset = code_offset + reloc;
1853
1854 ASSERT_LT(code->instruction_start() + pc_offset, code->instruction_end());
1855
1856 return pc_offset;
1857 }
1858
1859
RedirectActivationsToRecompiledCodeOnThread(Isolate * isolate,ThreadLocalTop * top)1860 static void RedirectActivationsToRecompiledCodeOnThread(
1861 Isolate* isolate,
1862 ThreadLocalTop* top) {
1863 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1864 JavaScriptFrame* frame = it.frame();
1865
1866 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue;
1867
1868 JSFunction* function = frame->function();
1869
1870 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1871
1872 Handle<Code> frame_code(frame->LookupCode());
1873 if (frame_code->has_debug_break_slots()) continue;
1874
1875 Handle<Code> new_code(function->shared()->code());
1876 if (new_code->kind() != Code::FUNCTION ||
1877 !new_code->has_debug_break_slots()) {
1878 continue;
1879 }
1880
1881 int old_pc_offset =
1882 static_cast<int>(frame->pc() - frame_code->instruction_start());
1883 int code_offset = ComputeCodeOffsetFromPcOffset(*frame_code, old_pc_offset);
1884 int new_pc_offset = ComputePcOffsetFromCodeOffset(*new_code, code_offset);
1885
1886 // Compute the equivalent pc in the new code.
1887 byte* new_pc = new_code->instruction_start() + new_pc_offset;
1888
1889 if (FLAG_trace_deopt) {
1890 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1891 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1892 "for debugging, "
1893 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
1894 reinterpret_cast<intptr_t>(
1895 frame_code->instruction_start()),
1896 reinterpret_cast<intptr_t>(
1897 frame_code->instruction_start()) +
1898 frame_code->instruction_size(),
1899 frame_code->instruction_size(),
1900 reinterpret_cast<intptr_t>(new_code->instruction_start()),
1901 reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1902 new_code->instruction_size(),
1903 new_code->instruction_size(),
1904 reinterpret_cast<intptr_t>(frame->pc()),
1905 reinterpret_cast<intptr_t>(new_pc));
1906 }
1907
1908 // Patch the return address to return into the code with
1909 // debug break slots.
1910 frame->set_pc(new_pc);
1911 }
1912 }
1913
1914
1915 class ActiveFunctionsCollector : public ThreadVisitor {
1916 public:
ActiveFunctionsCollector(List<Handle<JSFunction>> * active_functions,Object * active_code_marker)1917 explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
1918 Object* active_code_marker)
1919 : active_functions_(active_functions),
1920 active_code_marker_(active_code_marker) { }
1921
VisitThread(Isolate * isolate,ThreadLocalTop * top)1922 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1923 CollectActiveFunctionsFromThread(isolate,
1924 top,
1925 active_functions_,
1926 active_code_marker_);
1927 }
1928
1929 private:
1930 List<Handle<JSFunction> >* active_functions_;
1931 Object* active_code_marker_;
1932 };
1933
1934
1935 class ActiveFunctionsRedirector : public ThreadVisitor {
1936 public:
VisitThread(Isolate * isolate,ThreadLocalTop * top)1937 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1938 RedirectActivationsToRecompiledCodeOnThread(isolate, top);
1939 }
1940 };
1941
1942
EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function)1943 static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) {
1944 if (function->code()->kind() == Code::FUNCTION &&
1945 function->code()->has_debug_break_slots()) {
1946 // Nothing to do. Function code already had debug break slots.
1947 return;
1948 }
1949 // Make sure that the shared full code is compiled with debug
1950 // break slots.
1951 if (!function->shared()->code()->has_debug_break_slots()) {
1952 MaybeHandle<Code> code = Compiler::GetCodeForDebugging(function);
1953 // Recompilation can fail. In that case leave the code as it was.
1954 if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked());
1955 } else {
1956 // Simply use shared code if it has debug break slots.
1957 function->ReplaceCode(function->shared()->code());
1958 }
1959 }
1960
1961
RecompileAndRelocateSuspendedGenerators(const List<Handle<JSGeneratorObject>> & generators)1962 static void RecompileAndRelocateSuspendedGenerators(
1963 const List<Handle<JSGeneratorObject> > &generators) {
1964 for (int i = 0; i < generators.length(); i++) {
1965 Handle<JSFunction> fun(generators[i]->function());
1966
1967 EnsureFunctionHasDebugBreakSlots(fun);
1968
1969 int code_offset = generators[i]->continuation();
1970 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset);
1971 generators[i]->set_continuation(pc_offset);
1972 }
1973 }
1974
1975
PrepareForBreakPoints()1976 void Debug::PrepareForBreakPoints() {
1977 // If preparing for the first break point make sure to deoptimize all
1978 // functions as debugging does not work with optimized code.
1979 if (!has_break_points_) {
1980 if (isolate_->concurrent_recompilation_enabled()) {
1981 isolate_->optimizing_compiler_thread()->Flush();
1982 }
1983
1984 Deoptimizer::DeoptimizeAll(isolate_);
1985
1986 Handle<Code> lazy_compile = isolate_->builtins()->CompileUnoptimized();
1987
1988 // There will be at least one break point when we are done.
1989 has_break_points_ = true;
1990
1991 // Keep the list of activated functions in a handlified list as it
1992 // is used both in GC and non-GC code.
1993 List<Handle<JSFunction> > active_functions(100);
1994
1995 // A list of all suspended generators.
1996 List<Handle<JSGeneratorObject> > suspended_generators;
1997
1998 // A list of all generator functions. We need to recompile all functions,
1999 // but we don't know until after visiting the whole heap which generator
2000 // functions have suspended activations and which do not. As in the case of
2001 // functions with activations on the stack, we need to be careful with
2002 // generator functions with suspended activations because although they
2003 // should be recompiled, recompilation can fail, and we need to avoid
2004 // leaving the heap in an inconsistent state.
2005 //
2006 // We could perhaps avoid this list and instead re-use the GC metadata
2007 // links.
2008 List<Handle<JSFunction> > generator_functions;
2009
2010 {
2011 // We are going to iterate heap to find all functions without
2012 // debug break slots.
2013 Heap* heap = isolate_->heap();
2014 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
2015 "preparing for breakpoints");
2016 HeapIterator iterator(heap);
2017
2018 // Ensure no GC in this scope as we are going to use gc_metadata
2019 // field in the Code object to mark active functions.
2020 DisallowHeapAllocation no_allocation;
2021
2022 Object* active_code_marker = heap->the_hole_value();
2023
2024 CollectActiveFunctionsFromThread(isolate_,
2025 isolate_->thread_local_top(),
2026 &active_functions,
2027 active_code_marker);
2028 ActiveFunctionsCollector active_functions_collector(&active_functions,
2029 active_code_marker);
2030 isolate_->thread_manager()->IterateArchivedThreads(
2031 &active_functions_collector);
2032
2033 // Scan the heap for all non-optimized functions which have no
2034 // debug break slots and are not active or inlined into an active
2035 // function and mark them for lazy compilation.
2036 HeapObject* obj = NULL;
2037 while (((obj = iterator.next()) != NULL)) {
2038 if (obj->IsJSFunction()) {
2039 JSFunction* function = JSFunction::cast(obj);
2040 SharedFunctionInfo* shared = function->shared();
2041
2042 if (!shared->allows_lazy_compilation()) continue;
2043 if (!shared->script()->IsScript()) continue;
2044 if (function->IsNative()) continue;
2045 if (shared->code()->gc_metadata() == active_code_marker) continue;
2046
2047 if (shared->is_generator()) {
2048 generator_functions.Add(Handle<JSFunction>(function, isolate_));
2049 continue;
2050 }
2051
2052 Code::Kind kind = function->code()->kind();
2053 if (kind == Code::FUNCTION &&
2054 !function->code()->has_debug_break_slots()) {
2055 function->ReplaceCode(*lazy_compile);
2056 function->shared()->ReplaceCode(*lazy_compile);
2057 } else if (kind == Code::BUILTIN &&
2058 (function->IsInOptimizationQueue() ||
2059 function->IsMarkedForOptimization() ||
2060 function->IsMarkedForConcurrentOptimization())) {
2061 // Abort in-flight compilation.
2062 Code* shared_code = function->shared()->code();
2063 if (shared_code->kind() == Code::FUNCTION &&
2064 shared_code->has_debug_break_slots()) {
2065 function->ReplaceCode(shared_code);
2066 } else {
2067 function->ReplaceCode(*lazy_compile);
2068 function->shared()->ReplaceCode(*lazy_compile);
2069 }
2070 }
2071 } else if (obj->IsJSGeneratorObject()) {
2072 JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
2073 if (!gen->is_suspended()) continue;
2074
2075 JSFunction* fun = gen->function();
2076 ASSERT_EQ(fun->code()->kind(), Code::FUNCTION);
2077 if (fun->code()->has_debug_break_slots()) continue;
2078
2079 int pc_offset = gen->continuation();
2080 ASSERT_LT(0, pc_offset);
2081
2082 int code_offset =
2083 ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset);
2084
2085 // This will be fixed after we recompile the functions.
2086 gen->set_continuation(code_offset);
2087
2088 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_));
2089 }
2090 }
2091
2092 // Clear gc_metadata field.
2093 for (int i = 0; i < active_functions.length(); i++) {
2094 Handle<JSFunction> function = active_functions[i];
2095 function->shared()->code()->set_gc_metadata(Smi::FromInt(0));
2096 }
2097 }
2098
2099 // Recompile generator functions that have suspended activations, and
2100 // relocate those activations.
2101 RecompileAndRelocateSuspendedGenerators(suspended_generators);
2102
2103 // Mark generator functions that didn't have suspended activations for lazy
2104 // recompilation. Note that this set does not include any active functions.
2105 for (int i = 0; i < generator_functions.length(); i++) {
2106 Handle<JSFunction> &function = generator_functions[i];
2107 if (function->code()->kind() != Code::FUNCTION) continue;
2108 if (function->code()->has_debug_break_slots()) continue;
2109 function->ReplaceCode(*lazy_compile);
2110 function->shared()->ReplaceCode(*lazy_compile);
2111 }
2112
2113 // Now recompile all functions with activation frames and and
2114 // patch the return address to run in the new compiled code. It could be
2115 // that some active functions were recompiled already by the suspended
2116 // generator recompilation pass above; a generator with suspended
2117 // activations could also have active activations. That's fine.
2118 for (int i = 0; i < active_functions.length(); i++) {
2119 Handle<JSFunction> function = active_functions[i];
2120 Handle<SharedFunctionInfo> shared(function->shared());
2121
2122 // If recompilation is not possible just skip it.
2123 if (shared->is_toplevel()) continue;
2124 if (!shared->allows_lazy_compilation()) continue;
2125 if (shared->code()->kind() == Code::BUILTIN) continue;
2126
2127 EnsureFunctionHasDebugBreakSlots(function);
2128 }
2129
2130 RedirectActivationsToRecompiledCodeOnThread(isolate_,
2131 isolate_->thread_local_top());
2132
2133 ActiveFunctionsRedirector active_functions_redirector;
2134 isolate_->thread_manager()->IterateArchivedThreads(
2135 &active_functions_redirector);
2136 }
2137 }
2138
2139
FindSharedFunctionInfoInScript(Handle<Script> script,int position)2140 Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2141 int position) {
2142 // Iterate the heap looking for SharedFunctionInfo generated from the
2143 // script. The inner most SharedFunctionInfo containing the source position
2144 // for the requested break point is found.
2145 // NOTE: This might require several heap iterations. If the SharedFunctionInfo
2146 // which is found is not compiled it is compiled and the heap is iterated
2147 // again as the compilation might create inner functions from the newly
2148 // compiled function and the actual requested break point might be in one of
2149 // these functions.
2150 // NOTE: The below fix-point iteration depends on all functions that cannot be
2151 // compiled lazily without a context to not be compiled at all. Compilation
2152 // will be triggered at points where we do not need a context.
2153 bool done = false;
2154 // The current candidate for the source position:
2155 int target_start_position = RelocInfo::kNoPosition;
2156 Handle<JSFunction> target_function;
2157 Handle<SharedFunctionInfo> target;
2158 Heap* heap = isolate_->heap();
2159 while (!done) {
2160 { // Extra scope for iterator.
2161 HeapIterator iterator(heap);
2162 for (HeapObject* obj = iterator.next();
2163 obj != NULL; obj = iterator.next()) {
2164 bool found_next_candidate = false;
2165 Handle<JSFunction> function;
2166 Handle<SharedFunctionInfo> shared;
2167 if (obj->IsJSFunction()) {
2168 function = Handle<JSFunction>(JSFunction::cast(obj));
2169 shared = Handle<SharedFunctionInfo>(function->shared());
2170 ASSERT(shared->allows_lazy_compilation() || shared->is_compiled());
2171 found_next_candidate = true;
2172 } else if (obj->IsSharedFunctionInfo()) {
2173 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj));
2174 // Skip functions that we cannot compile lazily without a context,
2175 // which is not available here, because there is no closure.
2176 found_next_candidate = shared->is_compiled() ||
2177 shared->allows_lazy_compilation_without_context();
2178 }
2179 if (!found_next_candidate) continue;
2180 if (shared->script() == *script) {
2181 // If the SharedFunctionInfo found has the requested script data and
2182 // contains the source position it is a candidate.
2183 int start_position = shared->function_token_position();
2184 if (start_position == RelocInfo::kNoPosition) {
2185 start_position = shared->start_position();
2186 }
2187 if (start_position <= position &&
2188 position <= shared->end_position()) {
2189 // If there is no candidate or this function is within the current
2190 // candidate this is the new candidate.
2191 if (target.is_null()) {
2192 target_start_position = start_position;
2193 target_function = function;
2194 target = shared;
2195 } else {
2196 if (target_start_position == start_position &&
2197 shared->end_position() == target->end_position()) {
2198 // If a top-level function contains only one function
2199 // declaration the source for the top-level and the function
2200 // is the same. In that case prefer the non top-level function.
2201 if (!shared->is_toplevel()) {
2202 target_start_position = start_position;
2203 target_function = function;
2204 target = shared;
2205 }
2206 } else if (target_start_position <= start_position &&
2207 shared->end_position() <= target->end_position()) {
2208 // This containment check includes equality as a function
2209 // inside a top-level function can share either start or end
2210 // position with the top-level function.
2211 target_start_position = start_position;
2212 target_function = function;
2213 target = shared;
2214 }
2215 }
2216 }
2217 }
2218 } // End for loop.
2219 } // End no-allocation scope.
2220
2221 if (target.is_null()) return heap->undefined_value();
2222
2223 // There will be at least one break point when we are done.
2224 has_break_points_ = true;
2225
2226 // If the candidate found is compiled we are done.
2227 done = target->is_compiled();
2228 if (!done) {
2229 // If the candidate is not compiled, compile it to reveal any inner
2230 // functions which might contain the requested source position. This
2231 // will compile all inner functions that cannot be compiled without a
2232 // context, because Compiler::BuildFunctionInfo checks whether the
2233 // debugger is active.
2234 MaybeHandle<Code> maybe_result = target_function.is_null()
2235 ? Compiler::GetUnoptimizedCode(target)
2236 : Compiler::GetUnoptimizedCode(target_function);
2237 if (maybe_result.is_null()) return isolate_->heap()->undefined_value();
2238 }
2239 } // End while loop.
2240
2241 return *target;
2242 }
2243
2244
2245 // Ensures the debug information is present for shared.
EnsureDebugInfo(Handle<SharedFunctionInfo> shared,Handle<JSFunction> function)2246 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2247 Handle<JSFunction> function) {
2248 Isolate* isolate = shared->GetIsolate();
2249
2250 // Return if we already have the debug info for shared.
2251 if (HasDebugInfo(shared)) {
2252 ASSERT(shared->is_compiled());
2253 return true;
2254 }
2255
2256 // There will be at least one break point when we are done.
2257 has_break_points_ = true;
2258
2259 // Ensure function is compiled. Return false if this failed.
2260 if (!function.is_null() &&
2261 !Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) {
2262 return false;
2263 }
2264
2265 // Create the debug info object.
2266 Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared);
2267
2268 // Add debug info to the list.
2269 DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
2270 node->set_next(debug_info_list_);
2271 debug_info_list_ = node;
2272
2273 return true;
2274 }
2275
2276
RemoveDebugInfo(Handle<DebugInfo> debug_info)2277 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
2278 ASSERT(debug_info_list_ != NULL);
2279 // Run through the debug info objects to find this one and remove it.
2280 DebugInfoListNode* prev = NULL;
2281 DebugInfoListNode* current = debug_info_list_;
2282 while (current != NULL) {
2283 if (*current->debug_info() == *debug_info) {
2284 // Unlink from list. If prev is NULL we are looking at the first element.
2285 if (prev == NULL) {
2286 debug_info_list_ = current->next();
2287 } else {
2288 prev->set_next(current->next());
2289 }
2290 current->debug_info()->shared()->set_debug_info(
2291 isolate_->heap()->undefined_value());
2292 delete current;
2293
2294 // If there are no more debug info objects there are not more break
2295 // points.
2296 has_break_points_ = debug_info_list_ != NULL;
2297
2298 return;
2299 }
2300 // Move to next in list.
2301 prev = current;
2302 current = current->next();
2303 }
2304 UNREACHABLE();
2305 }
2306
2307
SetAfterBreakTarget(JavaScriptFrame * frame)2308 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
2309 after_break_target_ = NULL;
2310
2311 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job.
2312
2313 HandleScope scope(isolate_);
2314 PrepareForBreakPoints();
2315
2316 // Get the executing function in which the debug break occurred.
2317 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2318 Handle<SharedFunctionInfo> shared(function->shared());
2319 if (!EnsureDebugInfo(shared, function)) {
2320 // Return if we failed to retrieve the debug info.
2321 return;
2322 }
2323 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2324 Handle<Code> code(debug_info->code());
2325 Handle<Code> original_code(debug_info->original_code());
2326 #ifdef DEBUG
2327 // Get the code which is actually executing.
2328 Handle<Code> frame_code(frame->LookupCode());
2329 ASSERT(frame_code.is_identical_to(code));
2330 #endif
2331
2332 // Find the call address in the running code. This address holds the call to
2333 // either a DebugBreakXXX or to the debug break return entry code if the
2334 // break point is still active after processing the break point.
2335 Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset;
2336
2337 // Check if the location is at JS exit or debug break slot.
2338 bool at_js_return = false;
2339 bool break_at_js_return_active = false;
2340 bool at_debug_break_slot = false;
2341 RelocIterator it(debug_info->code());
2342 while (!it.done() && !at_js_return && !at_debug_break_slot) {
2343 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2344 at_js_return = (it.rinfo()->pc() ==
2345 addr - Assembler::kPatchReturnSequenceAddressOffset);
2346 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
2347 }
2348 if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2349 at_debug_break_slot = (it.rinfo()->pc() ==
2350 addr - Assembler::kPatchDebugBreakSlotAddressOffset);
2351 }
2352 it.next();
2353 }
2354
2355 // Handle the jump to continue execution after break point depending on the
2356 // break location.
2357 if (at_js_return) {
2358 // If the break point as return is still active jump to the corresponding
2359 // place in the original code. If not the break point was removed during
2360 // break point processing.
2361 if (break_at_js_return_active) {
2362 addr += original_code->instruction_start() - code->instruction_start();
2363 }
2364
2365 // Move back to where the call instruction sequence started.
2366 after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset;
2367 } else if (at_debug_break_slot) {
2368 // Address of where the debug break slot starts.
2369 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
2370
2371 // Continue just after the slot.
2372 after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
2373 } else if (IsDebugBreak(Assembler::target_address_at(addr, *code))) {
2374 // We now know that there is still a debug break call at the target address,
2375 // so the break point is still there and the original code will hold the
2376 // address to jump to in order to complete the call which is replaced by a
2377 // call to DebugBreakXXX.
2378
2379 // Find the corresponding address in the original code.
2380 addr += original_code->instruction_start() - code->instruction_start();
2381
2382 // Install jump to the call address in the original code. This will be the
2383 // call which was overwritten by the call to DebugBreakXXX.
2384 after_break_target_ = Assembler::target_address_at(addr, *original_code);
2385 } else {
2386 // There is no longer a break point present. Don't try to look in the
2387 // original code as the running code will have the right address. This takes
2388 // care of the case where the last break point is removed from the function
2389 // and therefore no "original code" is available.
2390 after_break_target_ = Assembler::target_address_at(addr, *code);
2391 }
2392 }
2393
2394
IsBreakAtReturn(JavaScriptFrame * frame)2395 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
2396 HandleScope scope(isolate_);
2397
2398 // If there are no break points this cannot be break at return, as
2399 // the debugger statement and stack guard bebug break cannot be at
2400 // return.
2401 if (!has_break_points_) {
2402 return false;
2403 }
2404
2405 PrepareForBreakPoints();
2406
2407 // Get the executing function in which the debug break occurred.
2408 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2409 Handle<SharedFunctionInfo> shared(function->shared());
2410 if (!EnsureDebugInfo(shared, function)) {
2411 // Return if we failed to retrieve the debug info.
2412 return false;
2413 }
2414 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2415 Handle<Code> code(debug_info->code());
2416 #ifdef DEBUG
2417 // Get the code which is actually executing.
2418 Handle<Code> frame_code(frame->LookupCode());
2419 ASSERT(frame_code.is_identical_to(code));
2420 #endif
2421
2422 // Find the call address in the running code.
2423 Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset;
2424
2425 // Check if the location is at JS return.
2426 RelocIterator it(debug_info->code());
2427 while (!it.done()) {
2428 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2429 return (it.rinfo()->pc() ==
2430 addr - Assembler::kPatchReturnSequenceAddressOffset);
2431 }
2432 it.next();
2433 }
2434 return false;
2435 }
2436
2437
FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,LiveEdit::FrameDropMode mode,Object ** restarter_frame_function_pointer)2438 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
2439 LiveEdit::FrameDropMode mode,
2440 Object** restarter_frame_function_pointer) {
2441 if (mode != LiveEdit::CURRENTLY_SET_MODE) {
2442 thread_local_.frame_drop_mode_ = mode;
2443 }
2444 thread_local_.break_frame_id_ = new_break_frame_id;
2445 thread_local_.restarter_frame_function_pointer_ =
2446 restarter_frame_function_pointer;
2447 }
2448
2449
IsDebugGlobal(GlobalObject * global)2450 bool Debug::IsDebugGlobal(GlobalObject* global) {
2451 return is_loaded() && global == debug_context()->global_object();
2452 }
2453
2454
ClearMirrorCache()2455 void Debug::ClearMirrorCache() {
2456 PostponeInterruptsScope postpone(isolate_);
2457 HandleScope scope(isolate_);
2458 AssertDebugContext();
2459 Factory* factory = isolate_->factory();
2460 JSObject::SetProperty(isolate_->global_object(),
2461 factory->NewStringFromAsciiChecked("next_handle_"),
2462 handle(Smi::FromInt(0), isolate_),
2463 NONE,
2464 SLOPPY).Check();
2465 JSObject::SetProperty(isolate_->global_object(),
2466 factory->NewStringFromAsciiChecked("mirror_cache_"),
2467 factory->NewJSArray(0, FAST_ELEMENTS),
2468 NONE,
2469 SLOPPY).Check();
2470 }
2471
2472
GetLoadedScripts()2473 Handle<FixedArray> Debug::GetLoadedScripts() {
2474 // Create and fill the script cache when the loaded scripts is requested for
2475 // the first time.
2476 if (script_cache_ == NULL) script_cache_ = new ScriptCache(isolate_);
2477
2478 // Perform GC to get unreferenced scripts evicted from the cache before
2479 // returning the content.
2480 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
2481 "Debug::GetLoadedScripts");
2482
2483 // Get the scripts from the cache.
2484 return script_cache_->GetScripts();
2485 }
2486
2487
RecordEvalCaller(Handle<Script> script)2488 void Debug::RecordEvalCaller(Handle<Script> script) {
2489 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
2490 // For eval scripts add information on the function from which eval was
2491 // called.
2492 StackTraceFrameIterator it(script->GetIsolate());
2493 if (!it.done()) {
2494 script->set_eval_from_shared(it.frame()->function()->shared());
2495 Code* code = it.frame()->LookupCode();
2496 int offset = static_cast<int>(
2497 it.frame()->pc() - code->instruction_start());
2498 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
2499 }
2500 }
2501
2502
AfterGarbageCollection()2503 void Debug::AfterGarbageCollection() {
2504 // Generate events for collected scripts.
2505 if (script_cache_ != NULL) {
2506 script_cache_->ProcessCollectedScripts();
2507 }
2508 }
2509
2510
MakeJSObject(const char * constructor_name,int argc,Handle<Object> argv[])2511 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name,
2512 int argc,
2513 Handle<Object> argv[]) {
2514 AssertDebugContext();
2515 // Create the execution state object.
2516 Handle<Object> constructor = Object::GetProperty(
2517 isolate_, isolate_->global_object(), constructor_name).ToHandleChecked();
2518 ASSERT(constructor->IsJSFunction());
2519 if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
2520 // We do not handle interrupts here. In particular, termination interrupts.
2521 PostponeInterruptsScope no_interrupts(isolate_);
2522 return Execution::TryCall(Handle<JSFunction>::cast(constructor),
2523 Handle<JSObject>(debug_context()->global_object()),
2524 argc,
2525 argv);
2526 }
2527
2528
MakeExecutionState()2529 MaybeHandle<Object> Debug::MakeExecutionState() {
2530 // Create the execution state object.
2531 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
2532 return MakeJSObject("MakeExecutionState", ARRAY_SIZE(argv), argv);
2533 }
2534
2535
MakeBreakEvent(Handle<Object> break_points_hit)2536 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
2537 Handle<Object> exec_state;
2538 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
2539 // Create the new break event object.
2540 Handle<Object> argv[] = { exec_state, break_points_hit };
2541 return MakeJSObject("MakeBreakEvent", ARRAY_SIZE(argv), argv);
2542 }
2543
2544
MakeExceptionEvent(Handle<Object> exception,bool uncaught,Handle<Object> promise)2545 MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
2546 bool uncaught,
2547 Handle<Object> promise) {
2548 Handle<Object> exec_state;
2549 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
2550 // Create the new exception event object.
2551 Handle<Object> argv[] = { exec_state,
2552 exception,
2553 isolate_->factory()->ToBoolean(uncaught),
2554 promise };
2555 return MakeJSObject("MakeExceptionEvent", ARRAY_SIZE(argv), argv);
2556 }
2557
2558
MakeCompileEvent(Handle<Script> script,bool before)2559 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
2560 bool before) {
2561 Handle<Object> exec_state;
2562 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
2563 // Create the compile event object.
2564 Handle<Object> script_wrapper = Script::GetWrapper(script);
2565 Handle<Object> argv[] = { exec_state,
2566 script_wrapper,
2567 isolate_->factory()->ToBoolean(before) };
2568 return MakeJSObject("MakeCompileEvent", ARRAY_SIZE(argv), argv);
2569 }
2570
2571
MakeScriptCollectedEvent(int id)2572 MaybeHandle<Object> Debug::MakeScriptCollectedEvent(int id) {
2573 Handle<Object> exec_state;
2574 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
2575 // Create the script collected event object.
2576 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_);
2577 Handle<Object> argv[] = { exec_state, id_object };
2578 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv);
2579 }
2580
2581
OnException(Handle<Object> exception,bool uncaught)2582 void Debug::OnException(Handle<Object> exception, bool uncaught) {
2583 if (in_debug_scope() || ignore_events()) return;
2584
2585 HandleScope scope(isolate_);
2586 Handle<Object> promise = GetPromiseForUncaughtException();
2587 uncaught |= !promise->IsUndefined();
2588
2589 // Bail out if exception breaks are not active
2590 if (uncaught) {
2591 // Uncaught exceptions are reported by either flags.
2592 if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
2593 } else {
2594 // Caught exceptions are reported is activated.
2595 if (!break_on_exception_) return;
2596 }
2597
2598 DebugScope debug_scope(this);
2599 if (debug_scope.failed()) return;
2600
2601 // Clear all current stepping setup.
2602 ClearStepping();
2603
2604 // Create the event data object.
2605 Handle<Object> event_data;
2606 // Bail out and don't call debugger if exception.
2607 if (!MakeExceptionEvent(
2608 exception, uncaught, promise).ToHandle(&event_data)) {
2609 return;
2610 }
2611
2612 // Process debug event.
2613 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
2614 // Return to continue execution from where the exception was thrown.
2615 }
2616
2617
OnDebugBreak(Handle<Object> break_points_hit,bool auto_continue)2618 void Debug::OnDebugBreak(Handle<Object> break_points_hit,
2619 bool auto_continue) {
2620 // The caller provided for DebugScope.
2621 AssertDebugContext();
2622 // Bail out if there is no listener for this event
2623 if (ignore_events()) return;
2624
2625 HandleScope scope(isolate_);
2626 // Create the event data object.
2627 Handle<Object> event_data;
2628 // Bail out and don't call debugger if exception.
2629 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
2630
2631 // Process debug event.
2632 ProcessDebugEvent(v8::Break,
2633 Handle<JSObject>::cast(event_data),
2634 auto_continue);
2635 }
2636
2637
OnBeforeCompile(Handle<Script> script)2638 void Debug::OnBeforeCompile(Handle<Script> script) {
2639 if (in_debug_scope() || ignore_events()) return;
2640
2641 HandleScope scope(isolate_);
2642 DebugScope debug_scope(this);
2643 if (debug_scope.failed()) return;
2644
2645 // Create the event data object.
2646 Handle<Object> event_data;
2647 // Bail out and don't call debugger if exception.
2648 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return;
2649
2650 // Process debug event.
2651 ProcessDebugEvent(v8::BeforeCompile,
2652 Handle<JSObject>::cast(event_data),
2653 true);
2654 }
2655
2656
2657 // Handle debugger actions when a new script is compiled.
OnAfterCompile(Handle<Script> script,AfterCompileFlags after_compile_flags)2658 void Debug::OnAfterCompile(Handle<Script> script,
2659 AfterCompileFlags after_compile_flags) {
2660 // Add the newly compiled script to the script cache.
2661 if (script_cache_ != NULL) script_cache_->Add(script);
2662
2663 // No more to do if not debugging.
2664 if (in_debug_scope() || ignore_events()) return;
2665
2666 HandleScope scope(isolate_);
2667 // Store whether in debugger before entering debugger.
2668 bool was_in_scope = in_debug_scope();
2669
2670 DebugScope debug_scope(this);
2671 if (debug_scope.failed()) return;
2672
2673 // If debugging there might be script break points registered for this
2674 // script. Make sure that these break points are set.
2675
2676 // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js).
2677 Handle<String> update_script_break_points_string =
2678 isolate_->factory()->InternalizeOneByteString(
2679 STATIC_ASCII_VECTOR("UpdateScriptBreakPoints"));
2680 Handle<GlobalObject> debug_global(debug_context()->global_object());
2681 Handle<Object> update_script_break_points =
2682 Object::GetProperty(
2683 debug_global, update_script_break_points_string).ToHandleChecked();
2684 if (!update_script_break_points->IsJSFunction()) {
2685 return;
2686 }
2687 ASSERT(update_script_break_points->IsJSFunction());
2688
2689 // Wrap the script object in a proper JS object before passing it
2690 // to JavaScript.
2691 Handle<Object> wrapper = Script::GetWrapper(script);
2692
2693 // Call UpdateScriptBreakPoints expect no exceptions.
2694 Handle<Object> argv[] = { wrapper };
2695 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
2696 isolate_->js_builtins_object(),
2697 ARRAY_SIZE(argv),
2698 argv).is_null()) {
2699 return;
2700 }
2701 // Bail out based on state or if there is no listener for this event
2702 if (was_in_scope && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return;
2703
2704 // Create the compile state object.
2705 Handle<Object> event_data;
2706 // Bail out and don't call debugger if exception.
2707 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return;
2708
2709 // Process debug event.
2710 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
2711 }
2712
2713
OnScriptCollected(int id)2714 void Debug::OnScriptCollected(int id) {
2715 if (in_debug_scope() || ignore_events()) return;
2716
2717 HandleScope scope(isolate_);
2718 DebugScope debug_scope(this);
2719 if (debug_scope.failed()) return;
2720
2721 // Create the script collected state object.
2722 Handle<Object> event_data;
2723 // Bail out and don't call debugger if exception.
2724 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return;
2725
2726 // Process debug event.
2727 ProcessDebugEvent(v8::ScriptCollected,
2728 Handle<JSObject>::cast(event_data),
2729 true);
2730 }
2731
2732
ProcessDebugEvent(v8::DebugEvent event,Handle<JSObject> event_data,bool auto_continue)2733 void Debug::ProcessDebugEvent(v8::DebugEvent event,
2734 Handle<JSObject> event_data,
2735 bool auto_continue) {
2736 HandleScope scope(isolate_);
2737
2738 // Create the execution state.
2739 Handle<Object> exec_state;
2740 // Bail out and don't call debugger if exception.
2741 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2742
2743 // First notify the message handler if any.
2744 if (message_handler_ != NULL) {
2745 NotifyMessageHandler(event,
2746 Handle<JSObject>::cast(exec_state),
2747 event_data,
2748 auto_continue);
2749 }
2750 // Notify registered debug event listener. This can be either a C or
2751 // a JavaScript function. Don't call event listener for v8::Break
2752 // here, if it's only a debug command -- they will be processed later.
2753 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
2754 CallEventCallback(event, exec_state, event_data, NULL);
2755 }
2756 // Process pending debug commands.
2757 if (event == v8::Break) {
2758 while (!event_command_queue_.IsEmpty()) {
2759 CommandMessage command = event_command_queue_.Get();
2760 if (!event_listener_.is_null()) {
2761 CallEventCallback(v8::BreakForCommand,
2762 exec_state,
2763 event_data,
2764 command.client_data());
2765 }
2766 command.Dispose();
2767 }
2768 }
2769 }
2770
2771
CallEventCallback(v8::DebugEvent event,Handle<Object> exec_state,Handle<Object> event_data,v8::Debug::ClientData * client_data)2772 void Debug::CallEventCallback(v8::DebugEvent event,
2773 Handle<Object> exec_state,
2774 Handle<Object> event_data,
2775 v8::Debug::ClientData* client_data) {
2776 if (event_listener_->IsForeign()) {
2777 // Invoke the C debug event listener.
2778 v8::Debug::EventCallback callback =
2779 FUNCTION_CAST<v8::Debug::EventCallback>(
2780 Handle<Foreign>::cast(event_listener_)->foreign_address());
2781 EventDetailsImpl event_details(event,
2782 Handle<JSObject>::cast(exec_state),
2783 Handle<JSObject>::cast(event_data),
2784 event_listener_data_,
2785 client_data);
2786 callback(event_details);
2787 ASSERT(!isolate_->has_scheduled_exception());
2788 } else {
2789 // Invoke the JavaScript debug event listener.
2790 ASSERT(event_listener_->IsJSFunction());
2791 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
2792 exec_state,
2793 event_data,
2794 event_listener_data_ };
2795 Execution::TryCall(Handle<JSFunction>::cast(event_listener_),
2796 isolate_->global_object(),
2797 ARRAY_SIZE(argv),
2798 argv);
2799 }
2800 }
2801
2802
GetDebugContext()2803 Handle<Context> Debug::GetDebugContext() {
2804 DebugScope debug_scope(this);
2805 // The global handle may be destroyed soon after. Return it reboxed.
2806 return handle(*debug_context(), isolate_);
2807 }
2808
2809
NotifyMessageHandler(v8::DebugEvent event,Handle<JSObject> exec_state,Handle<JSObject> event_data,bool auto_continue)2810 void Debug::NotifyMessageHandler(v8::DebugEvent event,
2811 Handle<JSObject> exec_state,
2812 Handle<JSObject> event_data,
2813 bool auto_continue) {
2814 // Prevent other interrupts from triggering, for example API callbacks,
2815 // while dispatching message handler callbacks.
2816 PostponeInterruptsScope no_interrupts(isolate_);
2817 ASSERT(is_active_);
2818 HandleScope scope(isolate_);
2819 // Process the individual events.
2820 bool sendEventMessage = false;
2821 switch (event) {
2822 case v8::Break:
2823 case v8::BreakForCommand:
2824 sendEventMessage = !auto_continue;
2825 break;
2826 case v8::Exception:
2827 sendEventMessage = true;
2828 break;
2829 case v8::BeforeCompile:
2830 break;
2831 case v8::AfterCompile:
2832 sendEventMessage = true;
2833 break;
2834 case v8::ScriptCollected:
2835 sendEventMessage = true;
2836 break;
2837 case v8::NewFunction:
2838 break;
2839 default:
2840 UNREACHABLE();
2841 }
2842
2843 // The debug command interrupt flag might have been set when the command was
2844 // added. It should be enough to clear the flag only once while we are in the
2845 // debugger.
2846 ASSERT(in_debug_scope());
2847 isolate_->stack_guard()->ClearDebugCommand();
2848
2849 // Notify the debugger that a debug event has occurred unless auto continue is
2850 // active in which case no event is send.
2851 if (sendEventMessage) {
2852 MessageImpl message = MessageImpl::NewEvent(
2853 event,
2854 auto_continue,
2855 Handle<JSObject>::cast(exec_state),
2856 Handle<JSObject>::cast(event_data));
2857 InvokeMessageHandler(message);
2858 }
2859
2860 // If auto continue don't make the event cause a break, but process messages
2861 // in the queue if any. For script collected events don't even process
2862 // messages in the queue as the execution state might not be what is expected
2863 // by the client.
2864 if ((auto_continue && !has_commands()) || event == v8::ScriptCollected) {
2865 return;
2866 }
2867
2868 // DebugCommandProcessor goes here.
2869 bool running = auto_continue;
2870
2871 Handle<Object> cmd_processor_ctor = Object::GetProperty(
2872 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked();
2873 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
2874 Handle<Object> cmd_processor = Execution::Call(
2875 isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked();
2876 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
2877 Object::GetProperty(
2878 isolate_, cmd_processor, "processDebugRequest").ToHandleChecked());
2879 Handle<Object> is_running = Object::GetProperty(
2880 isolate_, cmd_processor, "isRunning").ToHandleChecked();
2881
2882 // Process requests from the debugger.
2883 do {
2884 // Wait for new command in the queue.
2885 command_received_.Wait();
2886
2887 // Get the command from the queue.
2888 CommandMessage command = command_queue_.Get();
2889 isolate_->logger()->DebugTag(
2890 "Got request from command queue, in interactive loop.");
2891 if (!is_active()) {
2892 // Delete command text and user data.
2893 command.Dispose();
2894 return;
2895 }
2896
2897 Vector<const uc16> command_text(
2898 const_cast<const uc16*>(command.text().start()),
2899 command.text().length());
2900 Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
2901 command_text).ToHandleChecked();
2902 Handle<Object> request_args[] = { request_text };
2903 Handle<Object> exception;
2904 Handle<Object> answer_value;
2905 Handle<String> answer;
2906 MaybeHandle<Object> maybe_result = Execution::TryCall(
2907 process_debug_request, cmd_processor, 1, request_args, &exception);
2908
2909 if (maybe_result.ToHandle(&answer_value)) {
2910 if (answer_value->IsUndefined()) {
2911 answer = isolate_->factory()->empty_string();
2912 } else {
2913 answer = Handle<String>::cast(answer_value);
2914 }
2915
2916 // Log the JSON request/response.
2917 if (FLAG_trace_debug_json) {
2918 PrintF("%s\n", request_text->ToCString().get());
2919 PrintF("%s\n", answer->ToCString().get());
2920 }
2921
2922 Handle<Object> is_running_args[] = { answer };
2923 maybe_result = Execution::Call(
2924 isolate_, is_running, cmd_processor, 1, is_running_args);
2925 running = maybe_result.ToHandleChecked()->IsTrue();
2926 } else {
2927 answer = Handle<String>::cast(
2928 Execution::ToString(isolate_, exception).ToHandleChecked());
2929 }
2930
2931 // Return the result.
2932 MessageImpl message = MessageImpl::NewResponse(
2933 event, running, exec_state, event_data, answer, command.client_data());
2934 InvokeMessageHandler(message);
2935 command.Dispose();
2936
2937 // Return from debug event processing if either the VM is put into the
2938 // running state (through a continue command) or auto continue is active
2939 // and there are no more commands queued.
2940 } while (!running || has_commands());
2941 }
2942
2943
SetEventListener(Handle<Object> callback,Handle<Object> data)2944 void Debug::SetEventListener(Handle<Object> callback,
2945 Handle<Object> data) {
2946 GlobalHandles* global_handles = isolate_->global_handles();
2947
2948 // Remove existing entry.
2949 GlobalHandles::Destroy(event_listener_.location());
2950 event_listener_ = Handle<Object>();
2951 GlobalHandles::Destroy(event_listener_data_.location());
2952 event_listener_data_ = Handle<Object>();
2953
2954 // Set new entry.
2955 if (!callback->IsUndefined() && !callback->IsNull()) {
2956 event_listener_ = global_handles->Create(*callback);
2957 if (data.is_null()) data = isolate_->factory()->undefined_value();
2958 event_listener_data_ = global_handles->Create(*data);
2959 }
2960
2961 UpdateState();
2962 }
2963
2964
SetMessageHandler(v8::Debug::MessageHandler handler)2965 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
2966 message_handler_ = handler;
2967 UpdateState();
2968 if (handler == NULL && in_debug_scope()) {
2969 // Send an empty command to the debugger if in a break to make JavaScript
2970 // run again if the debugger is closed.
2971 EnqueueCommandMessage(Vector<const uint16_t>::empty());
2972 }
2973 }
2974
2975
2976
UpdateState()2977 void Debug::UpdateState() {
2978 is_active_ = message_handler_ != NULL || !event_listener_.is_null();
2979 if (is_active_ || in_debug_scope()) {
2980 // Note that the debug context could have already been loaded to
2981 // bootstrap test cases.
2982 isolate_->compilation_cache()->Disable();
2983 is_active_ = Load();
2984 } else if (is_loaded()) {
2985 isolate_->compilation_cache()->Enable();
2986 Unload();
2987 }
2988 }
2989
2990
2991 // Calls the registered debug message handler. This callback is part of the
2992 // public API.
InvokeMessageHandler(MessageImpl message)2993 void Debug::InvokeMessageHandler(MessageImpl message) {
2994 if (message_handler_ != NULL) message_handler_(message);
2995 }
2996
2997
2998 // Puts a command coming from the public API on the queue. Creates
2999 // a copy of the command string managed by the debugger. Up to this
3000 // point, the command data was managed by the API client. Called
3001 // by the API client thread.
EnqueueCommandMessage(Vector<const uint16_t> command,v8::Debug::ClientData * client_data)3002 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
3003 v8::Debug::ClientData* client_data) {
3004 // Need to cast away const.
3005 CommandMessage message = CommandMessage::New(
3006 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
3007 command.length()),
3008 client_data);
3009 isolate_->logger()->DebugTag("Put command on command_queue.");
3010 command_queue_.Put(message);
3011 command_received_.Signal();
3012
3013 // Set the debug command break flag to have the command processed.
3014 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
3015 }
3016
3017
EnqueueDebugCommand(v8::Debug::ClientData * client_data)3018 void Debug::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
3019 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
3020 event_command_queue_.Put(message);
3021
3022 // Set the debug command break flag to have the command processed.
3023 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
3024 }
3025
3026
Call(Handle<JSFunction> fun,Handle<Object> data)3027 MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) {
3028 DebugScope debug_scope(this);
3029 if (debug_scope.failed()) return isolate_->factory()->undefined_value();
3030
3031 // Create the execution state.
3032 Handle<Object> exec_state;
3033 if (!MakeExecutionState().ToHandle(&exec_state)) {
3034 return isolate_->factory()->undefined_value();
3035 }
3036
3037 Handle<Object> argv[] = { exec_state, data };
3038 return Execution::Call(
3039 isolate_,
3040 fun,
3041 Handle<Object>(debug_context()->global_proxy(), isolate_),
3042 ARRAY_SIZE(argv),
3043 argv);
3044 }
3045
3046
HandleDebugBreak()3047 void Debug::HandleDebugBreak() {
3048 // Ignore debug break during bootstrapping.
3049 if (isolate_->bootstrapper()->IsActive()) return;
3050 // Just continue if breaks are disabled.
3051 if (break_disabled_) return;
3052 // Ignore debug break if debugger is not active.
3053 if (!is_active()) return;
3054
3055 StackLimitCheck check(isolate_);
3056 if (check.HasOverflowed()) return;
3057
3058 { JavaScriptFrameIterator it(isolate_);
3059 ASSERT(!it.done());
3060 Object* fun = it.frame()->function();
3061 if (fun && fun->IsJSFunction()) {
3062 // Don't stop in builtin functions.
3063 if (JSFunction::cast(fun)->IsBuiltin()) return;
3064 GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
3065 // Don't stop in debugger functions.
3066 if (IsDebugGlobal(global)) return;
3067 }
3068 }
3069
3070 // Collect the break state before clearing the flags.
3071 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
3072 !isolate_->stack_guard()->CheckDebugBreak();
3073
3074 isolate_->stack_guard()->ClearDebugBreak();
3075
3076 ProcessDebugMessages(debug_command_only);
3077 }
3078
3079
ProcessDebugMessages(bool debug_command_only)3080 void Debug::ProcessDebugMessages(bool debug_command_only) {
3081 isolate_->stack_guard()->ClearDebugCommand();
3082
3083 StackLimitCheck check(isolate_);
3084 if (check.HasOverflowed()) return;
3085
3086 HandleScope scope(isolate_);
3087 DebugScope debug_scope(this);
3088 if (debug_scope.failed()) return;
3089
3090 // Notify the debug event listeners. Indicate auto continue if the break was
3091 // a debug command break.
3092 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
3093 }
3094
3095
DebugScope(Debug * debug)3096 DebugScope::DebugScope(Debug* debug) : debug_(debug),
3097 prev_(debug->debugger_entry()),
3098 save_(debug_->isolate_) {
3099 // Link recursive debugger entry.
3100 debug_->thread_local_.current_debug_scope_ = this;
3101
3102 // Store the previous break id and frame id.
3103 break_id_ = debug_->break_id();
3104 break_frame_id_ = debug_->break_frame_id();
3105
3106 // Create the new break info. If there is no JavaScript frames there is no
3107 // break frame id.
3108 JavaScriptFrameIterator it(isolate());
3109 bool has_js_frames = !it.done();
3110 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
3111 : StackFrame::NO_ID;
3112 debug_->SetNextBreakId();
3113
3114 debug_->UpdateState();
3115 // Make sure that debugger is loaded and enter the debugger context.
3116 // The previous context is kept in save_.
3117 failed_ = !debug_->is_loaded();
3118 if (!failed_) isolate()->set_context(*debug->debug_context());
3119 }
3120
3121
3122
~DebugScope()3123 DebugScope::~DebugScope() {
3124 if (!failed_ && prev_ == NULL) {
3125 // Clear mirror cache when leaving the debugger. Skip this if there is a
3126 // pending exception as clearing the mirror cache calls back into
3127 // JavaScript. This can happen if the v8::Debug::Call is used in which
3128 // case the exception should end up in the calling code.
3129 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
3130
3131 // If there are commands in the queue when leaving the debugger request
3132 // that these commands are processed.
3133 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
3134 }
3135
3136 // Leaving this debugger entry.
3137 debug_->thread_local_.current_debug_scope_ = prev_;
3138
3139 // Restore to the previous break state.
3140 debug_->thread_local_.break_frame_id_ = break_frame_id_;
3141 debug_->thread_local_.break_id_ = break_id_;
3142
3143 debug_->UpdateState();
3144 }
3145
3146
NewEvent(DebugEvent event,bool running,Handle<JSObject> exec_state,Handle<JSObject> event_data)3147 MessageImpl MessageImpl::NewEvent(DebugEvent event,
3148 bool running,
3149 Handle<JSObject> exec_state,
3150 Handle<JSObject> event_data) {
3151 MessageImpl message(true, event, running,
3152 exec_state, event_data, Handle<String>(), NULL);
3153 return message;
3154 }
3155
3156
NewResponse(DebugEvent event,bool running,Handle<JSObject> exec_state,Handle<JSObject> event_data,Handle<String> response_json,v8::Debug::ClientData * client_data)3157 MessageImpl MessageImpl::NewResponse(DebugEvent event,
3158 bool running,
3159 Handle<JSObject> exec_state,
3160 Handle<JSObject> event_data,
3161 Handle<String> response_json,
3162 v8::Debug::ClientData* client_data) {
3163 MessageImpl message(false, event, running,
3164 exec_state, event_data, response_json, client_data);
3165 return message;
3166 }
3167
3168
MessageImpl(bool is_event,DebugEvent event,bool running,Handle<JSObject> exec_state,Handle<JSObject> event_data,Handle<String> response_json,v8::Debug::ClientData * client_data)3169 MessageImpl::MessageImpl(bool is_event,
3170 DebugEvent event,
3171 bool running,
3172 Handle<JSObject> exec_state,
3173 Handle<JSObject> event_data,
3174 Handle<String> response_json,
3175 v8::Debug::ClientData* client_data)
3176 : is_event_(is_event),
3177 event_(event),
3178 running_(running),
3179 exec_state_(exec_state),
3180 event_data_(event_data),
3181 response_json_(response_json),
3182 client_data_(client_data) {}
3183
3184
IsEvent() const3185 bool MessageImpl::IsEvent() const {
3186 return is_event_;
3187 }
3188
3189
IsResponse() const3190 bool MessageImpl::IsResponse() const {
3191 return !is_event_;
3192 }
3193
3194
GetEvent() const3195 DebugEvent MessageImpl::GetEvent() const {
3196 return event_;
3197 }
3198
3199
WillStartRunning() const3200 bool MessageImpl::WillStartRunning() const {
3201 return running_;
3202 }
3203
3204
GetExecutionState() const3205 v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
3206 return v8::Utils::ToLocal(exec_state_);
3207 }
3208
3209
GetIsolate() const3210 v8::Isolate* MessageImpl::GetIsolate() const {
3211 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
3212 }
3213
3214
GetEventData() const3215 v8::Handle<v8::Object> MessageImpl::GetEventData() const {
3216 return v8::Utils::ToLocal(event_data_);
3217 }
3218
3219
GetJSON() const3220 v8::Handle<v8::String> MessageImpl::GetJSON() const {
3221 Isolate* isolate = event_data_->GetIsolate();
3222 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
3223
3224 if (IsEvent()) {
3225 // Call toJSONProtocol on the debug event object.
3226 Handle<Object> fun = Object::GetProperty(
3227 isolate, event_data_, "toJSONProtocol").ToHandleChecked();
3228 if (!fun->IsJSFunction()) {
3229 return v8::Handle<v8::String>();
3230 }
3231
3232 MaybeHandle<Object> maybe_json =
3233 Execution::TryCall(Handle<JSFunction>::cast(fun), event_data_, 0, NULL);
3234 Handle<Object> json;
3235 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
3236 return v8::Handle<v8::String>();
3237 }
3238 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
3239 } else {
3240 return v8::Utils::ToLocal(response_json_);
3241 }
3242 }
3243
3244
GetEventContext() const3245 v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
3246 Isolate* isolate = event_data_->GetIsolate();
3247 v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
3248 // Isolate::context() may be NULL when "script collected" event occures.
3249 ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected);
3250 return context;
3251 }
3252
3253
GetClientData() const3254 v8::Debug::ClientData* MessageImpl::GetClientData() const {
3255 return client_data_;
3256 }
3257
3258
EventDetailsImpl(DebugEvent event,Handle<JSObject> exec_state,Handle<JSObject> event_data,Handle<Object> callback_data,v8::Debug::ClientData * client_data)3259 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
3260 Handle<JSObject> exec_state,
3261 Handle<JSObject> event_data,
3262 Handle<Object> callback_data,
3263 v8::Debug::ClientData* client_data)
3264 : event_(event),
3265 exec_state_(exec_state),
3266 event_data_(event_data),
3267 callback_data_(callback_data),
3268 client_data_(client_data) {}
3269
3270
GetEvent() const3271 DebugEvent EventDetailsImpl::GetEvent() const {
3272 return event_;
3273 }
3274
3275
GetExecutionState() const3276 v8::Handle<v8::Object> EventDetailsImpl::GetExecutionState() const {
3277 return v8::Utils::ToLocal(exec_state_);
3278 }
3279
3280
GetEventData() const3281 v8::Handle<v8::Object> EventDetailsImpl::GetEventData() const {
3282 return v8::Utils::ToLocal(event_data_);
3283 }
3284
3285
GetEventContext() const3286 v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const {
3287 return GetDebugEventContext(exec_state_->GetIsolate());
3288 }
3289
3290
GetCallbackData() const3291 v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const {
3292 return v8::Utils::ToLocal(callback_data_);
3293 }
3294
3295
GetClientData() const3296 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
3297 return client_data_;
3298 }
3299
3300
CommandMessage()3301 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
3302 client_data_(NULL) {
3303 }
3304
3305
CommandMessage(const Vector<uint16_t> & text,v8::Debug::ClientData * data)3306 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
3307 v8::Debug::ClientData* data)
3308 : text_(text),
3309 client_data_(data) {
3310 }
3311
3312
Dispose()3313 void CommandMessage::Dispose() {
3314 text_.Dispose();
3315 delete client_data_;
3316 client_data_ = NULL;
3317 }
3318
3319
New(const Vector<uint16_t> & command,v8::Debug::ClientData * data)3320 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
3321 v8::Debug::ClientData* data) {
3322 return CommandMessage(command.Clone(), data);
3323 }
3324
3325
CommandMessageQueue(int size)3326 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
3327 size_(size) {
3328 messages_ = NewArray<CommandMessage>(size);
3329 }
3330
3331
~CommandMessageQueue()3332 CommandMessageQueue::~CommandMessageQueue() {
3333 while (!IsEmpty()) Get().Dispose();
3334 DeleteArray(messages_);
3335 }
3336
3337
Get()3338 CommandMessage CommandMessageQueue::Get() {
3339 ASSERT(!IsEmpty());
3340 int result = start_;
3341 start_ = (start_ + 1) % size_;
3342 return messages_[result];
3343 }
3344
3345
Put(const CommandMessage & message)3346 void CommandMessageQueue::Put(const CommandMessage& message) {
3347 if ((end_ + 1) % size_ == start_) {
3348 Expand();
3349 }
3350 messages_[end_] = message;
3351 end_ = (end_ + 1) % size_;
3352 }
3353
3354
Expand()3355 void CommandMessageQueue::Expand() {
3356 CommandMessageQueue new_queue(size_ * 2);
3357 while (!IsEmpty()) {
3358 new_queue.Put(Get());
3359 }
3360 CommandMessage* array_to_free = messages_;
3361 *this = new_queue;
3362 new_queue.messages_ = array_to_free;
3363 // Make the new_queue empty so that it doesn't call Dispose on any messages.
3364 new_queue.start_ = new_queue.end_;
3365 // Automatic destructor called on new_queue, freeing array_to_free.
3366 }
3367
3368
LockingCommandMessageQueue(Logger * logger,int size)3369 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
3370 : logger_(logger), queue_(size) {}
3371
3372
IsEmpty() const3373 bool LockingCommandMessageQueue::IsEmpty() const {
3374 LockGuard<Mutex> lock_guard(&mutex_);
3375 return queue_.IsEmpty();
3376 }
3377
3378
Get()3379 CommandMessage LockingCommandMessageQueue::Get() {
3380 LockGuard<Mutex> lock_guard(&mutex_);
3381 CommandMessage result = queue_.Get();
3382 logger_->DebugEvent("Get", result.text());
3383 return result;
3384 }
3385
3386
Put(const CommandMessage & message)3387 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
3388 LockGuard<Mutex> lock_guard(&mutex_);
3389 queue_.Put(message);
3390 logger_->DebugEvent("Put", message.text());
3391 }
3392
3393
Clear()3394 void LockingCommandMessageQueue::Clear() {
3395 LockGuard<Mutex> lock_guard(&mutex_);
3396 queue_.Clear();
3397 }
3398
3399 } } // namespace v8::internal
3400