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