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