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/debug/debug.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/deoptimizer.h"
15 #include "src/execution.h"
16 #include "src/frames-inl.h"
17 #include "src/full-codegen/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/snapshot/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       is_active_(false),
38       is_suppressed_(false),
39       live_edit_enabled_(true),  // TODO(yangguo): set to false by default.
40       break_disabled_(false),
41       break_points_active_(true),
42       in_debug_event_listener_(false),
43       break_on_exception_(false),
44       break_on_uncaught_exception_(false),
45       debug_info_list_(NULL),
46       feature_tracker_(isolate),
47       isolate_(isolate) {
48   ThreadInit();
49 }
50 
51 
GetDebugEventContext(Isolate * isolate)52 static v8::Local<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 
BreakLocation(Handle<DebugInfo> debug_info,RelocInfo * rinfo,int position,int statement_position)62 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo,
63                              int position, int statement_position)
64     : debug_info_(debug_info),
65       pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())),
66       rmode_(rinfo->rmode()),
67       data_(rinfo->data()),
68       position_(position),
69       statement_position_(statement_position) {}
70 
71 
Iterator(Handle<DebugInfo> debug_info,BreakLocatorType type)72 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
73                                   BreakLocatorType type)
74     : debug_info_(debug_info),
75       reloc_iterator_(debug_info->code(), GetModeMask(type)),
76       break_index_(-1),
77       position_(1),
78       statement_position_(1) {
79   if (!Done()) Next();
80 }
81 
82 
GetModeMask(BreakLocatorType type)83 int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) {
84   int mask = 0;
85   mask |= RelocInfo::ModeMask(RelocInfo::POSITION);
86   mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION);
87   mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
88   mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
89   if (type == ALL_BREAK_LOCATIONS) {
90     mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
91     mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT);
92   }
93   return mask;
94 }
95 
96 
Next()97 void BreakLocation::Iterator::Next() {
98   DisallowHeapAllocation no_gc;
99   DCHECK(!Done());
100 
101   // Iterate through reloc info for code and original code stopping at each
102   // breakable code target.
103   bool first = break_index_ == -1;
104   while (!Done()) {
105     if (!first) reloc_iterator_.next();
106     first = false;
107     if (Done()) return;
108 
109     // Whenever a statement position or (plain) position is passed update the
110     // current value of these.
111     if (RelocInfo::IsPosition(rmode())) {
112       if (RelocInfo::IsStatementPosition(rmode())) {
113         statement_position_ = static_cast<int>(
114             rinfo()->data() - debug_info_->shared()->start_position());
115       }
116       // Always update the position as we don't want that to be before the
117       // statement position.
118       position_ = static_cast<int>(rinfo()->data() -
119                                    debug_info_->shared()->start_position());
120       DCHECK(position_ >= 0);
121       DCHECK(statement_position_ >= 0);
122       continue;
123     }
124 
125     DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) ||
126            RelocInfo::IsDebuggerStatement(rmode()));
127 
128     if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
129       // Set the positions to the end of the function.
130       if (debug_info_->shared()->HasSourceCode()) {
131         position_ = debug_info_->shared()->end_position() -
132                     debug_info_->shared()->start_position() - 1;
133       } else {
134         position_ = 0;
135       }
136       statement_position_ = position_;
137     }
138 
139     break;
140   }
141   break_index_++;
142 }
143 
144 
145 // Find the break point at the supplied address, or the closest one before
146 // the address.
FromAddress(Handle<DebugInfo> debug_info,Address pc)147 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info,
148                                          Address pc) {
149   Iterator it(debug_info, ALL_BREAK_LOCATIONS);
150   it.SkipTo(BreakIndexFromAddress(debug_info, pc));
151   return it.GetBreakLocation();
152 }
153 
154 
155 // Find the break point at the supplied address, or the closest one before
156 // the address.
FromAddressSameStatement(Handle<DebugInfo> debug_info,Address pc,List<BreakLocation> * result_out)157 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info,
158                                              Address pc,
159                                              List<BreakLocation>* result_out) {
160   int break_index = BreakIndexFromAddress(debug_info, pc);
161   Iterator it(debug_info, ALL_BREAK_LOCATIONS);
162   it.SkipTo(break_index);
163   int statement_position = it.statement_position();
164   while (!it.Done() && it.statement_position() == statement_position) {
165     result_out->Add(it.GetBreakLocation());
166     it.Next();
167   }
168 }
169 
170 
BreakIndexFromAddress(Handle<DebugInfo> debug_info,Address pc)171 int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info,
172                                          Address pc) {
173   // Run through all break points to locate the one closest to the address.
174   int closest_break = 0;
175   int distance = kMaxInt;
176   for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) {
177     // Check if this break point is closer that what was previously found.
178     if (it.pc() <= pc && pc - it.pc() < distance) {
179       closest_break = it.break_index();
180       distance = static_cast<int>(pc - it.pc());
181       // Check whether we can't get any closer.
182       if (distance == 0) break;
183     }
184   }
185   return closest_break;
186 }
187 
188 
FromPosition(Handle<DebugInfo> debug_info,int position,BreakPositionAlignment alignment)189 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
190                                           int position,
191                                           BreakPositionAlignment alignment) {
192   // Run through all break points to locate the one closest to the source
193   // position.
194   int closest_break = 0;
195   int distance = kMaxInt;
196 
197   for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) {
198     int next_position;
199     if (alignment == STATEMENT_ALIGNED) {
200       next_position = it.statement_position();
201     } else {
202       DCHECK(alignment == BREAK_POSITION_ALIGNED);
203       next_position = it.position();
204     }
205     if (position <= next_position && next_position - position < distance) {
206       closest_break = it.break_index();
207       distance = next_position - position;
208       // Check whether we can't get any closer.
209       if (distance == 0) break;
210     }
211   }
212 
213   Iterator it(debug_info, ALL_BREAK_LOCATIONS);
214   it.SkipTo(closest_break);
215   return it.GetBreakLocation();
216 }
217 
218 
SetBreakPoint(Handle<Object> break_point_object)219 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) {
220   // If there is not already a real break point here patch code with debug
221   // break.
222   if (!HasBreakPoint()) SetDebugBreak();
223   DCHECK(IsDebugBreak() || IsDebuggerStatement());
224   // Set the break point information.
225   DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_,
226                            statement_position_, break_point_object);
227 }
228 
229 
ClearBreakPoint(Handle<Object> break_point_object)230 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
231   // Clear the break point information.
232   DebugInfo::ClearBreakPoint(debug_info_, pc_offset_, break_point_object);
233   // If there are no more break points here remove the debug break.
234   if (!HasBreakPoint()) {
235     ClearDebugBreak();
236     DCHECK(!IsDebugBreak());
237   }
238 }
239 
240 
SetOneShot()241 void BreakLocation::SetOneShot() {
242   // Debugger statement always calls debugger. No need to modify it.
243   if (IsDebuggerStatement()) return;
244 
245   // If there is a real break point here no more to do.
246   if (HasBreakPoint()) {
247     DCHECK(IsDebugBreak());
248     return;
249   }
250 
251   // Patch code with debug break.
252   SetDebugBreak();
253 }
254 
255 
ClearOneShot()256 void BreakLocation::ClearOneShot() {
257   // Debugger statement always calls debugger. No need to modify it.
258   if (IsDebuggerStatement()) return;
259 
260   // If there is a real break point here no more to do.
261   if (HasBreakPoint()) {
262     DCHECK(IsDebugBreak());
263     return;
264   }
265 
266   // Patch code removing debug break.
267   ClearDebugBreak();
268   DCHECK(!IsDebugBreak());
269 }
270 
271 
SetDebugBreak()272 void BreakLocation::SetDebugBreak() {
273   // Debugger statement always calls debugger. No need to modify it.
274   if (IsDebuggerStatement()) return;
275 
276   // If there is already a break point here just return. This might happen if
277   // the same code is flooded with break points twice. Flooding the same
278   // function twice might happen when stepping in a function with an exception
279   // handler as the handler and the function is the same.
280   if (IsDebugBreak()) return;
281 
282   DCHECK(IsDebugBreakSlot());
283   Isolate* isolate = debug_info_->GetIsolate();
284   Builtins* builtins = isolate->builtins();
285   Handle<Code> target =
286       IsReturn() ? builtins->Return_DebugBreak() : builtins->Slot_DebugBreak();
287   DebugCodegen::PatchDebugBreakSlot(isolate, pc(), target);
288   DCHECK(IsDebugBreak());
289 }
290 
291 
ClearDebugBreak()292 void BreakLocation::ClearDebugBreak() {
293   // Debugger statement always calls debugger. No need to modify it.
294   if (IsDebuggerStatement()) return;
295 
296   DCHECK(IsDebugBreakSlot());
297   DebugCodegen::ClearDebugBreakSlot(debug_info_->GetIsolate(), pc());
298   DCHECK(!IsDebugBreak());
299 }
300 
301 
IsDebugBreak() const302 bool BreakLocation::IsDebugBreak() const {
303   if (IsDebuggerStatement()) return false;
304   DCHECK(IsDebugBreakSlot());
305   return rinfo().IsPatchedDebugBreakSlotSequence();
306 }
307 
308 
BreakPointObjects() const309 Handle<Object> BreakLocation::BreakPointObjects() const {
310   return debug_info_->GetBreakPointObjects(pc_offset_);
311 }
312 
313 
Track(DebugFeatureTracker::Feature feature)314 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
315   uint32_t mask = 1 << feature;
316   // Only count one sample per feature and isolate.
317   if (bitfield_ & mask) return;
318   isolate_->counters()->debug_feature_usage()->AddSample(feature);
319   bitfield_ |= mask;
320 }
321 
322 
323 // Threading support.
ThreadInit()324 void Debug::ThreadInit() {
325   thread_local_.break_count_ = 0;
326   thread_local_.break_id_ = 0;
327   thread_local_.break_frame_id_ = StackFrame::NO_ID;
328   thread_local_.last_step_action_ = StepNone;
329   thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
330   thread_local_.last_fp_ = 0;
331   thread_local_.target_fp_ = 0;
332   thread_local_.step_in_enabled_ = false;
333   // TODO(isolates): frames_are_dropped_?
334   base::NoBarrier_Store(&thread_local_.current_debug_scope_,
335                         static_cast<base::AtomicWord>(0));
336 }
337 
338 
ArchiveDebug(char * storage)339 char* Debug::ArchiveDebug(char* storage) {
340   char* to = storage;
341   MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
342   ThreadInit();
343   return storage + ArchiveSpacePerThread();
344 }
345 
346 
RestoreDebug(char * storage)347 char* Debug::RestoreDebug(char* storage) {
348   char* from = storage;
349   MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
350   return storage + ArchiveSpacePerThread();
351 }
352 
353 
ArchiveSpacePerThread()354 int Debug::ArchiveSpacePerThread() {
355   return sizeof(ThreadLocal);
356 }
357 
358 
DebugInfoListNode(DebugInfo * debug_info)359 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
360   // Globalize the request debug info object and make it weak.
361   GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
362   debug_info_ =
363       Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location();
364 }
365 
366 
~DebugInfoListNode()367 DebugInfoListNode::~DebugInfoListNode() {
368   if (debug_info_ == nullptr) return;
369   GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_));
370   debug_info_ = nullptr;
371 }
372 
373 
Load()374 bool Debug::Load() {
375   // Return if debugger is already loaded.
376   if (is_loaded()) return true;
377 
378   // Bail out if we're already in the process of compiling the native
379   // JavaScript source code for the debugger.
380   if (is_suppressed_) return false;
381   SuppressDebug while_loading(this);
382 
383   // Disable breakpoints and interrupts while compiling and running the
384   // debugger scripts including the context creation code.
385   DisableBreak disable(this, true);
386   PostponeInterruptsScope postpone(isolate_);
387 
388   // Create the debugger context.
389   HandleScope scope(isolate_);
390   ExtensionConfiguration no_extensions;
391   Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
392       MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
393       DEBUG_CONTEXT);
394 
395   // Fail if no context could be created.
396   if (context.is_null()) return false;
397 
398   debug_context_ = Handle<Context>::cast(
399       isolate_->global_handles()->Create(*context));
400 
401   feature_tracker()->Track(DebugFeatureTracker::kActive);
402 
403   return true;
404 }
405 
406 
Unload()407 void Debug::Unload() {
408   ClearAllBreakPoints();
409   ClearStepping();
410 
411   // Return debugger is not loaded.
412   if (!is_loaded()) return;
413 
414   // Clear debugger context global handle.
415   GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
416   debug_context_ = Handle<Context>();
417 }
418 
419 
Break(Arguments args,JavaScriptFrame * frame)420 void Debug::Break(Arguments args, JavaScriptFrame* frame) {
421   HandleScope scope(isolate_);
422   DCHECK(args.length() == 0);
423 
424   // Initialize LiveEdit.
425   LiveEdit::InitializeThreadLocal(this);
426 
427   // Just continue if breaks are disabled or debugger cannot be loaded.
428   if (break_disabled()) return;
429 
430   // Enter the debugger.
431   DebugScope debug_scope(this);
432   if (debug_scope.failed()) return;
433 
434   // Postpone interrupt during breakpoint processing.
435   PostponeInterruptsScope postpone(isolate_);
436 
437   // Get the debug info (create it if it does not exist).
438   Handle<JSFunction> function(frame->function());
439   Handle<SharedFunctionInfo> shared(function->shared());
440   if (!EnsureDebugInfo(shared, function)) {
441     // Return if we failed to retrieve the debug info.
442     return;
443   }
444   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
445 
446   // Find the break location where execution has stopped.
447   // PC points to the instruction after the current one, possibly a break
448   // location as well. So the "- 1" to exclude it from the search.
449   Address call_pc = frame->pc() - 1;
450   BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc);
451 
452   // Find actual break points, if any, and trigger debug break event.
453   if (break_points_active_ && location.HasBreakPoint()) {
454     Handle<Object> break_point_objects = location.BreakPointObjects();
455     Handle<Object> break_points_hit = CheckBreakPoints(break_point_objects);
456     if (!break_points_hit->IsUndefined()) {
457       // Clear all current stepping setup.
458       ClearStepping();
459       // Notify the debug event listeners.
460       OnDebugBreak(break_points_hit, false);
461       return;
462     }
463   }
464 
465   // No break point. Check for stepping.
466   StepAction step_action = last_step_action();
467   Address current_fp = frame->UnpaddedFP();
468   Address target_fp = thread_local_.target_fp_;
469   Address last_fp = thread_local_.last_fp_;
470 
471   bool step_break = true;
472   switch (step_action) {
473     case StepNone:
474       return;
475     case StepOut:
476       // Step out has not reached the target frame yet.
477       if (current_fp < target_fp) return;
478       break;
479     case StepNext:
480       // Step next should not break in a deeper frame.
481       if (current_fp < target_fp) return;
482     // Fall through.
483     case StepIn:
484       step_break = location.IsReturn() || (current_fp != last_fp) ||
485                    (thread_local_.last_statement_position_ !=
486                     location.code()->SourceStatementPosition(frame->pc()));
487       break;
488     case StepFrame:
489       step_break = current_fp != last_fp;
490       break;
491   }
492 
493   // Clear all current stepping setup.
494   ClearStepping();
495 
496   if (step_break) {
497     // Notify the debug event listeners.
498     OnDebugBreak(isolate_->factory()->undefined_value(), false);
499   } else {
500     // Re-prepare to continue.
501     PrepareStep(step_action);
502   }
503 }
504 
505 
506 // Check the break point objects for whether one or more are actually
507 // triggered. This function returns a JSArray with the break point objects
508 // which is triggered.
CheckBreakPoints(Handle<Object> break_point_objects)509 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
510   Factory* factory = isolate_->factory();
511 
512   // Count the number of break points hit. If there are multiple break points
513   // they are in a FixedArray.
514   Handle<FixedArray> break_points_hit;
515   int break_points_hit_count = 0;
516   DCHECK(!break_point_objects->IsUndefined());
517   if (break_point_objects->IsFixedArray()) {
518     Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
519     break_points_hit = factory->NewFixedArray(array->length());
520     for (int i = 0; i < array->length(); i++) {
521       Handle<Object> o(array->get(i), isolate_);
522       if (CheckBreakPoint(o)) {
523         break_points_hit->set(break_points_hit_count++, *o);
524       }
525     }
526   } else {
527     break_points_hit = factory->NewFixedArray(1);
528     if (CheckBreakPoint(break_point_objects)) {
529       break_points_hit->set(break_points_hit_count++, *break_point_objects);
530     }
531   }
532 
533   // Return undefined if no break points were triggered.
534   if (break_points_hit_count == 0) {
535     return factory->undefined_value();
536   }
537   // Return break points hit as a JSArray.
538   Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
539   result->set_length(Smi::FromInt(break_points_hit_count));
540   return result;
541 }
542 
543 
CallFunction(const char * name,int argc,Handle<Object> args[])544 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
545                                         Handle<Object> args[]) {
546   PostponeInterruptsScope no_interrupts(isolate_);
547   AssertDebugContext();
548   Handle<Object> holder = isolate_->natives_utils_object();
549   Handle<JSFunction> fun = Handle<JSFunction>::cast(
550       Object::GetProperty(isolate_, holder, name, STRICT).ToHandleChecked());
551   Handle<Object> undefined = isolate_->factory()->undefined_value();
552   return Execution::TryCall(isolate_, fun, undefined, argc, args);
553 }
554 
555 
556 // Check whether a single break point object is triggered.
CheckBreakPoint(Handle<Object> break_point_object)557 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
558   Factory* factory = isolate_->factory();
559   HandleScope scope(isolate_);
560 
561   // Ignore check if break point object is not a JSObject.
562   if (!break_point_object->IsJSObject()) return true;
563 
564   // Get the break id as an object.
565   Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
566 
567   // Call IsBreakPointTriggered.
568   Handle<Object> argv[] = { break_id, break_point_object };
569   Handle<Object> result;
570   if (!CallFunction("IsBreakPointTriggered", arraysize(argv), argv)
571            .ToHandle(&result)) {
572     return false;
573   }
574 
575   // Return whether the break point is triggered.
576   return result->IsTrue();
577 }
578 
579 
SetBreakPoint(Handle<JSFunction> function,Handle<Object> break_point_object,int * source_position)580 bool Debug::SetBreakPoint(Handle<JSFunction> function,
581                           Handle<Object> break_point_object,
582                           int* source_position) {
583   HandleScope scope(isolate_);
584 
585   // Make sure the function is compiled and has set up the debug info.
586   Handle<SharedFunctionInfo> shared(function->shared());
587   if (!EnsureDebugInfo(shared, function)) {
588     // Return if retrieving debug info failed.
589     return true;
590   }
591 
592   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
593   // Source positions starts with zero.
594   DCHECK(*source_position >= 0);
595 
596   // Find the break point and change it.
597   BreakLocation location = BreakLocation::FromPosition(
598       debug_info, *source_position, STATEMENT_ALIGNED);
599   *source_position = location.statement_position();
600   location.SetBreakPoint(break_point_object);
601 
602   feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
603 
604   // At least one active break point now.
605   return debug_info->GetBreakPointCount() > 0;
606 }
607 
608 
SetBreakPointForScript(Handle<Script> script,Handle<Object> break_point_object,int * source_position,BreakPositionAlignment alignment)609 bool Debug::SetBreakPointForScript(Handle<Script> script,
610                                    Handle<Object> break_point_object,
611                                    int* source_position,
612                                    BreakPositionAlignment alignment) {
613   HandleScope scope(isolate_);
614 
615   // Obtain shared function info for the function.
616   Handle<Object> result =
617       FindSharedFunctionInfoInScript(script, *source_position);
618   if (result->IsUndefined()) return false;
619 
620   // Make sure the function has set up the debug info.
621   Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
622   if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
623     // Return if retrieving debug info failed.
624     return false;
625   }
626 
627   // Find position within function. The script position might be before the
628   // source position of the first function.
629   int position;
630   if (shared->start_position() > *source_position) {
631     position = 0;
632   } else {
633     position = *source_position - shared->start_position();
634   }
635 
636   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
637   // Source positions starts with zero.
638   DCHECK(position >= 0);
639 
640   // Find the break point and change it.
641   BreakLocation location =
642       BreakLocation::FromPosition(debug_info, position, alignment);
643   location.SetBreakPoint(break_point_object);
644 
645   feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
646 
647   position = (alignment == STATEMENT_ALIGNED) ? location.statement_position()
648                                               : location.position();
649 
650   *source_position = position + shared->start_position();
651 
652   // At least one active break point now.
653   DCHECK(debug_info->GetBreakPointCount() > 0);
654   return true;
655 }
656 
657 
ClearBreakPoint(Handle<Object> break_point_object)658 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
659   HandleScope scope(isolate_);
660 
661   DebugInfoListNode* node = debug_info_list_;
662   while (node != NULL) {
663     Handle<Object> result =
664         DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
665     if (!result->IsUndefined()) {
666       // Get information in the break point.
667       Handle<BreakPointInfo> break_point_info =
668           Handle<BreakPointInfo>::cast(result);
669       Handle<DebugInfo> debug_info = node->debug_info();
670 
671       // Find the break point and clear it.
672       Address pc =
673           debug_info->code()->entry() + break_point_info->code_position();
674 
675       BreakLocation location = BreakLocation::FromAddress(debug_info, pc);
676       location.ClearBreakPoint(break_point_object);
677 
678       // If there are no more break points left remove the debug info for this
679       // function.
680       if (debug_info->GetBreakPointCount() == 0) {
681         RemoveDebugInfoAndClearFromShared(debug_info);
682       }
683 
684       return;
685     }
686     node = node->next();
687   }
688 }
689 
690 
691 // Clear out all the debug break code. This is ONLY supposed to be used when
692 // shutting down the debugger as it will leave the break point information in
693 // DebugInfo even though the code is patched back to the non break point state.
ClearAllBreakPoints()694 void Debug::ClearAllBreakPoints() {
695   for (DebugInfoListNode* node = debug_info_list_; node != NULL;
696        node = node->next()) {
697     for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
698          !it.Done(); it.Next()) {
699       it.GetBreakLocation().ClearDebugBreak();
700     }
701   }
702   // Remove all debug info.
703   while (debug_info_list_ != NULL) {
704     RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
705   }
706 }
707 
708 
FloodWithOneShot(Handle<JSFunction> function,BreakLocatorType type)709 void Debug::FloodWithOneShot(Handle<JSFunction> function,
710                              BreakLocatorType type) {
711   // Debug utility functions are not subject to debugging.
712   if (function->native_context() == *debug_context()) return;
713 
714   if (!function->shared()->IsSubjectToDebugging()) {
715     // Builtin functions are not subject to stepping, but need to be
716     // deoptimized, because optimized code does not check for debug
717     // step in at call sites.
718     Deoptimizer::DeoptimizeFunction(*function);
719     return;
720   }
721   // Make sure the function is compiled and has set up the debug info.
722   Handle<SharedFunctionInfo> shared(function->shared());
723   if (!EnsureDebugInfo(shared, function)) {
724     // Return if we failed to retrieve the debug info.
725     return;
726   }
727 
728   // Flood the function with break points.
729   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
730   for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) {
731     it.GetBreakLocation().SetOneShot();
732   }
733 }
734 
735 
ChangeBreakOnException(ExceptionBreakType type,bool enable)736 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
737   if (type == BreakUncaughtException) {
738     break_on_uncaught_exception_ = enable;
739   } else {
740     break_on_exception_ = enable;
741   }
742 }
743 
744 
IsBreakOnException(ExceptionBreakType type)745 bool Debug::IsBreakOnException(ExceptionBreakType type) {
746   if (type == BreakUncaughtException) {
747     return break_on_uncaught_exception_;
748   } else {
749     return break_on_exception_;
750   }
751 }
752 
753 
GetFirstFrameSummary(JavaScriptFrame * frame)754 FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) {
755   List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
756   frame->Summarize(&frames);
757   return frames.first();
758 }
759 
760 
PrepareStepIn(Handle<JSFunction> function)761 void Debug::PrepareStepIn(Handle<JSFunction> function) {
762   if (!is_active()) return;
763   if (last_step_action() < StepIn) return;
764   if (in_debug_scope()) return;
765   if (thread_local_.step_in_enabled_) {
766     FloodWithOneShot(function);
767   }
768 }
769 
770 
PrepareStepOnThrow()771 void Debug::PrepareStepOnThrow() {
772   if (!is_active()) return;
773   if (last_step_action() == StepNone) return;
774   if (in_debug_scope()) return;
775 
776   ClearOneShot();
777 
778   // Iterate through the JavaScript stack looking for handlers.
779   JavaScriptFrameIterator it(isolate_);
780   while (!it.done()) {
781     JavaScriptFrame* frame = it.frame();
782     int stack_slots = 0;  // The computed stack slot count is not used.
783     if (frame->LookupExceptionHandlerInTable(&stack_slots, NULL) > 0) break;
784     it.Advance();
785   }
786 
787   // Find the closest Javascript frame we can flood with one-shots.
788   while (!it.done() &&
789          !it.frame()->function()->shared()->IsSubjectToDebugging()) {
790     it.Advance();
791   }
792 
793   if (it.done()) return;  // No suitable Javascript catch handler.
794 
795   FloodWithOneShot(Handle<JSFunction>(it.frame()->function()));
796 }
797 
798 
PrepareStep(StepAction step_action)799 void Debug::PrepareStep(StepAction step_action) {
800   HandleScope scope(isolate_);
801 
802   DCHECK(in_debug_scope());
803 
804   // Get the frame where the execution has stopped and skip the debug frame if
805   // any. The debug frame will only be present if execution was stopped due to
806   // hitting a break point. In other situations (e.g. unhandled exception) the
807   // debug frame is not present.
808   StackFrame::Id frame_id = break_frame_id();
809   // If there is no JavaScript stack don't do anything.
810   if (frame_id == StackFrame::NO_ID) return;
811 
812   JavaScriptFrameIterator frames_it(isolate_, frame_id);
813   JavaScriptFrame* frame = frames_it.frame();
814 
815   feature_tracker()->Track(DebugFeatureTracker::kStepping);
816 
817   // Remember this step action and count.
818   thread_local_.last_step_action_ = step_action;
819   STATIC_ASSERT(StepFrame > StepIn);
820   thread_local_.step_in_enabled_ = (step_action >= StepIn);
821 
822   // If the function on the top frame is unresolved perform step out. This will
823   // be the case when calling unknown function and having the debugger stopped
824   // in an unhandled exception.
825   if (!frame->function()->IsJSFunction()) {
826     // Step out: Find the calling JavaScript frame and flood it with
827     // breakpoints.
828     frames_it.Advance();
829     // Fill the function to return to with one-shot break points.
830     JSFunction* function = frames_it.frame()->function();
831     FloodWithOneShot(Handle<JSFunction>(function));
832     return;
833   }
834 
835   // Get the debug info (create it if it does not exist).
836   FrameSummary summary = GetFirstFrameSummary(frame);
837   Handle<JSFunction> function(summary.function());
838   Handle<SharedFunctionInfo> shared(function->shared());
839   if (!EnsureDebugInfo(shared, function)) {
840     // Return if ensuring debug info failed.
841     return;
842   }
843 
844   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
845   // Refresh frame summary if the code has been recompiled for debugging.
846   if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame);
847 
848   // PC points to the instruction after the current one, possibly a break
849   // location as well. So the "- 1" to exclude it from the search.
850   Address call_pc = summary.pc() - 1;
851   BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc);
852 
853   // At a return statement we will step out either way.
854   if (location.IsReturn()) step_action = StepOut;
855 
856   thread_local_.last_statement_position_ =
857       debug_info->code()->SourceStatementPosition(summary.pc());
858   thread_local_.last_fp_ = frame->UnpaddedFP();
859 
860   switch (step_action) {
861     case StepNone:
862       UNREACHABLE();
863       break;
864     case StepOut:
865       // Advance to caller frame.
866       frames_it.Advance();
867       // Skip native and extension functions on the stack.
868       while (!frames_it.done() &&
869              !frames_it.frame()->function()->shared()->IsSubjectToDebugging()) {
870         // Builtin functions are not subject to stepping, but need to be
871         // deoptimized to include checks for step-in at call sites.
872         Deoptimizer::DeoptimizeFunction(frames_it.frame()->function());
873         frames_it.Advance();
874       }
875       if (frames_it.done()) {
876         // Stepping out to the embedder. Disable step-in to avoid stepping into
877         // the next (unrelated) call that the embedder makes.
878         thread_local_.step_in_enabled_ = false;
879       } else {
880         // Fill the caller function to return to with one-shot break points.
881         Handle<JSFunction> caller_function(frames_it.frame()->function());
882         FloodWithOneShot(caller_function);
883         thread_local_.target_fp_ = frames_it.frame()->UnpaddedFP();
884       }
885       // Clear last position info. For stepping out it does not matter.
886       thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
887       thread_local_.last_fp_ = 0;
888       break;
889     case StepNext:
890       thread_local_.target_fp_ = frame->UnpaddedFP();
891       FloodWithOneShot(function);
892       break;
893     case StepIn:
894       FloodWithOneShot(function);
895       break;
896     case StepFrame:
897       // No point in setting one-shot breaks at places where we are not about
898       // to leave the current frame.
899       FloodWithOneShot(function, CALLS_AND_RETURNS);
900       break;
901   }
902 }
903 
904 
905 // Simple function for returning the source positions for active break points.
GetSourceBreakLocations(Handle<SharedFunctionInfo> shared,BreakPositionAlignment position_alignment)906 Handle<Object> Debug::GetSourceBreakLocations(
907     Handle<SharedFunctionInfo> shared,
908     BreakPositionAlignment position_alignment) {
909   Isolate* isolate = shared->GetIsolate();
910   Heap* heap = isolate->heap();
911   if (!shared->HasDebugInfo()) {
912     return Handle<Object>(heap->undefined_value(), isolate);
913   }
914   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
915   if (debug_info->GetBreakPointCount() == 0) {
916     return Handle<Object>(heap->undefined_value(), isolate);
917   }
918   Handle<FixedArray> locations =
919       isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
920   int count = 0;
921   for (int i = 0; i < debug_info->break_points()->length(); ++i) {
922     if (!debug_info->break_points()->get(i)->IsUndefined()) {
923       BreakPointInfo* break_point_info =
924           BreakPointInfo::cast(debug_info->break_points()->get(i));
925       int break_points = break_point_info->GetBreakPointCount();
926       if (break_points == 0) continue;
927       Smi* position = NULL;
928       switch (position_alignment) {
929         case STATEMENT_ALIGNED:
930           position = Smi::FromInt(break_point_info->statement_position());
931           break;
932         case BREAK_POSITION_ALIGNED:
933           position = Smi::FromInt(break_point_info->source_position());
934           break;
935       }
936       for (int j = 0; j < break_points; ++j) locations->set(count++, position);
937     }
938   }
939   return locations;
940 }
941 
942 
ClearStepping()943 void Debug::ClearStepping() {
944   // Clear the various stepping setup.
945   ClearOneShot();
946 
947   thread_local_.last_step_action_ = StepNone;
948   thread_local_.step_in_enabled_ = false;
949   thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
950   thread_local_.last_fp_ = 0;
951   thread_local_.target_fp_ = 0;
952 }
953 
954 
955 // Clears all the one-shot break points that are currently set. Normally this
956 // function is called each time a break point is hit as one shot break points
957 // are used to support stepping.
ClearOneShot()958 void Debug::ClearOneShot() {
959   // The current implementation just runs through all the breakpoints. When the
960   // last break point for a function is removed that function is automatically
961   // removed from the list.
962   for (DebugInfoListNode* node = debug_info_list_; node != NULL;
963        node = node->next()) {
964     for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
965          !it.Done(); it.Next()) {
966       it.GetBreakLocation().ClearOneShot();
967     }
968   }
969 }
970 
971 
EnableStepIn()972 void Debug::EnableStepIn() {
973   STATIC_ASSERT(StepFrame > StepIn);
974   thread_local_.step_in_enabled_ = (last_step_action() >= StepIn);
975 }
976 
977 
MatchingCodeTargets(Code * target1,Code * target2)978 bool MatchingCodeTargets(Code* target1, Code* target2) {
979   if (target1 == target2) return true;
980   if (target1->kind() != target2->kind()) return false;
981   return target1->is_handler() || target1->is_inline_cache_stub();
982 }
983 
984 
985 // Count the number of calls before the current frame PC to find the
986 // corresponding PC in the newly recompiled code.
ComputeNewPcForRedirect(Code * new_code,Code * old_code,Address old_pc)987 static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code,
988                                        Address old_pc) {
989   DCHECK_EQ(old_code->kind(), Code::FUNCTION);
990   DCHECK_EQ(new_code->kind(), Code::FUNCTION);
991   DCHECK(new_code->has_debug_break_slots());
992   static const int mask = RelocInfo::kCodeTargetMask;
993 
994   // Find the target of the current call.
995   Code* target = NULL;
996   intptr_t delta = 0;
997   for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
998     RelocInfo* rinfo = it.rinfo();
999     Address current_pc = rinfo->pc();
1000     // The frame PC is behind the call instruction by the call instruction size.
1001     if (current_pc > old_pc) break;
1002     delta = old_pc - current_pc;
1003     target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1004   }
1005 
1006   // Count the number of calls to the same target before the current call.
1007   int index = 0;
1008   for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
1009     RelocInfo* rinfo = it.rinfo();
1010     Address current_pc = rinfo->pc();
1011     if (current_pc > old_pc) break;
1012     Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
1013     if (MatchingCodeTargets(target, current)) index++;
1014   }
1015 
1016   DCHECK(index > 0);
1017 
1018   // Repeat the count on the new code to find corresponding call.
1019   for (RelocIterator it(new_code, mask); !it.done(); it.next()) {
1020     RelocInfo* rinfo = it.rinfo();
1021     Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
1022     if (MatchingCodeTargets(target, current)) index--;
1023     if (index == 0) return rinfo->pc() + delta;
1024   }
1025 
1026   UNREACHABLE();
1027   return NULL;
1028 }
1029 
1030 
1031 // Count the number of continuations at which the current pc offset is at.
ComputeContinuationIndexFromPcOffset(Code * code,int pc_offset)1032 static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) {
1033   DCHECK_EQ(code->kind(), Code::FUNCTION);
1034   Address pc = code->instruction_start() + pc_offset;
1035   int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
1036   int index = 0;
1037   for (RelocIterator it(code, mask); !it.done(); it.next()) {
1038     index++;
1039     RelocInfo* rinfo = it.rinfo();
1040     Address current_pc = rinfo->pc();
1041     if (current_pc == pc) break;
1042     DCHECK(current_pc < pc);
1043   }
1044   return index;
1045 }
1046 
1047 
1048 // Find the pc offset for the given continuation index.
ComputePcOffsetFromContinuationIndex(Code * code,int index)1049 static int ComputePcOffsetFromContinuationIndex(Code* code, int index) {
1050   DCHECK_EQ(code->kind(), Code::FUNCTION);
1051   DCHECK(code->has_debug_break_slots());
1052   int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
1053   RelocIterator it(code, mask);
1054   for (int i = 1; i < index; i++) it.next();
1055   return static_cast<int>(it.rinfo()->pc() - code->instruction_start());
1056 }
1057 
1058 
1059 class RedirectActiveFunctions : public ThreadVisitor {
1060  public:
RedirectActiveFunctions(SharedFunctionInfo * shared)1061   explicit RedirectActiveFunctions(SharedFunctionInfo* shared)
1062       : shared_(shared) {
1063     DCHECK(shared->HasDebugCode());
1064   }
1065 
VisitThread(Isolate * isolate,ThreadLocalTop * top)1066   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1067     for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1068       JavaScriptFrame* frame = it.frame();
1069       JSFunction* function = frame->function();
1070       if (frame->is_optimized()) continue;
1071       if (!function->Inlines(shared_)) continue;
1072 
1073       Code* frame_code = frame->LookupCode();
1074       DCHECK(frame_code->kind() == Code::FUNCTION);
1075       if (frame_code->has_debug_break_slots()) continue;
1076 
1077       Code* new_code = function->shared()->code();
1078       Address old_pc = frame->pc();
1079       Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc);
1080 
1081       if (FLAG_trace_deopt) {
1082         PrintF("Replacing pc for debugging: %08" V8PRIxPTR " => %08" V8PRIxPTR
1083                "\n",
1084                reinterpret_cast<intptr_t>(old_pc),
1085                reinterpret_cast<intptr_t>(new_pc));
1086       }
1087 
1088       if (FLAG_enable_embedded_constant_pool) {
1089         // Update constant pool pointer for new code.
1090         frame->set_constant_pool(new_code->constant_pool());
1091       }
1092 
1093       // Patch the return address to return into the code with
1094       // debug break slots.
1095       frame->set_pc(new_pc);
1096     }
1097   }
1098 
1099  private:
1100   SharedFunctionInfo* shared_;
1101   DisallowHeapAllocation no_gc_;
1102 };
1103 
1104 
PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared)1105 bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
1106   DCHECK(shared->is_compiled());
1107 
1108   if (isolate_->concurrent_recompilation_enabled()) {
1109     isolate_->optimizing_compile_dispatcher()->Flush();
1110   }
1111 
1112   List<Handle<JSFunction> > functions;
1113   List<Handle<JSGeneratorObject> > suspended_generators;
1114 
1115   // Flush all optimized code maps. Note that the below heap iteration does not
1116   // cover this, because the given function might have been inlined into code
1117   // for which no JSFunction exists.
1118   {
1119     SharedFunctionInfo::Iterator iterator(isolate_);
1120     while (SharedFunctionInfo* shared = iterator.Next()) {
1121       if (!shared->OptimizedCodeMapIsCleared()) {
1122         shared->ClearOptimizedCodeMap();
1123       }
1124     }
1125   }
1126 
1127   // Make sure we abort incremental marking.
1128   isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1129                                       "prepare for break points");
1130 
1131   {
1132     HeapIterator iterator(isolate_->heap());
1133     HeapObject* obj;
1134     bool include_generators = shared->is_generator();
1135 
1136     while ((obj = iterator.next())) {
1137       if (obj->IsJSFunction()) {
1138         JSFunction* function = JSFunction::cast(obj);
1139         if (!function->Inlines(*shared)) continue;
1140         if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) {
1141           Deoptimizer::DeoptimizeFunction(function);
1142         }
1143         if (function->shared() == *shared) functions.Add(handle(function));
1144       } else if (include_generators && obj->IsJSGeneratorObject()) {
1145         JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj);
1146         if (!generator_obj->is_suspended()) continue;
1147         JSFunction* function = generator_obj->function();
1148         if (!function->Inlines(*shared)) continue;
1149         int pc_offset = generator_obj->continuation();
1150         int index =
1151             ComputeContinuationIndexFromPcOffset(function->code(), pc_offset);
1152         generator_obj->set_continuation(index);
1153         suspended_generators.Add(handle(generator_obj));
1154       }
1155     }
1156   }
1157 
1158   if (!shared->HasDebugCode()) {
1159     DCHECK(functions.length() > 0);
1160     if (!Compiler::CompileDebugCode(functions.first())) return false;
1161   }
1162 
1163   for (Handle<JSFunction> const function : functions) {
1164     function->ReplaceCode(shared->code());
1165   }
1166 
1167   for (Handle<JSGeneratorObject> const generator_obj : suspended_generators) {
1168     int index = generator_obj->continuation();
1169     int pc_offset = ComputePcOffsetFromContinuationIndex(shared->code(), index);
1170     generator_obj->set_continuation(pc_offset);
1171   }
1172 
1173   // Update PCs on the stack to point to recompiled code.
1174   RedirectActiveFunctions redirect_visitor(*shared);
1175   redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top());
1176   isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor);
1177 
1178   return true;
1179 }
1180 
1181 
1182 class SharedFunctionInfoFinder {
1183  public:
SharedFunctionInfoFinder(int target_position)1184   explicit SharedFunctionInfoFinder(int target_position)
1185       : current_candidate_(NULL),
1186         current_candidate_closure_(NULL),
1187         current_start_position_(RelocInfo::kNoPosition),
1188         target_position_(target_position) {}
1189 
NewCandidate(SharedFunctionInfo * shared,JSFunction * closure=NULL)1190   void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) {
1191     if (!shared->IsSubjectToDebugging()) return;
1192     int start_position = shared->function_token_position();
1193     if (start_position == RelocInfo::kNoPosition) {
1194       start_position = shared->start_position();
1195     }
1196 
1197     if (start_position > target_position_) return;
1198     if (target_position_ > shared->end_position()) return;
1199 
1200     if (current_candidate_ != NULL) {
1201       if (current_start_position_ == start_position &&
1202           shared->end_position() == current_candidate_->end_position()) {
1203         // If we already have a matching closure, do not throw it away.
1204         if (current_candidate_closure_ != NULL && closure == NULL) return;
1205         // If a top-level function contains only one function
1206         // declaration the source for the top-level and the function
1207         // is the same. In that case prefer the non top-level function.
1208         if (!current_candidate_->is_toplevel() && shared->is_toplevel()) return;
1209       } else if (start_position < current_start_position_ ||
1210                  current_candidate_->end_position() < shared->end_position()) {
1211         return;
1212       }
1213     }
1214 
1215     current_start_position_ = start_position;
1216     current_candidate_ = shared;
1217     current_candidate_closure_ = closure;
1218   }
1219 
Result()1220   SharedFunctionInfo* Result() { return current_candidate_; }
1221 
ResultClosure()1222   JSFunction* ResultClosure() { return current_candidate_closure_; }
1223 
1224  private:
1225   SharedFunctionInfo* current_candidate_;
1226   JSFunction* current_candidate_closure_;
1227   int current_start_position_;
1228   int target_position_;
1229   DisallowHeapAllocation no_gc_;
1230 };
1231 
1232 
1233 // We need to find a SFI for a literal that may not yet have been compiled yet,
1234 // and there may not be a JSFunction referencing it. Find the SFI closest to
1235 // the given position, compile it to reveal possible inner SFIs and repeat.
1236 // While we are at this, also ensure code with debug break slots so that we do
1237 // not have to compile a SFI without JSFunction, which is paifu for those that
1238 // cannot be compiled without context (need to find outer compilable SFI etc.)
FindSharedFunctionInfoInScript(Handle<Script> script,int position)1239 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
1240                                                      int position) {
1241   for (int iteration = 0;; iteration++) {
1242     // Go through all shared function infos associated with this script to
1243     // find the inner most function containing this position.
1244     // If there is no shared function info for this script at all, there is
1245     // no point in looking for it by walking the heap.
1246     if (!script->shared_function_infos()->IsWeakFixedArray()) break;
1247 
1248     SharedFunctionInfo* shared;
1249     {
1250       SharedFunctionInfoFinder finder(position);
1251       WeakFixedArray::Iterator iterator(script->shared_function_infos());
1252       SharedFunctionInfo* candidate;
1253       while ((candidate = iterator.Next<SharedFunctionInfo>())) {
1254         finder.NewCandidate(candidate);
1255       }
1256       shared = finder.Result();
1257       if (shared == NULL) break;
1258       // We found it if it's already compiled and has debug code.
1259       if (shared->HasDebugCode()) {
1260         Handle<SharedFunctionInfo> shared_handle(shared);
1261         // If the iteration count is larger than 1, we had to compile the outer
1262         // function in order to create this shared function info. So there can
1263         // be no JSFunction referencing it. We can anticipate creating a debug
1264         // info while bypassing PrepareFunctionForBreakpoints.
1265         if (iteration > 1) {
1266           AllowHeapAllocation allow_before_return;
1267           CreateDebugInfo(shared_handle);
1268         }
1269         return shared_handle;
1270       }
1271     }
1272     // If not, compile to reveal inner functions, if possible.
1273     if (shared->allows_lazy_compilation_without_context()) {
1274       HandleScope scope(isolate_);
1275       if (!Compiler::CompileDebugCode(handle(shared))) break;
1276       continue;
1277     }
1278 
1279     // If not possible, comb the heap for the best suitable compile target.
1280     JSFunction* closure;
1281     {
1282       HeapIterator it(isolate_->heap());
1283       SharedFunctionInfoFinder finder(position);
1284       while (HeapObject* object = it.next()) {
1285         JSFunction* candidate_closure = NULL;
1286         SharedFunctionInfo* candidate = NULL;
1287         if (object->IsJSFunction()) {
1288           candidate_closure = JSFunction::cast(object);
1289           candidate = candidate_closure->shared();
1290         } else if (object->IsSharedFunctionInfo()) {
1291           candidate = SharedFunctionInfo::cast(object);
1292           if (!candidate->allows_lazy_compilation_without_context()) continue;
1293         } else {
1294           continue;
1295         }
1296         if (candidate->script() == *script) {
1297           finder.NewCandidate(candidate, candidate_closure);
1298         }
1299       }
1300       closure = finder.ResultClosure();
1301       shared = finder.Result();
1302     }
1303     if (shared == NULL) break;
1304     HandleScope scope(isolate_);
1305     if (closure == NULL) {
1306       if (!Compiler::CompileDebugCode(handle(shared))) break;
1307     } else {
1308       if (!Compiler::CompileDebugCode(handle(closure))) break;
1309     }
1310   }
1311   return isolate_->factory()->undefined_value();
1312 }
1313 
1314 
1315 // Ensures the debug information is present for shared.
EnsureDebugInfo(Handle<SharedFunctionInfo> shared,Handle<JSFunction> function)1316 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
1317                             Handle<JSFunction> function) {
1318   if (!shared->IsSubjectToDebugging()) return false;
1319 
1320   // Return if we already have the debug info for shared.
1321   if (shared->HasDebugInfo()) return true;
1322 
1323   if (function.is_null()) {
1324     DCHECK(shared->HasDebugCode());
1325   } else if (!Compiler::Compile(function, CLEAR_EXCEPTION)) {
1326     return false;
1327   }
1328 
1329   if (!PrepareFunctionForBreakPoints(shared)) return false;
1330 
1331   CreateDebugInfo(shared);
1332 
1333   return true;
1334 }
1335 
1336 
CreateDebugInfo(Handle<SharedFunctionInfo> shared)1337 void Debug::CreateDebugInfo(Handle<SharedFunctionInfo> shared) {
1338   // Create the debug info object.
1339   DCHECK(shared->HasDebugCode());
1340   Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared);
1341 
1342   // Add debug info to the list.
1343   DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
1344   node->set_next(debug_info_list_);
1345   debug_info_list_ = node;
1346 }
1347 
1348 
RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info)1349 void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) {
1350   HandleScope scope(isolate_);
1351   Handle<SharedFunctionInfo> shared(debug_info->shared());
1352 
1353   DCHECK_NOT_NULL(debug_info_list_);
1354   // Run through the debug info objects to find this one and remove it.
1355   DebugInfoListNode* prev = NULL;
1356   DebugInfoListNode* current = debug_info_list_;
1357   while (current != NULL) {
1358     if (current->debug_info().is_identical_to(debug_info)) {
1359       // Unlink from list. If prev is NULL we are looking at the first element.
1360       if (prev == NULL) {
1361         debug_info_list_ = current->next();
1362       } else {
1363         prev->set_next(current->next());
1364       }
1365       delete current;
1366       shared->set_debug_info(isolate_->heap()->undefined_value());
1367       return;
1368     }
1369     // Move to next in list.
1370     prev = current;
1371     current = current->next();
1372   }
1373 
1374   UNREACHABLE();
1375 }
1376 
1377 
SetAfterBreakTarget(JavaScriptFrame * frame)1378 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
1379   after_break_target_ = NULL;
1380 
1381   if (LiveEdit::SetAfterBreakTarget(this)) return;  // LiveEdit did the job.
1382 
1383   // Continue just after the slot.
1384   after_break_target_ = frame->pc();
1385 }
1386 
1387 
IsBreakAtReturn(JavaScriptFrame * frame)1388 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
1389   HandleScope scope(isolate_);
1390 
1391   // Get the executing function in which the debug break occurred.
1392   Handle<JSFunction> function(JSFunction::cast(frame->function()));
1393   Handle<SharedFunctionInfo> shared(function->shared());
1394 
1395   // With no debug info there are no break points, so we can't be at a return.
1396   if (!shared->HasDebugInfo()) return false;
1397   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1398   Handle<Code> code(debug_info->code());
1399 #ifdef DEBUG
1400   // Get the code which is actually executing.
1401   Handle<Code> frame_code(frame->LookupCode());
1402   DCHECK(frame_code.is_identical_to(code));
1403 #endif
1404 
1405   // Find the reloc info matching the start of the debug break slot.
1406   Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength;
1407   int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
1408   for (RelocIterator it(*code, mask); !it.done(); it.next()) {
1409     if (it.rinfo()->pc() == slot_pc) return true;
1410   }
1411   return false;
1412 }
1413 
1414 
FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,LiveEdit::FrameDropMode mode)1415 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
1416                                   LiveEdit::FrameDropMode mode) {
1417   if (mode != LiveEdit::CURRENTLY_SET_MODE) {
1418     thread_local_.frame_drop_mode_ = mode;
1419   }
1420   thread_local_.break_frame_id_ = new_break_frame_id;
1421 }
1422 
1423 
IsDebugGlobal(JSGlobalObject * global)1424 bool Debug::IsDebugGlobal(JSGlobalObject* global) {
1425   return is_loaded() && global == debug_context()->global_object();
1426 }
1427 
1428 
ClearMirrorCache()1429 void Debug::ClearMirrorCache() {
1430   PostponeInterruptsScope postpone(isolate_);
1431   HandleScope scope(isolate_);
1432   CallFunction("ClearMirrorCache", 0, NULL);
1433 }
1434 
1435 
GetLoadedScripts()1436 Handle<FixedArray> Debug::GetLoadedScripts() {
1437   isolate_->heap()->CollectAllGarbage();
1438   Factory* factory = isolate_->factory();
1439   if (!factory->script_list()->IsWeakFixedArray()) {
1440     return factory->empty_fixed_array();
1441   }
1442   Handle<WeakFixedArray> array =
1443       Handle<WeakFixedArray>::cast(factory->script_list());
1444   Handle<FixedArray> results = factory->NewFixedArray(array->Length());
1445   int length = 0;
1446   {
1447     Script::Iterator iterator(isolate_);
1448     Script* script;
1449     while ((script = iterator.Next())) {
1450       if (script->HasValidSource()) results->set(length++, script);
1451     }
1452   }
1453   results->Shrink(length);
1454   return results;
1455 }
1456 
1457 
GetStepinPositions(JavaScriptFrame * frame,StackFrame::Id frame_id,List<int> * results_out)1458 void Debug::GetStepinPositions(JavaScriptFrame* frame, StackFrame::Id frame_id,
1459                                List<int>* results_out) {
1460   FrameSummary summary = GetFirstFrameSummary(frame);
1461 
1462   Handle<JSFunction> fun = Handle<JSFunction>(summary.function());
1463   Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared());
1464 
1465   if (!EnsureDebugInfo(shared, fun)) return;
1466 
1467   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1468   // Refresh frame summary if the code has been recompiled for debugging.
1469   if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame);
1470 
1471   // Find range of break points starting from the break point where execution
1472   // has stopped.
1473   Address call_pc = summary.pc() - 1;
1474   List<BreakLocation> locations;
1475   BreakLocation::FromAddressSameStatement(debug_info, call_pc, &locations);
1476 
1477   for (BreakLocation location : locations) {
1478     if (location.pc() <= summary.pc()) {
1479       // The break point is near our pc. Could be a step-in possibility,
1480       // that is currently taken by active debugger call.
1481       if (break_frame_id() == StackFrame::NO_ID) {
1482         continue;  // We are not stepping.
1483       } else {
1484         JavaScriptFrameIterator frame_it(isolate_, break_frame_id());
1485         // If our frame is a top frame and we are stepping, we can do step-in
1486         // at this place.
1487         if (frame_it.frame()->id() != frame_id) continue;
1488       }
1489     }
1490     if (location.IsCall()) results_out->Add(location.position());
1491   }
1492 }
1493 
1494 
RecordEvalCaller(Handle<Script> script)1495 void Debug::RecordEvalCaller(Handle<Script> script) {
1496   script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1497   // For eval scripts add information on the function from which eval was
1498   // called.
1499   StackTraceFrameIterator it(script->GetIsolate());
1500   if (!it.done()) {
1501     script->set_eval_from_shared(it.frame()->function()->shared());
1502     Code* code = it.frame()->LookupCode();
1503     int offset = static_cast<int>(
1504         it.frame()->pc() - code->instruction_start());
1505     script->set_eval_from_instructions_offset(offset);
1506   }
1507 }
1508 
1509 
MakeExecutionState()1510 MaybeHandle<Object> Debug::MakeExecutionState() {
1511   // Create the execution state object.
1512   Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
1513   return CallFunction("MakeExecutionState", arraysize(argv), argv);
1514 }
1515 
1516 
MakeBreakEvent(Handle<Object> break_points_hit)1517 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
1518   // Create the new break event object.
1519   Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
1520                             break_points_hit };
1521   return CallFunction("MakeBreakEvent", arraysize(argv), argv);
1522 }
1523 
1524 
MakeExceptionEvent(Handle<Object> exception,bool uncaught,Handle<Object> promise)1525 MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
1526                                               bool uncaught,
1527                                               Handle<Object> promise) {
1528   // Create the new exception event object.
1529   Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
1530                             exception,
1531                             isolate_->factory()->ToBoolean(uncaught),
1532                             promise };
1533   return CallFunction("MakeExceptionEvent", arraysize(argv), argv);
1534 }
1535 
1536 
MakeCompileEvent(Handle<Script> script,v8::DebugEvent type)1537 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
1538                                             v8::DebugEvent type) {
1539   // Create the compile event object.
1540   Handle<Object> script_wrapper = Script::GetWrapper(script);
1541   Handle<Object> argv[] = { script_wrapper,
1542                             isolate_->factory()->NewNumberFromInt(type) };
1543   return CallFunction("MakeCompileEvent", arraysize(argv), argv);
1544 }
1545 
1546 
MakePromiseEvent(Handle<JSObject> event_data)1547 MaybeHandle<Object> Debug::MakePromiseEvent(Handle<JSObject> event_data) {
1548   // Create the promise event object.
1549   Handle<Object> argv[] = { event_data };
1550   return CallFunction("MakePromiseEvent", arraysize(argv), argv);
1551 }
1552 
1553 
MakeAsyncTaskEvent(Handle<JSObject> task_event)1554 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
1555   // Create the async task event object.
1556   Handle<Object> argv[] = { task_event };
1557   return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv);
1558 }
1559 
1560 
OnThrow(Handle<Object> exception)1561 void Debug::OnThrow(Handle<Object> exception) {
1562   if (in_debug_scope() || ignore_events()) return;
1563   PrepareStepOnThrow();
1564   // Temporarily clear any scheduled_exception to allow evaluating
1565   // JavaScript from the debug event handler.
1566   HandleScope scope(isolate_);
1567   Handle<Object> scheduled_exception;
1568   if (isolate_->has_scheduled_exception()) {
1569     scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
1570     isolate_->clear_scheduled_exception();
1571   }
1572   OnException(exception, isolate_->GetPromiseOnStackOnThrow());
1573   if (!scheduled_exception.is_null()) {
1574     isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
1575   }
1576 }
1577 
1578 
OnPromiseReject(Handle<JSObject> promise,Handle<Object> value)1579 void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
1580   if (in_debug_scope() || ignore_events()) return;
1581   HandleScope scope(isolate_);
1582   // Check whether the promise has been marked as having triggered a message.
1583   Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1584   if (JSReceiver::GetDataProperty(promise, key)->IsUndefined()) {
1585     OnException(value, promise);
1586   }
1587 }
1588 
1589 
PromiseHasUserDefinedRejectHandler(Handle<JSObject> promise)1590 MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler(
1591     Handle<JSObject> promise) {
1592   Handle<JSFunction> fun = isolate_->promise_has_user_defined_reject_handler();
1593   return Execution::Call(isolate_, fun, promise, 0, NULL);
1594 }
1595 
1596 
OnException(Handle<Object> exception,Handle<Object> promise)1597 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
1598   // In our prediction, try-finally is not considered to catch.
1599   Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
1600   bool uncaught = (catch_type == Isolate::NOT_CAUGHT);
1601   if (promise->IsJSObject()) {
1602     Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
1603     // Mark the promise as already having triggered a message.
1604     Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1605     JSObject::SetProperty(jspromise, key, key, STRICT).Assert();
1606     // Check whether the promise reject is considered an uncaught exception.
1607     Handle<Object> has_reject_handler;
1608     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1609         isolate_, has_reject_handler,
1610         PromiseHasUserDefinedRejectHandler(jspromise), /* void */);
1611     uncaught = has_reject_handler->IsFalse();
1612   }
1613   // Bail out if exception breaks are not active
1614   if (uncaught) {
1615     // Uncaught exceptions are reported by either flags.
1616     if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
1617   } else {
1618     // Caught exceptions are reported is activated.
1619     if (!break_on_exception_) return;
1620   }
1621 
1622   DebugScope debug_scope(this);
1623   if (debug_scope.failed()) return;
1624 
1625   // Create the event data object.
1626   Handle<Object> event_data;
1627   // Bail out and don't call debugger if exception.
1628   if (!MakeExceptionEvent(
1629           exception, uncaught, promise).ToHandle(&event_data)) {
1630     return;
1631   }
1632 
1633   // Process debug event.
1634   ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
1635   // Return to continue execution from where the exception was thrown.
1636 }
1637 
1638 
OnDebugBreak(Handle<Object> break_points_hit,bool auto_continue)1639 void Debug::OnDebugBreak(Handle<Object> break_points_hit,
1640                             bool auto_continue) {
1641   // The caller provided for DebugScope.
1642   AssertDebugContext();
1643   // Bail out if there is no listener for this event
1644   if (ignore_events()) return;
1645 
1646   HandleScope scope(isolate_);
1647   // Create the event data object.
1648   Handle<Object> event_data;
1649   // Bail out and don't call debugger if exception.
1650   if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
1651 
1652   // Process debug event.
1653   ProcessDebugEvent(v8::Break,
1654                     Handle<JSObject>::cast(event_data),
1655                     auto_continue);
1656 }
1657 
1658 
OnCompileError(Handle<Script> script)1659 void Debug::OnCompileError(Handle<Script> script) {
1660   ProcessCompileEvent(v8::CompileError, script);
1661 }
1662 
1663 
OnBeforeCompile(Handle<Script> script)1664 void Debug::OnBeforeCompile(Handle<Script> script) {
1665   ProcessCompileEvent(v8::BeforeCompile, script);
1666 }
1667 
1668 
1669 // Handle debugger actions when a new script is compiled.
OnAfterCompile(Handle<Script> script)1670 void Debug::OnAfterCompile(Handle<Script> script) {
1671   ProcessCompileEvent(v8::AfterCompile, script);
1672 }
1673 
1674 
OnPromiseEvent(Handle<JSObject> data)1675 void Debug::OnPromiseEvent(Handle<JSObject> data) {
1676   if (in_debug_scope() || ignore_events()) return;
1677 
1678   HandleScope scope(isolate_);
1679   DebugScope debug_scope(this);
1680   if (debug_scope.failed()) return;
1681 
1682   // Create the script collected state object.
1683   Handle<Object> event_data;
1684   // Bail out and don't call debugger if exception.
1685   if (!MakePromiseEvent(data).ToHandle(&event_data)) return;
1686 
1687   // Process debug event.
1688   ProcessDebugEvent(v8::PromiseEvent,
1689                     Handle<JSObject>::cast(event_data),
1690                     true);
1691 }
1692 
1693 
OnAsyncTaskEvent(Handle<JSObject> data)1694 void Debug::OnAsyncTaskEvent(Handle<JSObject> data) {
1695   if (in_debug_scope() || ignore_events()) return;
1696 
1697   HandleScope scope(isolate_);
1698   DebugScope debug_scope(this);
1699   if (debug_scope.failed()) return;
1700 
1701   // Create the script collected state object.
1702   Handle<Object> event_data;
1703   // Bail out and don't call debugger if exception.
1704   if (!MakeAsyncTaskEvent(data).ToHandle(&event_data)) return;
1705 
1706   // Process debug event.
1707   ProcessDebugEvent(v8::AsyncTaskEvent,
1708                     Handle<JSObject>::cast(event_data),
1709                     true);
1710 }
1711 
1712 
ProcessDebugEvent(v8::DebugEvent event,Handle<JSObject> event_data,bool auto_continue)1713 void Debug::ProcessDebugEvent(v8::DebugEvent event,
1714                               Handle<JSObject> event_data,
1715                               bool auto_continue) {
1716   HandleScope scope(isolate_);
1717 
1718   // Create the execution state.
1719   Handle<Object> exec_state;
1720   // Bail out and don't call debugger if exception.
1721   if (!MakeExecutionState().ToHandle(&exec_state)) return;
1722 
1723   // First notify the message handler if any.
1724   if (message_handler_ != NULL) {
1725     NotifyMessageHandler(event,
1726                          Handle<JSObject>::cast(exec_state),
1727                          event_data,
1728                          auto_continue);
1729   }
1730   // Notify registered debug event listener. This can be either a C or
1731   // a JavaScript function. Don't call event listener for v8::Break
1732   // here, if it's only a debug command -- they will be processed later.
1733   if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
1734     CallEventCallback(event, exec_state, event_data, NULL);
1735   }
1736 }
1737 
1738 
CallEventCallback(v8::DebugEvent event,Handle<Object> exec_state,Handle<Object> event_data,v8::Debug::ClientData * client_data)1739 void Debug::CallEventCallback(v8::DebugEvent event,
1740                               Handle<Object> exec_state,
1741                               Handle<Object> event_data,
1742                               v8::Debug::ClientData* client_data) {
1743   // Prevent other interrupts from triggering, for example API callbacks,
1744   // while dispatching event listners.
1745   PostponeInterruptsScope postpone(isolate_);
1746   bool previous = in_debug_event_listener_;
1747   in_debug_event_listener_ = true;
1748   if (event_listener_->IsForeign()) {
1749     // Invoke the C debug event listener.
1750     v8::Debug::EventCallback callback =
1751         FUNCTION_CAST<v8::Debug::EventCallback>(
1752             Handle<Foreign>::cast(event_listener_)->foreign_address());
1753     EventDetailsImpl event_details(event,
1754                                    Handle<JSObject>::cast(exec_state),
1755                                    Handle<JSObject>::cast(event_data),
1756                                    event_listener_data_,
1757                                    client_data);
1758     callback(event_details);
1759     DCHECK(!isolate_->has_scheduled_exception());
1760   } else {
1761     // Invoke the JavaScript debug event listener.
1762     DCHECK(event_listener_->IsJSFunction());
1763     Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
1764                               exec_state,
1765                               event_data,
1766                               event_listener_data_ };
1767     Handle<JSReceiver> global(isolate_->global_proxy());
1768     Execution::TryCall(isolate_, Handle<JSFunction>::cast(event_listener_),
1769                        global, arraysize(argv), argv);
1770   }
1771   in_debug_event_listener_ = previous;
1772 }
1773 
1774 
ProcessCompileEvent(v8::DebugEvent event,Handle<Script> script)1775 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
1776   if (ignore_events()) return;
1777   SuppressDebug while_processing(this);
1778 
1779   bool in_nested_debug_scope = in_debug_scope();
1780   HandleScope scope(isolate_);
1781   DebugScope debug_scope(this);
1782   if (debug_scope.failed()) return;
1783 
1784   if (event == v8::AfterCompile) {
1785     // If debugging there might be script break points registered for this
1786     // script. Make sure that these break points are set.
1787     Handle<Object> argv[] = {Script::GetWrapper(script)};
1788     if (CallFunction("UpdateScriptBreakPoints", arraysize(argv), argv)
1789             .is_null()) {
1790       return;
1791     }
1792   }
1793 
1794   // Create the compile state object.
1795   Handle<Object> event_data;
1796   // Bail out and don't call debugger if exception.
1797   if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;
1798 
1799   // Don't call NotifyMessageHandler if already in debug scope to avoid running
1800   // nested command loop.
1801   if (in_nested_debug_scope) {
1802     if (event_listener_.is_null()) return;
1803     // Create the execution state.
1804     Handle<Object> exec_state;
1805     // Bail out and don't call debugger if exception.
1806     if (!MakeExecutionState().ToHandle(&exec_state)) return;
1807 
1808     CallEventCallback(event, exec_state, event_data, NULL);
1809   } else {
1810     // Process debug event.
1811     ProcessDebugEvent(event, Handle<JSObject>::cast(event_data), true);
1812   }
1813 }
1814 
1815 
GetDebugContext()1816 Handle<Context> Debug::GetDebugContext() {
1817   if (!is_loaded()) return Handle<Context>();
1818   DebugScope debug_scope(this);
1819   if (debug_scope.failed()) return Handle<Context>();
1820   // The global handle may be destroyed soon after.  Return it reboxed.
1821   return handle(*debug_context(), isolate_);
1822 }
1823 
1824 
NotifyMessageHandler(v8::DebugEvent event,Handle<JSObject> exec_state,Handle<JSObject> event_data,bool auto_continue)1825 void Debug::NotifyMessageHandler(v8::DebugEvent event,
1826                                  Handle<JSObject> exec_state,
1827                                  Handle<JSObject> event_data,
1828                                  bool auto_continue) {
1829   // Prevent other interrupts from triggering, for example API callbacks,
1830   // while dispatching message handler callbacks.
1831   PostponeInterruptsScope no_interrupts(isolate_);
1832   DCHECK(is_active_);
1833   HandleScope scope(isolate_);
1834   // Process the individual events.
1835   bool sendEventMessage = false;
1836   switch (event) {
1837     case v8::Break:
1838       sendEventMessage = !auto_continue;
1839       break;
1840     case v8::NewFunction:
1841     case v8::BeforeCompile:
1842     case v8::CompileError:
1843     case v8::PromiseEvent:
1844     case v8::AsyncTaskEvent:
1845       break;
1846     case v8::Exception:
1847     case v8::AfterCompile:
1848       sendEventMessage = true;
1849       break;
1850   }
1851 
1852   // The debug command interrupt flag might have been set when the command was
1853   // added. It should be enough to clear the flag only once while we are in the
1854   // debugger.
1855   DCHECK(in_debug_scope());
1856   isolate_->stack_guard()->ClearDebugCommand();
1857 
1858   // Notify the debugger that a debug event has occurred unless auto continue is
1859   // active in which case no event is send.
1860   if (sendEventMessage) {
1861     MessageImpl message = MessageImpl::NewEvent(
1862         event,
1863         auto_continue,
1864         Handle<JSObject>::cast(exec_state),
1865         Handle<JSObject>::cast(event_data));
1866     InvokeMessageHandler(message);
1867   }
1868 
1869   // If auto continue don't make the event cause a break, but process messages
1870   // in the queue if any. For script collected events don't even process
1871   // messages in the queue as the execution state might not be what is expected
1872   // by the client.
1873   if (auto_continue && !has_commands()) return;
1874 
1875   // DebugCommandProcessor goes here.
1876   bool running = auto_continue;
1877 
1878   Handle<Object> cmd_processor_ctor = Object::GetProperty(
1879       isolate_, exec_state, "debugCommandProcessor").ToHandleChecked();
1880   Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
1881   Handle<Object> cmd_processor = Execution::Call(
1882       isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked();
1883   Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
1884       Object::GetProperty(
1885           isolate_, cmd_processor, "processDebugRequest").ToHandleChecked());
1886   Handle<Object> is_running = Object::GetProperty(
1887       isolate_, cmd_processor, "isRunning").ToHandleChecked();
1888 
1889   // Process requests from the debugger.
1890   do {
1891     // Wait for new command in the queue.
1892     command_received_.Wait();
1893 
1894     // Get the command from the queue.
1895     CommandMessage command = command_queue_.Get();
1896     isolate_->logger()->DebugTag(
1897         "Got request from command queue, in interactive loop.");
1898     if (!is_active()) {
1899       // Delete command text and user data.
1900       command.Dispose();
1901       return;
1902     }
1903 
1904     Vector<const uc16> command_text(
1905         const_cast<const uc16*>(command.text().start()),
1906         command.text().length());
1907     Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
1908         command_text).ToHandleChecked();
1909     Handle<Object> request_args[] = { request_text };
1910     Handle<Object> answer_value;
1911     Handle<String> answer;
1912     MaybeHandle<Object> maybe_exception;
1913     MaybeHandle<Object> maybe_result =
1914         Execution::TryCall(isolate_, process_debug_request, cmd_processor, 1,
1915                            request_args, &maybe_exception);
1916 
1917     if (maybe_result.ToHandle(&answer_value)) {
1918       if (answer_value->IsUndefined()) {
1919         answer = isolate_->factory()->empty_string();
1920       } else {
1921         answer = Handle<String>::cast(answer_value);
1922       }
1923 
1924       // Log the JSON request/response.
1925       if (FLAG_trace_debug_json) {
1926         PrintF("%s\n", request_text->ToCString().get());
1927         PrintF("%s\n", answer->ToCString().get());
1928       }
1929 
1930       Handle<Object> is_running_args[] = { answer };
1931       maybe_result = Execution::Call(
1932           isolate_, is_running, cmd_processor, 1, is_running_args);
1933       Handle<Object> result;
1934       if (!maybe_result.ToHandle(&result)) break;
1935       running = result->IsTrue();
1936     } else {
1937       Handle<Object> exception;
1938       if (!maybe_exception.ToHandle(&exception)) break;
1939       Handle<Object> result;
1940       if (!Object::ToString(isolate_, exception).ToHandle(&result)) break;
1941       answer = Handle<String>::cast(result);
1942     }
1943 
1944     // Return the result.
1945     MessageImpl message = MessageImpl::NewResponse(
1946         event, running, exec_state, event_data, answer, command.client_data());
1947     InvokeMessageHandler(message);
1948     command.Dispose();
1949 
1950     // Return from debug event processing if either the VM is put into the
1951     // running state (through a continue command) or auto continue is active
1952     // and there are no more commands queued.
1953   } while (!running || has_commands());
1954   command_queue_.Clear();
1955 }
1956 
1957 
SetEventListener(Handle<Object> callback,Handle<Object> data)1958 void Debug::SetEventListener(Handle<Object> callback,
1959                              Handle<Object> data) {
1960   GlobalHandles* global_handles = isolate_->global_handles();
1961 
1962   // Remove existing entry.
1963   GlobalHandles::Destroy(event_listener_.location());
1964   event_listener_ = Handle<Object>();
1965   GlobalHandles::Destroy(event_listener_data_.location());
1966   event_listener_data_ = Handle<Object>();
1967 
1968   // Set new entry.
1969   if (!callback->IsUndefined() && !callback->IsNull()) {
1970     event_listener_ = global_handles->Create(*callback);
1971     if (data.is_null()) data = isolate_->factory()->undefined_value();
1972     event_listener_data_ = global_handles->Create(*data);
1973   }
1974 
1975   UpdateState();
1976 }
1977 
1978 
SetMessageHandler(v8::Debug::MessageHandler handler)1979 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
1980   message_handler_ = handler;
1981   UpdateState();
1982   if (handler == NULL && in_debug_scope()) {
1983     // Send an empty command to the debugger if in a break to make JavaScript
1984     // run again if the debugger is closed.
1985     EnqueueCommandMessage(Vector<const uint16_t>::empty());
1986   }
1987 }
1988 
1989 
1990 
UpdateState()1991 void Debug::UpdateState() {
1992   bool is_active = message_handler_ != NULL || !event_listener_.is_null();
1993   if (is_active || in_debug_scope()) {
1994     // Note that the debug context could have already been loaded to
1995     // bootstrap test cases.
1996     isolate_->compilation_cache()->Disable();
1997     is_active = Load();
1998   } else if (is_loaded()) {
1999     isolate_->compilation_cache()->Enable();
2000     Unload();
2001   }
2002   is_active_ = is_active;
2003 }
2004 
2005 
2006 // Calls the registered debug message handler. This callback is part of the
2007 // public API.
InvokeMessageHandler(MessageImpl message)2008 void Debug::InvokeMessageHandler(MessageImpl message) {
2009   if (message_handler_ != NULL) message_handler_(message);
2010 }
2011 
2012 
2013 // Puts a command coming from the public API on the queue.  Creates
2014 // a copy of the command string managed by the debugger.  Up to this
2015 // point, the command data was managed by the API client.  Called
2016 // by the API client thread.
EnqueueCommandMessage(Vector<const uint16_t> command,v8::Debug::ClientData * client_data)2017 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
2018                                   v8::Debug::ClientData* client_data) {
2019   // Need to cast away const.
2020   CommandMessage message = CommandMessage::New(
2021       Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
2022                        command.length()),
2023       client_data);
2024   isolate_->logger()->DebugTag("Put command on command_queue.");
2025   command_queue_.Put(message);
2026   command_received_.Signal();
2027 
2028   // Set the debug command break flag to have the command processed.
2029   if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
2030 }
2031 
2032 
Call(Handle<Object> fun,Handle<Object> data)2033 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
2034   DebugScope debug_scope(this);
2035   if (debug_scope.failed()) return isolate_->factory()->undefined_value();
2036 
2037   // Create the execution state.
2038   Handle<Object> exec_state;
2039   if (!MakeExecutionState().ToHandle(&exec_state)) {
2040     return isolate_->factory()->undefined_value();
2041   }
2042 
2043   Handle<Object> argv[] = { exec_state, data };
2044   return Execution::Call(
2045       isolate_,
2046       fun,
2047       Handle<Object>(debug_context()->global_proxy(), isolate_),
2048       arraysize(argv),
2049       argv);
2050 }
2051 
2052 
HandleDebugBreak()2053 void Debug::HandleDebugBreak() {
2054   // Ignore debug break during bootstrapping.
2055   if (isolate_->bootstrapper()->IsActive()) return;
2056   // Just continue if breaks are disabled.
2057   if (break_disabled()) return;
2058   // Ignore debug break if debugger is not active.
2059   if (!is_active()) return;
2060 
2061   StackLimitCheck check(isolate_);
2062   if (check.HasOverflowed()) return;
2063 
2064   { JavaScriptFrameIterator it(isolate_);
2065     DCHECK(!it.done());
2066     Object* fun = it.frame()->function();
2067     if (fun && fun->IsJSFunction()) {
2068       // Don't stop in builtin functions.
2069       if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return;
2070       JSGlobalObject* global =
2071           JSFunction::cast(fun)->context()->global_object();
2072       // Don't stop in debugger functions.
2073       if (IsDebugGlobal(global)) return;
2074     }
2075   }
2076 
2077   // Collect the break state before clearing the flags.
2078   bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
2079                             !isolate_->stack_guard()->CheckDebugBreak();
2080 
2081   isolate_->stack_guard()->ClearDebugBreak();
2082 
2083   // Clear stepping to avoid duplicate breaks.
2084   ClearStepping();
2085 
2086   ProcessDebugMessages(debug_command_only);
2087 }
2088 
2089 
ProcessDebugMessages(bool debug_command_only)2090 void Debug::ProcessDebugMessages(bool debug_command_only) {
2091   isolate_->stack_guard()->ClearDebugCommand();
2092 
2093   StackLimitCheck check(isolate_);
2094   if (check.HasOverflowed()) return;
2095 
2096   HandleScope scope(isolate_);
2097   DebugScope debug_scope(this);
2098   if (debug_scope.failed()) return;
2099 
2100   // Notify the debug event listeners. Indicate auto continue if the break was
2101   // a debug command break.
2102   OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
2103 }
2104 
2105 
DebugScope(Debug * debug)2106 DebugScope::DebugScope(Debug* debug)
2107     : debug_(debug),
2108       prev_(debug->debugger_entry()),
2109       save_(debug_->isolate_),
2110       no_termination_exceptons_(debug_->isolate_,
2111                                 StackGuard::TERMINATE_EXECUTION) {
2112   // Link recursive debugger entry.
2113   base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2114                         reinterpret_cast<base::AtomicWord>(this));
2115 
2116   // Store the previous break id and frame id.
2117   break_id_ = debug_->break_id();
2118   break_frame_id_ = debug_->break_frame_id();
2119 
2120   // Create the new break info. If there is no JavaScript frames there is no
2121   // break frame id.
2122   JavaScriptFrameIterator it(isolate());
2123   bool has_js_frames = !it.done();
2124   debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
2125                                                         : StackFrame::NO_ID;
2126   debug_->SetNextBreakId();
2127 
2128   debug_->UpdateState();
2129   // Make sure that debugger is loaded and enter the debugger context.
2130   // The previous context is kept in save_.
2131   failed_ = !debug_->is_loaded();
2132   if (!failed_) isolate()->set_context(*debug->debug_context());
2133 }
2134 
2135 
~DebugScope()2136 DebugScope::~DebugScope() {
2137   if (!failed_ && prev_ == NULL) {
2138     // Clear mirror cache when leaving the debugger. Skip this if there is a
2139     // pending exception as clearing the mirror cache calls back into
2140     // JavaScript. This can happen if the v8::Debug::Call is used in which
2141     // case the exception should end up in the calling code.
2142     if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
2143 
2144     // If there are commands in the queue when leaving the debugger request
2145     // that these commands are processed.
2146     if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
2147   }
2148 
2149   // Leaving this debugger entry.
2150   base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2151                         reinterpret_cast<base::AtomicWord>(prev_));
2152 
2153   // Restore to the previous break state.
2154   debug_->thread_local_.break_frame_id_ = break_frame_id_;
2155   debug_->thread_local_.break_id_ = break_id_;
2156 
2157   debug_->UpdateState();
2158 }
2159 
2160 
NewEvent(DebugEvent event,bool running,Handle<JSObject> exec_state,Handle<JSObject> event_data)2161 MessageImpl MessageImpl::NewEvent(DebugEvent event,
2162                                   bool running,
2163                                   Handle<JSObject> exec_state,
2164                                   Handle<JSObject> event_data) {
2165   MessageImpl message(true, event, running,
2166                       exec_state, event_data, Handle<String>(), NULL);
2167   return message;
2168 }
2169 
2170 
NewResponse(DebugEvent event,bool running,Handle<JSObject> exec_state,Handle<JSObject> event_data,Handle<String> response_json,v8::Debug::ClientData * client_data)2171 MessageImpl MessageImpl::NewResponse(DebugEvent event,
2172                                      bool running,
2173                                      Handle<JSObject> exec_state,
2174                                      Handle<JSObject> event_data,
2175                                      Handle<String> response_json,
2176                                      v8::Debug::ClientData* client_data) {
2177   MessageImpl message(false, event, running,
2178                       exec_state, event_data, response_json, client_data);
2179   return message;
2180 }
2181 
2182 
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)2183 MessageImpl::MessageImpl(bool is_event,
2184                          DebugEvent event,
2185                          bool running,
2186                          Handle<JSObject> exec_state,
2187                          Handle<JSObject> event_data,
2188                          Handle<String> response_json,
2189                          v8::Debug::ClientData* client_data)
2190     : is_event_(is_event),
2191       event_(event),
2192       running_(running),
2193       exec_state_(exec_state),
2194       event_data_(event_data),
2195       response_json_(response_json),
2196       client_data_(client_data) {}
2197 
2198 
IsEvent() const2199 bool MessageImpl::IsEvent() const {
2200   return is_event_;
2201 }
2202 
2203 
IsResponse() const2204 bool MessageImpl::IsResponse() const {
2205   return !is_event_;
2206 }
2207 
2208 
GetEvent() const2209 DebugEvent MessageImpl::GetEvent() const {
2210   return event_;
2211 }
2212 
2213 
WillStartRunning() const2214 bool MessageImpl::WillStartRunning() const {
2215   return running_;
2216 }
2217 
2218 
GetExecutionState() const2219 v8::Local<v8::Object> MessageImpl::GetExecutionState() const {
2220   return v8::Utils::ToLocal(exec_state_);
2221 }
2222 
2223 
GetIsolate() const2224 v8::Isolate* MessageImpl::GetIsolate() const {
2225   return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2226 }
2227 
2228 
GetEventData() const2229 v8::Local<v8::Object> MessageImpl::GetEventData() const {
2230   return v8::Utils::ToLocal(event_data_);
2231 }
2232 
2233 
GetJSON() const2234 v8::Local<v8::String> MessageImpl::GetJSON() const {
2235   Isolate* isolate = event_data_->GetIsolate();
2236   v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
2237 
2238   if (IsEvent()) {
2239     // Call toJSONProtocol on the debug event object.
2240     Handle<Object> fun = Object::GetProperty(
2241         isolate, event_data_, "toJSONProtocol").ToHandleChecked();
2242     if (!fun->IsJSFunction()) {
2243       return v8::Local<v8::String>();
2244     }
2245 
2246     MaybeHandle<Object> maybe_json =
2247         Execution::TryCall(isolate, fun, event_data_, 0, NULL);
2248     Handle<Object> json;
2249     if (!maybe_json.ToHandle(&json) || !json->IsString()) {
2250       return v8::Local<v8::String>();
2251     }
2252     return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
2253   } else {
2254     return v8::Utils::ToLocal(response_json_);
2255   }
2256 }
2257 
2258 
GetEventContext() const2259 v8::Local<v8::Context> MessageImpl::GetEventContext() const {
2260   Isolate* isolate = event_data_->GetIsolate();
2261   v8::Local<v8::Context> context = GetDebugEventContext(isolate);
2262   // Isolate::context() may be NULL when "script collected" event occurs.
2263   DCHECK(!context.IsEmpty());
2264   return context;
2265 }
2266 
2267 
GetClientData() const2268 v8::Debug::ClientData* MessageImpl::GetClientData() const {
2269   return client_data_;
2270 }
2271 
2272 
EventDetailsImpl(DebugEvent event,Handle<JSObject> exec_state,Handle<JSObject> event_data,Handle<Object> callback_data,v8::Debug::ClientData * client_data)2273 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
2274                                    Handle<JSObject> exec_state,
2275                                    Handle<JSObject> event_data,
2276                                    Handle<Object> callback_data,
2277                                    v8::Debug::ClientData* client_data)
2278     : event_(event),
2279       exec_state_(exec_state),
2280       event_data_(event_data),
2281       callback_data_(callback_data),
2282       client_data_(client_data) {}
2283 
2284 
GetEvent() const2285 DebugEvent EventDetailsImpl::GetEvent() const {
2286   return event_;
2287 }
2288 
2289 
GetExecutionState() const2290 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const {
2291   return v8::Utils::ToLocal(exec_state_);
2292 }
2293 
2294 
GetEventData() const2295 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const {
2296   return v8::Utils::ToLocal(event_data_);
2297 }
2298 
2299 
GetEventContext() const2300 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const {
2301   return GetDebugEventContext(exec_state_->GetIsolate());
2302 }
2303 
2304 
GetCallbackData() const2305 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const {
2306   return v8::Utils::ToLocal(callback_data_);
2307 }
2308 
2309 
GetClientData() const2310 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
2311   return client_data_;
2312 }
2313 
2314 
CommandMessage()2315 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
2316                                    client_data_(NULL) {
2317 }
2318 
2319 
CommandMessage(const Vector<uint16_t> & text,v8::Debug::ClientData * data)2320 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
2321                                v8::Debug::ClientData* data)
2322     : text_(text),
2323       client_data_(data) {
2324 }
2325 
2326 
Dispose()2327 void CommandMessage::Dispose() {
2328   text_.Dispose();
2329   delete client_data_;
2330   client_data_ = NULL;
2331 }
2332 
2333 
New(const Vector<uint16_t> & command,v8::Debug::ClientData * data)2334 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
2335                                    v8::Debug::ClientData* data) {
2336   return CommandMessage(command.Clone(), data);
2337 }
2338 
2339 
CommandMessageQueue(int size)2340 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
2341                                                      size_(size) {
2342   messages_ = NewArray<CommandMessage>(size);
2343 }
2344 
2345 
~CommandMessageQueue()2346 CommandMessageQueue::~CommandMessageQueue() {
2347   while (!IsEmpty()) Get().Dispose();
2348   DeleteArray(messages_);
2349 }
2350 
2351 
Get()2352 CommandMessage CommandMessageQueue::Get() {
2353   DCHECK(!IsEmpty());
2354   int result = start_;
2355   start_ = (start_ + 1) % size_;
2356   return messages_[result];
2357 }
2358 
2359 
Put(const CommandMessage & message)2360 void CommandMessageQueue::Put(const CommandMessage& message) {
2361   if ((end_ + 1) % size_ == start_) {
2362     Expand();
2363   }
2364   messages_[end_] = message;
2365   end_ = (end_ + 1) % size_;
2366 }
2367 
2368 
Expand()2369 void CommandMessageQueue::Expand() {
2370   CommandMessageQueue new_queue(size_ * 2);
2371   while (!IsEmpty()) {
2372     new_queue.Put(Get());
2373   }
2374   CommandMessage* array_to_free = messages_;
2375   *this = new_queue;
2376   new_queue.messages_ = array_to_free;
2377   // Make the new_queue empty so that it doesn't call Dispose on any messages.
2378   new_queue.start_ = new_queue.end_;
2379   // Automatic destructor called on new_queue, freeing array_to_free.
2380 }
2381 
2382 
LockingCommandMessageQueue(Logger * logger,int size)2383 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
2384     : logger_(logger), queue_(size) {}
2385 
2386 
IsEmpty() const2387 bool LockingCommandMessageQueue::IsEmpty() const {
2388   base::LockGuard<base::Mutex> lock_guard(&mutex_);
2389   return queue_.IsEmpty();
2390 }
2391 
2392 
Get()2393 CommandMessage LockingCommandMessageQueue::Get() {
2394   base::LockGuard<base::Mutex> lock_guard(&mutex_);
2395   CommandMessage result = queue_.Get();
2396   logger_->DebugEvent("Get", result.text());
2397   return result;
2398 }
2399 
2400 
Put(const CommandMessage & message)2401 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
2402   base::LockGuard<base::Mutex> lock_guard(&mutex_);
2403   queue_.Put(message);
2404   logger_->DebugEvent("Put", message.text());
2405 }
2406 
2407 
Clear()2408 void LockingCommandMessageQueue::Clear() {
2409   base::LockGuard<base::Mutex> lock_guard(&mutex_);
2410   queue_.Clear();
2411 }
2412 
2413 }  // namespace internal
2414 }  // namespace v8
2415