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