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.
5 #include "src/debug/debug.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"
21 #include "src/messages.h"
22 #include "src/snapshot/natives.h"
24 #include "include/v8-debug.h"
29 Debug::Debug(Isolate* isolate)
30 : debug_context_(Handle<Context>()),
31 event_listener_(Handle<Object>()),
32 event_listener_data_(Handle<Object>()),
33 message_handler_(NULL),
35 command_queue_(isolate->logger(), kQueueInitialSize),
37 is_suppressed_(false),
38 live_edit_enabled_(true), // TODO(yangguo): set to false by default.
39 break_disabled_(false),
40 in_debug_event_listener_(false),
41 break_on_exception_(false),
42 break_on_uncaught_exception_(false),
43 debug_info_list_(NULL),
49 static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
50 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
51 // Isolate::context() may have been NULL when "script collected" event
53 if (context.is_null()) return v8::Local<v8::Context>();
54 Handle<Context> native_context(context->native_context());
55 return v8::Utils::ToLocal(native_context);
59 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo,
60 int position, int statement_position)
61 : debug_info_(debug_info),
62 pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())),
63 rmode_(rinfo->rmode()),
66 statement_position_(statement_position) {}
69 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
70 BreakLocatorType type)
71 : debug_info_(debug_info),
72 reloc_iterator_(debug_info->code(), GetModeMask(type)),
75 statement_position_(1) {
80 int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) {
82 mask |= RelocInfo::ModeMask(RelocInfo::POSITION);
83 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION);
84 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
85 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
86 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CONSTRUCT_CALL);
87 if (type == ALL_BREAK_LOCATIONS) {
88 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
89 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT);
95 void BreakLocation::Iterator::Next() {
96 DisallowHeapAllocation no_gc;
99 // Iterate through reloc info for code and original code stopping at each
100 // breakable code target.
101 bool first = break_index_ == -1;
103 if (!first) reloc_iterator_.next();
107 // Whenever a statement position or (plain) position is passed update the
108 // current value of these.
109 if (RelocInfo::IsPosition(rmode())) {
110 if (RelocInfo::IsStatementPosition(rmode())) {
111 statement_position_ = static_cast<int>(
112 rinfo()->data() - debug_info_->shared()->start_position());
114 // Always update the position as we don't want that to be before the
115 // statement position.
116 position_ = static_cast<int>(rinfo()->data() -
117 debug_info_->shared()->start_position());
118 DCHECK(position_ >= 0);
119 DCHECK(statement_position_ >= 0);
123 DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) ||
124 RelocInfo::IsDebuggerStatement(rmode()));
126 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
127 // Set the positions to the end of the function.
128 if (debug_info_->shared()->HasSourceCode()) {
129 position_ = debug_info_->shared()->end_position() -
130 debug_info_->shared()->start_position() - 1;
134 statement_position_ = position_;
143 // Find the break point at the supplied address, or the closest one before
145 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info,
146 BreakLocatorType type, Address pc) {
147 Iterator it(debug_info, type);
148 it.SkipTo(BreakIndexFromAddress(debug_info, type, pc));
149 return it.GetBreakLocation();
153 // Find the break point at the supplied address, or the closest one before
155 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info,
156 BreakLocatorType type, Address pc,
157 List<BreakLocation>* result_out) {
158 int break_index = BreakIndexFromAddress(debug_info, type, pc);
159 Iterator it(debug_info, type);
160 it.SkipTo(break_index);
161 int statement_position = it.statement_position();
162 while (!it.Done() && it.statement_position() == statement_position) {
163 result_out->Add(it.GetBreakLocation());
169 int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info,
170 BreakLocatorType type, Address pc) {
171 // Run through all break points to locate the one closest to the address.
172 int closest_break = 0;
173 int distance = kMaxInt;
174 for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
175 // Check if this break point is closer that what was previously found.
176 if (it.pc() <= pc && pc - it.pc() < distance) {
177 closest_break = it.break_index();
178 distance = static_cast<int>(pc - it.pc());
179 // Check whether we can't get any closer.
180 if (distance == 0) break;
183 return closest_break;
187 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
188 BreakLocatorType type, int position,
189 BreakPositionAlignment alignment) {
190 // Run through all break points to locate the one closest to the source
192 int closest_break = 0;
193 int distance = kMaxInt;
195 for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
197 if (alignment == STATEMENT_ALIGNED) {
198 next_position = it.statement_position();
200 DCHECK(alignment == BREAK_POSITION_ALIGNED);
201 next_position = it.position();
203 if (position <= next_position && next_position - position < distance) {
204 closest_break = it.break_index();
205 distance = next_position - position;
206 // Check whether we can't get any closer.
207 if (distance == 0) break;
211 Iterator it(debug_info, type);
212 it.SkipTo(closest_break);
213 return it.GetBreakLocation();
217 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) {
218 // If there is not already a real break point here patch code with debug
220 if (!HasBreakPoint()) SetDebugBreak();
221 DCHECK(IsDebugBreak() || IsDebuggerStatement());
222 // Set the break point information.
223 DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_,
224 statement_position_, break_point_object);
228 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
229 // Clear the break point information.
230 DebugInfo::ClearBreakPoint(debug_info_, pc_offset_, break_point_object);
231 // If there are no more break points here remove the debug break.
232 if (!HasBreakPoint()) {
234 DCHECK(!IsDebugBreak());
239 void BreakLocation::SetOneShot() {
240 // Debugger statement always calls debugger. No need to modify it.
241 if (IsDebuggerStatement()) return;
243 // If there is a real break point here no more to do.
244 if (HasBreakPoint()) {
245 DCHECK(IsDebugBreak());
249 // Patch code with debug break.
254 void BreakLocation::ClearOneShot() {
255 // Debugger statement always calls debugger. No need to modify it.
256 if (IsDebuggerStatement()) return;
258 // If there is a real break point here no more to do.
259 if (HasBreakPoint()) {
260 DCHECK(IsDebugBreak());
264 // Patch code removing debug break.
266 DCHECK(!IsDebugBreak());
270 void BreakLocation::SetDebugBreak() {
271 // Debugger statement always calls debugger. No need to modify it.
272 if (IsDebuggerStatement()) return;
274 // If there is already a break point here just return. This might happen if
275 // the same code is flooded with break points twice. Flooding the same
276 // function twice might happen when stepping in a function with an exception
277 // handler as the handler and the function is the same.
278 if (IsDebugBreak()) return;
280 DCHECK(IsDebugBreakSlot());
281 Builtins* builtins = debug_info_->GetIsolate()->builtins();
282 Handle<Code> target =
283 IsReturn() ? builtins->Return_DebugBreak() : builtins->Slot_DebugBreak();
284 DebugCodegen::PatchDebugBreakSlot(pc(), target);
285 DCHECK(IsDebugBreak());
289 void BreakLocation::ClearDebugBreak() {
290 // Debugger statement always calls debugger. No need to modify it.
291 if (IsDebuggerStatement()) return;
293 DCHECK(IsDebugBreakSlot());
294 DebugCodegen::ClearDebugBreakSlot(pc());
295 DCHECK(!IsDebugBreak());
299 bool BreakLocation::IsStepInLocation() const {
300 return IsConstructCall() || IsCall();
304 bool BreakLocation::IsDebugBreak() const {
305 if (IsDebugBreakSlot()) {
306 return rinfo().IsPatchedDebugBreakSlotSequence();
312 Handle<Object> BreakLocation::BreakPointObjects() const {
313 return debug_info_->GetBreakPointObjects(pc_offset_);
317 // Threading support.
318 void Debug::ThreadInit() {
319 thread_local_.break_count_ = 0;
320 thread_local_.break_id_ = 0;
321 thread_local_.break_frame_id_ = StackFrame::NO_ID;
322 thread_local_.last_step_action_ = StepNone;
323 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
324 thread_local_.step_count_ = 0;
325 thread_local_.last_fp_ = 0;
326 thread_local_.queued_step_count_ = 0;
327 thread_local_.step_into_fp_ = 0;
328 thread_local_.step_out_fp_ = 0;
329 // TODO(isolates): frames_are_dropped_?
330 base::NoBarrier_Store(&thread_local_.current_debug_scope_,
331 static_cast<base::AtomicWord>(0));
332 thread_local_.restarter_frame_function_pointer_ = NULL;
336 char* Debug::ArchiveDebug(char* storage) {
338 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
340 return storage + ArchiveSpacePerThread();
344 char* Debug::RestoreDebug(char* storage) {
345 char* from = storage;
346 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
347 return storage + ArchiveSpacePerThread();
351 int Debug::ArchiveSpacePerThread() {
352 return sizeof(ThreadLocal);
356 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
357 // Globalize the request debug info object and make it weak.
358 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
360 Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location();
364 DebugInfoListNode::~DebugInfoListNode() {
365 if (debug_info_ == nullptr) return;
366 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_));
367 debug_info_ = nullptr;
372 // Return if debugger is already loaded.
373 if (is_loaded()) return true;
375 // Bail out if we're already in the process of compiling the native
376 // JavaScript source code for the debugger.
377 if (is_suppressed_) return false;
378 SuppressDebug while_loading(this);
380 // Disable breakpoints and interrupts while compiling and running the
381 // debugger scripts including the context creation code.
382 DisableBreak disable(this, true);
383 PostponeInterruptsScope postpone(isolate_);
385 // Create the debugger context.
386 HandleScope scope(isolate_);
387 ExtensionConfiguration no_extensions;
388 Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
389 MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
392 // Fail if no context could be created.
393 if (context.is_null()) return false;
395 debug_context_ = Handle<Context>::cast(
396 isolate_->global_handles()->Create(*context));
401 void Debug::Unload() {
402 ClearAllBreakPoints();
405 // Return debugger is not loaded.
406 if (!is_loaded()) return;
408 // Clear debugger context global handle.
409 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
410 debug_context_ = Handle<Context>();
414 void Debug::Break(Arguments args, JavaScriptFrame* frame) {
415 Heap* heap = isolate_->heap();
416 HandleScope scope(isolate_);
417 DCHECK(args.length() == 0);
419 // Initialize LiveEdit.
420 LiveEdit::InitializeThreadLocal(this);
422 // Just continue if breaks are disabled or debugger cannot be loaded.
423 if (break_disabled()) return;
425 // Enter the debugger.
426 DebugScope debug_scope(this);
427 if (debug_scope.failed()) return;
429 // Postpone interrupt during breakpoint processing.
430 PostponeInterruptsScope postpone(isolate_);
432 // Get the debug info (create it if it does not exist).
433 Handle<JSFunction> function(frame->function());
434 Handle<SharedFunctionInfo> shared(function->shared());
435 if (!EnsureDebugInfo(shared, function)) {
436 // Return if we failed to retrieve the debug info.
439 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
441 // Find the break point where execution has stopped.
442 // PC points to the instruction after the current one, possibly a break
443 // location as well. So the "- 1" to exclude it from the search.
444 Address call_pc = frame->pc() - 1;
445 BreakLocation break_location =
446 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
448 // Check whether step next reached a new statement.
449 if (!StepNextContinue(&break_location, frame)) {
450 // Decrease steps left if performing multiple steps.
451 if (thread_local_.step_count_ > 0) {
452 thread_local_.step_count_--;
456 // If there is one or more real break points check whether any of these are
458 Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
459 if (break_location.HasBreakPoint()) {
460 Handle<Object> break_point_objects = break_location.BreakPointObjects();
461 break_points_hit = CheckBreakPoints(break_point_objects);
464 // If step out is active skip everything until the frame where we need to step
465 // out to is reached, unless real breakpoint is hit.
466 if (StepOutActive() &&
467 frame->fp() != thread_local_.step_out_fp_ &&
468 break_points_hit->IsUndefined() ) {
469 // Step count should always be 0 for StepOut.
470 DCHECK(thread_local_.step_count_ == 0);
471 } else if (!break_points_hit->IsUndefined() ||
472 (thread_local_.last_step_action_ != StepNone &&
473 thread_local_.step_count_ == 0)) {
474 // Notify debugger if a real break point is triggered or if performing
475 // single stepping with no more steps to perform. Otherwise do another step.
477 // Clear all current stepping setup.
480 if (thread_local_.queued_step_count_ > 0) {
481 // Perform queued steps
482 int step_count = thread_local_.queued_step_count_;
485 thread_local_.queued_step_count_ = 0;
487 PrepareStep(StepNext, step_count, StackFrame::NO_ID);
489 // Notify the debug event listeners.
490 OnDebugBreak(break_points_hit, false);
492 } else if (thread_local_.last_step_action_ != StepNone) {
493 // Hold on to last step action as it is cleared by the call to
495 StepAction step_action = thread_local_.last_step_action_;
496 int step_count = thread_local_.step_count_;
498 // If StepNext goes deeper in code, StepOut until original frame
499 // and keep step count queued up in the meantime.
500 if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
501 // Count frames until target frame
503 JavaScriptFrameIterator it(isolate_);
504 while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
509 // Check that we indeed found the frame we are looking for.
510 CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
511 if (step_count > 1) {
512 // Save old count and action to continue stepping after StepOut.
513 thread_local_.queued_step_count_ = step_count - 1;
516 // Set up for StepOut to reach target frame.
517 step_action = StepOut;
521 // Clear all current stepping setup.
524 // Set up for the remaining steps.
525 PrepareStep(step_action, step_count, StackFrame::NO_ID);
530 // Check the break point objects for whether one or more are actually
531 // triggered. This function returns a JSArray with the break point objects
532 // which is triggered.
533 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
534 Factory* factory = isolate_->factory();
536 // Count the number of break points hit. If there are multiple break points
537 // they are in a FixedArray.
538 Handle<FixedArray> break_points_hit;
539 int break_points_hit_count = 0;
540 DCHECK(!break_point_objects->IsUndefined());
541 if (break_point_objects->IsFixedArray()) {
542 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
543 break_points_hit = factory->NewFixedArray(array->length());
544 for (int i = 0; i < array->length(); i++) {
545 Handle<Object> o(array->get(i), isolate_);
546 if (CheckBreakPoint(o)) {
547 break_points_hit->set(break_points_hit_count++, *o);
551 break_points_hit = factory->NewFixedArray(1);
552 if (CheckBreakPoint(break_point_objects)) {
553 break_points_hit->set(break_points_hit_count++, *break_point_objects);
557 // Return undefined if no break points were triggered.
558 if (break_points_hit_count == 0) {
559 return factory->undefined_value();
561 // Return break points hit as a JSArray.
562 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
563 result->set_length(Smi::FromInt(break_points_hit_count));
568 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
569 Handle<Object> args[]) {
570 PostponeInterruptsScope no_interrupts(isolate_);
571 AssertDebugContext();
572 Handle<Object> holder = isolate_->natives_utils_object();
573 Handle<JSFunction> fun = Handle<JSFunction>::cast(
574 Object::GetProperty(isolate_, holder, name, STRICT).ToHandleChecked());
575 Handle<Object> undefined = isolate_->factory()->undefined_value();
576 return Execution::TryCall(fun, undefined, argc, args);
580 // Check whether a single break point object is triggered.
581 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
582 Factory* factory = isolate_->factory();
583 HandleScope scope(isolate_);
585 // Ignore check if break point object is not a JSObject.
586 if (!break_point_object->IsJSObject()) return true;
588 // Get the break id as an object.
589 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
591 // Call IsBreakPointTriggered.
592 Handle<Object> argv[] = { break_id, break_point_object };
593 Handle<Object> result;
594 if (!CallFunction("IsBreakPointTriggered", arraysize(argv), argv)
595 .ToHandle(&result)) {
599 // Return whether the break point is triggered.
600 return result->IsTrue();
604 bool Debug::SetBreakPoint(Handle<JSFunction> function,
605 Handle<Object> break_point_object,
606 int* source_position) {
607 HandleScope scope(isolate_);
609 // Make sure the function is compiled and has set up the debug info.
610 Handle<SharedFunctionInfo> shared(function->shared());
611 if (!EnsureDebugInfo(shared, function)) {
612 // Return if retrieving debug info failed.
616 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
617 // Source positions starts with zero.
618 DCHECK(*source_position >= 0);
620 // Find the break point and change it.
621 BreakLocation location = BreakLocation::FromPosition(
622 debug_info, ALL_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED);
623 *source_position = location.statement_position();
624 location.SetBreakPoint(break_point_object);
626 // At least one active break point now.
627 return debug_info->GetBreakPointCount() > 0;
631 bool Debug::SetBreakPointForScript(Handle<Script> script,
632 Handle<Object> break_point_object,
633 int* source_position,
634 BreakPositionAlignment alignment) {
635 HandleScope scope(isolate_);
637 // Obtain shared function info for the function.
638 Handle<Object> result =
639 FindSharedFunctionInfoInScript(script, *source_position);
640 if (result->IsUndefined()) return false;
642 // Make sure the function has set up the debug info.
643 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
644 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
645 // Return if retrieving debug info failed.
649 // Find position within function. The script position might be before the
650 // source position of the first function.
652 if (shared->start_position() > *source_position) {
655 position = *source_position - shared->start_position();
658 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
659 // Source positions starts with zero.
660 DCHECK(position >= 0);
662 // Find the break point and change it.
663 BreakLocation location = BreakLocation::FromPosition(
664 debug_info, ALL_BREAK_LOCATIONS, position, alignment);
665 location.SetBreakPoint(break_point_object);
667 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position()
668 : location.position();
670 *source_position = position + shared->start_position();
672 // At least one active break point now.
673 DCHECK(debug_info->GetBreakPointCount() > 0);
678 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
679 HandleScope scope(isolate_);
681 DebugInfoListNode* node = debug_info_list_;
682 while (node != NULL) {
683 Handle<Object> result =
684 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
685 if (!result->IsUndefined()) {
686 // Get information in the break point.
687 Handle<BreakPointInfo> break_point_info =
688 Handle<BreakPointInfo>::cast(result);
689 Handle<DebugInfo> debug_info = node->debug_info();
691 // Find the break point and clear it.
692 Address pc = debug_info->code()->entry() +
693 break_point_info->code_position()->value();
695 BreakLocation location =
696 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, pc);
697 location.ClearBreakPoint(break_point_object);
699 // If there are no more break points left remove the debug info for this
701 if (debug_info->GetBreakPointCount() == 0) {
702 RemoveDebugInfoAndClearFromShared(debug_info);
712 // Clear out all the debug break code. This is ONLY supposed to be used when
713 // shutting down the debugger as it will leave the break point information in
714 // DebugInfo even though the code is patched back to the non break point state.
715 void Debug::ClearAllBreakPoints() {
716 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
717 node = node->next()) {
718 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
719 !it.Done(); it.Next()) {
720 it.GetBreakLocation().ClearDebugBreak();
723 // Remove all debug info.
724 while (debug_info_list_ != NULL) {
725 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
730 void Debug::FloodWithOneShot(Handle<JSFunction> function,
731 BreakLocatorType type) {
732 // Make sure the function is compiled and has set up the debug info.
733 Handle<SharedFunctionInfo> shared(function->shared());
734 if (!EnsureDebugInfo(shared, function)) {
735 // Return if we failed to retrieve the debug info.
739 // Flood the function with break points.
740 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
741 for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) {
742 it.GetBreakLocation().SetOneShot();
747 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
748 Handle<FixedArray> new_bindings(function->function_bindings());
749 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
752 if (!bindee.is_null() && bindee->IsJSFunction()) {
753 Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
754 FloodWithOneShotGeneric(bindee_function);
759 void Debug::FloodDefaultConstructorWithOneShot(Handle<JSFunction> function) {
760 DCHECK(function->shared()->is_default_constructor());
761 // Instead of stepping into the function we directly step into the super class
763 Isolate* isolate = function->GetIsolate();
764 PrototypeIterator iter(isolate, function);
765 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
766 if (!proto->IsJSFunction()) return; // Object.prototype
767 Handle<JSFunction> function_proto = Handle<JSFunction>::cast(proto);
768 FloodWithOneShotGeneric(function_proto);
772 void Debug::FloodWithOneShotGeneric(Handle<JSFunction> function,
773 Handle<Object> holder) {
774 if (function->shared()->bound()) {
775 FloodBoundFunctionWithOneShot(function);
776 } else if (function->shared()->is_default_constructor()) {
777 FloodDefaultConstructorWithOneShot(function);
779 Isolate* isolate = function->GetIsolate();
780 // Don't allow step into functions in the native context.
781 if (function->shared()->code() ==
782 isolate->builtins()->builtin(Builtins::kFunctionApply) ||
783 function->shared()->code() ==
784 isolate->builtins()->builtin(Builtins::kFunctionCall)) {
785 // Handle function.apply and function.call separately to flood the
786 // function to be called and not the code for Builtins::FunctionApply or
787 // Builtins::FunctionCall. The receiver of call/apply is the target
789 if (!holder.is_null() && holder->IsJSFunction()) {
790 Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
791 FloodWithOneShotGeneric(js_function);
794 FloodWithOneShot(function);
800 void Debug::FloodHandlerWithOneShot() {
801 // Iterate through the JavaScript stack looking for handlers.
802 StackFrame::Id id = break_frame_id();
803 if (id == StackFrame::NO_ID) {
804 // If there is no JavaScript stack don't do anything.
807 for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
808 JavaScriptFrame* frame = it.frame();
809 int stack_slots = 0; // The computed stack slot count is not used.
810 if (frame->LookupExceptionHandlerInTable(&stack_slots, NULL) > 0) {
811 // Flood the function with the catch/finally block with break points.
812 FloodWithOneShot(Handle<JSFunction>(frame->function()));
819 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
820 if (type == BreakUncaughtException) {
821 break_on_uncaught_exception_ = enable;
823 break_on_exception_ = enable;
828 bool Debug::IsBreakOnException(ExceptionBreakType type) {
829 if (type == BreakUncaughtException) {
830 return break_on_uncaught_exception_;
832 return break_on_exception_;
837 FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) {
838 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
839 frame->Summarize(&frames);
840 return frames.first();
844 void Debug::PrepareStep(StepAction step_action,
846 StackFrame::Id frame_id) {
847 HandleScope scope(isolate_);
849 DCHECK(in_debug_scope());
851 // Remember this step action and count.
852 thread_local_.last_step_action_ = step_action;
853 if (step_action == StepOut) {
854 // For step out target frame will be found on the stack so there is no need
855 // to set step counter for it. It's expected to always be 0 for StepOut.
856 thread_local_.step_count_ = 0;
858 thread_local_.step_count_ = step_count;
861 // Get the frame where the execution has stopped and skip the debug frame if
862 // any. The debug frame will only be present if execution was stopped due to
863 // hitting a break point. In other situations (e.g. unhandled exception) the
864 // debug frame is not present.
865 StackFrame::Id id = break_frame_id();
866 if (id == StackFrame::NO_ID) {
867 // If there is no JavaScript stack don't do anything.
870 if (frame_id != StackFrame::NO_ID) {
873 JavaScriptFrameIterator frames_it(isolate_, id);
874 JavaScriptFrame* frame = frames_it.frame();
876 // First of all ensure there is one-shot break points in the top handler
878 FloodHandlerWithOneShot();
880 // If the function on the top frame is unresolved perform step out. This will
881 // be the case when calling unknown function and having the debugger stopped
882 // in an unhandled exception.
883 if (!frame->function()->IsJSFunction()) {
884 // Step out: Find the calling JavaScript frame and flood it with
887 // Fill the function to return to with one-shot break points.
888 JSFunction* function = frames_it.frame()->function();
889 FloodWithOneShot(Handle<JSFunction>(function));
893 // Get the debug info (create it if it does not exist).
894 FrameSummary summary = GetFirstFrameSummary(frame);
895 Handle<JSFunction> function(summary.function());
896 Handle<SharedFunctionInfo> shared(function->shared());
897 if (!EnsureDebugInfo(shared, function)) {
898 // Return if ensuring debug info failed.
902 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
903 // Refresh frame summary if the code has been recompiled for debugging.
904 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame);
906 // PC points to the instruction after the current one, possibly a break
907 // location as well. So the "- 1" to exclude it from the search.
908 Address call_pc = summary.pc() - 1;
909 BreakLocation location =
910 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
912 // If this is the last break code target step out is the only possibility.
913 if (location.IsReturn() || step_action == StepOut) {
914 if (step_action == StepOut) {
915 // Skip step_count frames starting with the current one.
916 while (step_count-- > 0 && !frames_it.done()) {
920 DCHECK(location.IsReturn());
923 // Skip native and extension functions on the stack.
924 while (!frames_it.done() &&
925 !frames_it.frame()->function()->IsSubjectToDebugging()) {
928 // Step out: If there is a JavaScript caller frame, we need to
929 // flood it with breakpoints.
930 if (!frames_it.done()) {
931 // Fill the function to return to with one-shot break points.
932 JSFunction* function = frames_it.frame()->function();
933 FloodWithOneShot(Handle<JSFunction>(function));
934 // Set target frame pointer.
935 ActivateStepOut(frames_it.frame());
940 if (step_action != StepNext && step_action != StepMin) {
941 // If there's restarter frame on top of the stack, just get the pointer
942 // to function which is going to be restarted.
943 if (thread_local_.restarter_frame_function_pointer_ != NULL) {
944 Handle<JSFunction> restarted_function(
945 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
946 FloodWithOneShot(restarted_function);
947 } else if (location.IsCall()) {
948 // Find target function on the expression stack.
949 // Expression stack looks like this (top to bottom):
955 int num_expressions_without_args =
956 frame->ComputeExpressionsCount() - location.CallArgumentsCount();
957 DCHECK(num_expressions_without_args >= 2);
958 Object* fun = frame->GetExpression(num_expressions_without_args - 2);
960 // Flood the actual target of call/apply.
961 if (fun->IsJSFunction()) {
962 Isolate* isolate = JSFunction::cast(fun)->GetIsolate();
963 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply);
964 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall);
965 // Find target function on the expression stack for expression like
966 // Function.call.call...apply(...)
968 while (fun->IsJSFunction()) {
969 Code* code = JSFunction::cast(fun)->shared()->code();
970 if (code != apply && code != call) break;
971 DCHECK(num_expressions_without_args >= i);
972 fun = frame->GetExpression(num_expressions_without_args - i);
977 if (fun->IsJSFunction()) {
978 Handle<JSFunction> js_function(JSFunction::cast(fun));
979 FloodWithOneShotGeneric(js_function);
983 ActivateStepIn(frame);
986 // Fill the current function with one-shot break points even for step in on
987 // a call target as the function called might be a native function for
988 // which step in will not stop. It also prepares for stepping in
990 // If we are stepping into another frame, only fill calls and returns.
991 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
992 : ALL_BREAK_LOCATIONS);
994 // Remember source position and frame to handle step next.
995 thread_local_.last_statement_position_ =
996 debug_info->code()->SourceStatementPosition(summary.pc());
997 thread_local_.last_fp_ = frame->UnpaddedFP();
1001 // Check whether the current debug break should be reported to the debugger. It
1002 // is used to have step next and step in only report break back to the debugger
1003 // if on a different frame or in a different statement. In some situations
1004 // there will be several break points in the same statement when the code is
1005 // flooded with one-shot break points. This function helps to perform several
1006 // steps before reporting break back to the debugger.
1007 bool Debug::StepNextContinue(BreakLocation* break_location,
1008 JavaScriptFrame* frame) {
1009 // StepNext and StepOut shouldn't bring us deeper in code, so last frame
1010 // shouldn't be a parent of current frame.
1011 StepAction step_action = thread_local_.last_step_action_;
1013 if (step_action == StepNext || step_action == StepOut) {
1014 if (frame->fp() < thread_local_.last_fp_) return true;
1017 // We stepped into a new frame if the frame pointer changed.
1018 if (step_action == StepFrame) {
1019 return frame->UnpaddedFP() == thread_local_.last_fp_;
1022 // If the step last action was step next or step in make sure that a new
1023 // statement is hit.
1024 if (step_action == StepNext || step_action == StepIn) {
1025 // Never continue if returning from function.
1026 if (break_location->IsReturn()) return false;
1028 // Continue if we are still on the same frame and in the same statement.
1029 int current_statement_position =
1030 break_location->code()->SourceStatementPosition(frame->pc());
1031 return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1032 thread_local_.last_statement_position_ == current_statement_position;
1035 // No step next action - don't continue.
1040 // Check whether the code object at the specified address is a debug break code
1042 bool Debug::IsDebugBreak(Address addr) {
1043 Code* code = Code::GetCodeFromTargetAddress(addr);
1044 return code->is_debug_stub();
1048 // Simple function for returning the source positions for active break points.
1049 Handle<Object> Debug::GetSourceBreakLocations(
1050 Handle<SharedFunctionInfo> shared,
1051 BreakPositionAlignment position_alignment) {
1052 Isolate* isolate = shared->GetIsolate();
1053 Heap* heap = isolate->heap();
1054 if (!shared->HasDebugInfo()) {
1055 return Handle<Object>(heap->undefined_value(), isolate);
1057 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1058 if (debug_info->GetBreakPointCount() == 0) {
1059 return Handle<Object>(heap->undefined_value(), isolate);
1061 Handle<FixedArray> locations =
1062 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1064 for (int i = 0; i < debug_info->break_points()->length(); ++i) {
1065 if (!debug_info->break_points()->get(i)->IsUndefined()) {
1066 BreakPointInfo* break_point_info =
1067 BreakPointInfo::cast(debug_info->break_points()->get(i));
1068 int break_points = break_point_info->GetBreakPointCount();
1069 if (break_points == 0) continue;
1070 Smi* position = NULL;
1071 switch (position_alignment) {
1072 case STATEMENT_ALIGNED:
1073 position = break_point_info->statement_position();
1075 case BREAK_POSITION_ALIGNED:
1076 position = break_point_info->source_position();
1079 for (int j = 0; j < break_points; ++j) locations->set(count++, position);
1086 // Handle stepping into a function.
1087 void Debug::HandleStepIn(Handle<Object> function_obj, bool is_constructor) {
1088 // Flood getter/setter if we either step in or step to another frame.
1089 bool step_frame = thread_local_.last_step_action_ == StepFrame;
1090 if (!StepInActive() && !step_frame) return;
1091 if (!function_obj->IsJSFunction()) return;
1092 Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj);
1093 Isolate* isolate = function->GetIsolate();
1095 StackFrameIterator it(isolate);
1097 // For constructor functions skip another frame.
1098 if (is_constructor) {
1099 DCHECK(it.frame()->is_construct());
1102 Address fp = it.frame()->fp();
1104 // Flood the function with one-shot break points if it is called from where
1105 // step into was requested, or when stepping into a new frame.
1106 if (fp == thread_local_.step_into_fp_ || step_frame) {
1107 FloodWithOneShotGeneric(function, Handle<Object>());
1112 void Debug::ClearStepping() {
1113 // Clear the various stepping setup.
1119 // Clear multiple step counter.
1120 thread_local_.step_count_ = 0;
1124 // Clears all the one-shot break points that are currently set. Normally this
1125 // function is called each time a break point is hit as one shot break points
1126 // are used to support stepping.
1127 void Debug::ClearOneShot() {
1128 // The current implementation just runs through all the breakpoints. When the
1129 // last break point for a function is removed that function is automatically
1130 // removed from the list.
1131 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
1132 node = node->next()) {
1133 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1134 !it.Done(); it.Next()) {
1135 it.GetBreakLocation().ClearOneShot();
1141 void Debug::ActivateStepIn(StackFrame* frame) {
1142 DCHECK(!StepOutActive());
1143 thread_local_.step_into_fp_ = frame->UnpaddedFP();
1147 void Debug::ClearStepIn() {
1148 thread_local_.step_into_fp_ = 0;
1152 void Debug::ActivateStepOut(StackFrame* frame) {
1153 DCHECK(!StepInActive());
1154 thread_local_.step_out_fp_ = frame->UnpaddedFP();
1158 void Debug::ClearStepOut() {
1159 thread_local_.step_out_fp_ = 0;
1163 void Debug::ClearStepNext() {
1164 thread_local_.last_step_action_ = StepNone;
1165 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1166 thread_local_.last_fp_ = 0;
1170 bool MatchingCodeTargets(Code* target1, Code* target2) {
1171 if (target1 == target2) return true;
1172 if (target1->kind() != target2->kind()) return false;
1173 return target1->is_handler() || target1->is_inline_cache_stub();
1177 // Count the number of calls before the current frame PC to find the
1178 // corresponding PC in the newly recompiled code.
1179 static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code,
1181 DCHECK_EQ(old_code->kind(), Code::FUNCTION);
1182 DCHECK_EQ(new_code->kind(), Code::FUNCTION);
1183 DCHECK(new_code->has_debug_break_slots());
1184 static const int mask = RelocInfo::kCodeTargetMask;
1186 // Find the target of the current call.
1187 Code* target = NULL;
1189 for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
1190 RelocInfo* rinfo = it.rinfo();
1191 Address current_pc = rinfo->pc();
1192 // The frame PC is behind the call instruction by the call instruction size.
1193 if (current_pc > old_pc) break;
1194 delta = old_pc - current_pc;
1195 target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1198 // Count the number of calls to the same target before the current call.
1200 for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
1201 RelocInfo* rinfo = it.rinfo();
1202 Address current_pc = rinfo->pc();
1203 if (current_pc > old_pc) break;
1204 Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
1205 if (MatchingCodeTargets(target, current)) index++;
1210 // Repeat the count on the new code to find corresponding call.
1211 for (RelocIterator it(new_code, mask); !it.done(); it.next()) {
1212 RelocInfo* rinfo = it.rinfo();
1213 Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
1214 if (MatchingCodeTargets(target, current)) index--;
1215 if (index == 0) return rinfo->pc() + delta;
1223 // Count the number of continuations at which the current pc offset is at.
1224 static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) {
1225 DCHECK_EQ(code->kind(), Code::FUNCTION);
1226 Address pc = code->instruction_start() + pc_offset;
1227 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
1229 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1231 RelocInfo* rinfo = it.rinfo();
1232 Address current_pc = rinfo->pc();
1233 if (current_pc == pc) break;
1234 DCHECK(current_pc < pc);
1240 // Find the pc offset for the given continuation index.
1241 static int ComputePcOffsetFromContinuationIndex(Code* code, int index) {
1242 DCHECK_EQ(code->kind(), Code::FUNCTION);
1243 DCHECK(code->has_debug_break_slots());
1244 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
1245 RelocIterator it(code, mask);
1246 for (int i = 1; i < index; i++) it.next();
1247 return static_cast<int>(it.rinfo()->pc() - code->instruction_start());
1251 class RedirectActiveFunctions : public ThreadVisitor {
1253 explicit RedirectActiveFunctions(SharedFunctionInfo* shared)
1255 DCHECK(shared->HasDebugCode());
1258 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1259 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1260 JavaScriptFrame* frame = it.frame();
1261 JSFunction* function = frame->function();
1262 if (frame->is_optimized()) continue;
1263 if (!function->Inlines(shared_)) continue;
1265 Code* frame_code = frame->LookupCode();
1266 DCHECK(frame_code->kind() == Code::FUNCTION);
1267 if (frame_code->has_debug_break_slots()) continue;
1269 Code* new_code = function->shared()->code();
1270 Address old_pc = frame->pc();
1271 Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc);
1273 if (FLAG_trace_deopt) {
1274 PrintF("Replacing pc for debugging: %08" V8PRIxPTR " => %08" V8PRIxPTR
1276 reinterpret_cast<intptr_t>(old_pc),
1277 reinterpret_cast<intptr_t>(new_pc));
1280 if (FLAG_enable_embedded_constant_pool) {
1281 // Update constant pool pointer for new code.
1282 frame->set_constant_pool(new_code->constant_pool());
1285 // Patch the return address to return into the code with
1286 // debug break slots.
1287 frame->set_pc(new_pc);
1292 SharedFunctionInfo* shared_;
1293 DisallowHeapAllocation no_gc_;
1297 bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
1298 DCHECK(shared->is_compiled());
1300 if (isolate_->concurrent_recompilation_enabled()) {
1301 isolate_->optimizing_compile_dispatcher()->Flush();
1304 List<Handle<JSFunction> > functions;
1305 List<Handle<JSGeneratorObject> > suspended_generators;
1307 if (!shared->optimized_code_map()->IsSmi()) {
1308 shared->ClearOptimizedCodeMap();
1311 // Make sure we abort incremental marking.
1312 isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1313 "prepare for break points");
1316 HeapIterator iterator(isolate_->heap());
1318 bool include_generators = shared->is_generator();
1320 while ((obj = iterator.next())) {
1321 if (obj->IsJSFunction()) {
1322 JSFunction* function = JSFunction::cast(obj);
1323 if (!function->Inlines(*shared)) continue;
1324 if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) {
1325 Deoptimizer::DeoptimizeFunction(function);
1327 if (function->shared() == *shared) functions.Add(handle(function));
1328 } else if (include_generators && obj->IsJSGeneratorObject()) {
1329 JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj);
1330 if (!generator_obj->is_suspended()) continue;
1331 JSFunction* function = generator_obj->function();
1332 if (!function->Inlines(*shared)) continue;
1333 int pc_offset = generator_obj->continuation();
1335 ComputeContinuationIndexFromPcOffset(function->code(), pc_offset);
1336 generator_obj->set_continuation(index);
1337 suspended_generators.Add(handle(generator_obj));
1342 if (!shared->HasDebugCode()) {
1343 DCHECK(functions.length() > 0);
1344 if (!Compiler::CompileDebugCode(functions.first())) return false;
1347 for (Handle<JSFunction> const function : functions) {
1348 function->ReplaceCode(shared->code());
1351 for (Handle<JSGeneratorObject> const generator_obj : suspended_generators) {
1352 int index = generator_obj->continuation();
1353 int pc_offset = ComputePcOffsetFromContinuationIndex(shared->code(), index);
1354 generator_obj->set_continuation(pc_offset);
1357 // Update PCs on the stack to point to recompiled code.
1358 RedirectActiveFunctions redirect_visitor(*shared);
1359 redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top());
1360 isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor);
1366 class SharedFunctionInfoFinder {
1368 explicit SharedFunctionInfoFinder(int target_position)
1369 : current_candidate_(NULL),
1370 current_candidate_closure_(NULL),
1371 current_start_position_(RelocInfo::kNoPosition),
1372 target_position_(target_position) {}
1374 void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) {
1375 int start_position = shared->function_token_position();
1376 if (start_position == RelocInfo::kNoPosition) {
1377 start_position = shared->start_position();
1380 if (start_position > target_position_) return;
1381 if (target_position_ > shared->end_position()) return;
1383 if (current_candidate_ != NULL) {
1384 if (current_start_position_ == start_position &&
1385 shared->end_position() == current_candidate_->end_position()) {
1386 // If we already have a matching closure, do not throw it away.
1387 if (current_candidate_closure_ != NULL && closure == NULL) return;
1388 // If a top-level function contains only one function
1389 // declaration the source for the top-level and the function
1390 // is the same. In that case prefer the non top-level function.
1391 if (!current_candidate_->is_toplevel() && shared->is_toplevel()) return;
1392 } else if (start_position < current_start_position_ ||
1393 current_candidate_->end_position() < shared->end_position()) {
1398 current_start_position_ = start_position;
1399 current_candidate_ = shared;
1400 current_candidate_closure_ = closure;
1403 SharedFunctionInfo* Result() { return current_candidate_; }
1405 JSFunction* ResultClosure() { return current_candidate_closure_; }
1408 SharedFunctionInfo* current_candidate_;
1409 JSFunction* current_candidate_closure_;
1410 int current_start_position_;
1411 int target_position_;
1412 DisallowHeapAllocation no_gc_;
1416 // We need to find a SFI for a literal that may not yet have been compiled yet,
1417 // and there may not be a JSFunction referencing it. Find the SFI closest to
1418 // the given position, compile it to reveal possible inner SFIs and repeat.
1419 // While we are at this, also ensure code with debug break slots so that we do
1420 // not have to compile a SFI without JSFunction, which is paifu for those that
1421 // cannot be compiled without context (need to find outer compilable SFI etc.)
1422 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
1425 // Go through all shared function infos associated with this script to
1426 // find the inner most function containing this position.
1427 // If there is no shared function info for this script at all, there is
1428 // no point in looking for it by walking the heap.
1429 if (!script->shared_function_infos()->IsWeakFixedArray()) break;
1431 SharedFunctionInfo* shared;
1433 SharedFunctionInfoFinder finder(position);
1434 WeakFixedArray::Iterator iterator(script->shared_function_infos());
1435 SharedFunctionInfo* candidate;
1436 while ((candidate = iterator.Next<SharedFunctionInfo>())) {
1437 finder.NewCandidate(candidate);
1439 shared = finder.Result();
1440 if (shared == NULL) break;
1441 // We found it if it's already compiled and has debug code.
1442 if (shared->HasDebugCode()) return handle(shared);
1444 // If not, compile to reveal inner functions, if possible.
1445 if (shared->allows_lazy_compilation_without_context()) {
1446 HandleScope scope(isolate_);
1447 if (!Compiler::CompileDebugCode(handle(shared))) break;
1451 // If not possible, comb the heap for the best suitable compile target.
1452 JSFunction* closure;
1454 HeapIterator it(isolate_->heap());
1455 SharedFunctionInfoFinder finder(position);
1456 while (HeapObject* object = it.next()) {
1457 JSFunction* candidate_closure = NULL;
1458 SharedFunctionInfo* candidate = NULL;
1459 if (object->IsJSFunction()) {
1460 candidate_closure = JSFunction::cast(object);
1461 candidate = candidate_closure->shared();
1462 } else if (object->IsSharedFunctionInfo()) {
1463 candidate = SharedFunctionInfo::cast(object);
1464 if (!candidate->allows_lazy_compilation_without_context()) continue;
1468 if (candidate->script() == *script) {
1469 finder.NewCandidate(candidate, candidate_closure);
1472 closure = finder.ResultClosure();
1473 shared = finder.Result();
1475 HandleScope scope(isolate_);
1476 if (closure == NULL) {
1477 if (!Compiler::CompileDebugCode(handle(shared))) break;
1479 if (!Compiler::CompileDebugCode(handle(closure))) break;
1482 return isolate_->factory()->undefined_value();
1486 // Ensures the debug information is present for shared.
1487 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
1488 Handle<JSFunction> function) {
1489 if (!shared->IsSubjectToDebugging()) return false;
1491 // Return if we already have the debug info for shared.
1492 if (shared->HasDebugInfo()) return true;
1494 if (function.is_null()) {
1495 DCHECK(shared->HasDebugCode());
1496 } else if (!Compiler::Compile(function, CLEAR_EXCEPTION)) {
1500 if (!PrepareFunctionForBreakPoints(shared)) return false;
1502 // Make sure IC state is clean. This is so that we correctly flood
1503 // accessor pairs when stepping in.
1504 shared->code()->ClearInlineCaches();
1505 shared->feedback_vector()->ClearICSlots(*shared);
1507 // Create the debug info object.
1508 DCHECK(shared->HasDebugCode());
1509 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared);
1511 // Add debug info to the list.
1512 DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
1513 node->set_next(debug_info_list_);
1514 debug_info_list_ = node;
1520 void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) {
1521 HandleScope scope(isolate_);
1522 Handle<SharedFunctionInfo> shared(debug_info->shared());
1524 DCHECK_NOT_NULL(debug_info_list_);
1525 // Run through the debug info objects to find this one and remove it.
1526 DebugInfoListNode* prev = NULL;
1527 DebugInfoListNode* current = debug_info_list_;
1528 while (current != NULL) {
1529 if (current->debug_info().is_identical_to(debug_info)) {
1530 // Unlink from list. If prev is NULL we are looking at the first element.
1532 debug_info_list_ = current->next();
1534 prev->set_next(current->next());
1537 shared->set_debug_info(isolate_->heap()->undefined_value());
1540 // Move to next in list.
1542 current = current->next();
1549 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
1550 after_break_target_ = NULL;
1552 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job.
1554 // Continue just after the slot.
1555 after_break_target_ = frame->pc();
1559 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
1560 HandleScope scope(isolate_);
1562 // Get the executing function in which the debug break occurred.
1563 Handle<JSFunction> function(JSFunction::cast(frame->function()));
1564 Handle<SharedFunctionInfo> shared(function->shared());
1566 // With no debug info there are no break points, so we can't be at a return.
1567 if (!shared->HasDebugInfo()) return false;
1568 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1569 Handle<Code> code(debug_info->code());
1571 // Get the code which is actually executing.
1572 Handle<Code> frame_code(frame->LookupCode());
1573 DCHECK(frame_code.is_identical_to(code));
1576 // Find the reloc info matching the start of the debug break slot.
1577 Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength;
1578 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
1579 for (RelocIterator it(*code, mask); !it.done(); it.next()) {
1580 if (it.rinfo()->pc() == slot_pc) return true;
1586 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
1587 LiveEdit::FrameDropMode mode,
1588 Object** restarter_frame_function_pointer) {
1589 if (mode != LiveEdit::CURRENTLY_SET_MODE) {
1590 thread_local_.frame_drop_mode_ = mode;
1592 thread_local_.break_frame_id_ = new_break_frame_id;
1593 thread_local_.restarter_frame_function_pointer_ =
1594 restarter_frame_function_pointer;
1598 bool Debug::IsDebugGlobal(GlobalObject* global) {
1599 return is_loaded() && global == debug_context()->global_object();
1603 void Debug::ClearMirrorCache() {
1604 PostponeInterruptsScope postpone(isolate_);
1605 HandleScope scope(isolate_);
1606 CallFunction("ClearMirrorCache", 0, NULL);
1610 Handle<FixedArray> Debug::GetLoadedScripts() {
1611 isolate_->heap()->CollectAllGarbage();
1612 Factory* factory = isolate_->factory();
1613 if (!factory->script_list()->IsWeakFixedArray()) {
1614 return factory->empty_fixed_array();
1616 Handle<WeakFixedArray> array =
1617 Handle<WeakFixedArray>::cast(factory->script_list());
1618 Handle<FixedArray> results = factory->NewFixedArray(array->Length());
1621 Script::Iterator iterator(isolate_);
1623 while ((script = iterator.Next())) {
1624 if (script->HasValidSource()) results->set(length++, script);
1627 results->Shrink(length);
1632 void Debug::GetStepinPositions(JavaScriptFrame* frame, StackFrame::Id frame_id,
1633 List<int>* results_out) {
1634 FrameSummary summary = GetFirstFrameSummary(frame);
1636 Handle<JSFunction> fun = Handle<JSFunction>(summary.function());
1637 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared());
1639 if (!EnsureDebugInfo(shared, fun)) return;
1641 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1642 // Refresh frame summary if the code has been recompiled for debugging.
1643 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame);
1645 // Find range of break points starting from the break point where execution
1647 Address call_pc = summary.pc() - 1;
1648 List<BreakLocation> locations;
1649 BreakLocation::FromAddressSameStatement(debug_info, ALL_BREAK_LOCATIONS,
1650 call_pc, &locations);
1652 for (BreakLocation location : locations) {
1653 if (location.pc() <= summary.pc()) {
1654 // The break point is near our pc. Could be a step-in possibility,
1655 // that is currently taken by active debugger call.
1656 if (break_frame_id() == StackFrame::NO_ID) {
1657 continue; // We are not stepping.
1659 JavaScriptFrameIterator frame_it(isolate_, break_frame_id());
1660 // If our frame is a top frame and we are stepping, we can do step-in
1662 if (frame_it.frame()->id() != frame_id) continue;
1665 if (location.IsStepInLocation()) results_out->Add(location.position());
1670 void Debug::RecordEvalCaller(Handle<Script> script) {
1671 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1672 // For eval scripts add information on the function from which eval was
1674 StackTraceFrameIterator it(script->GetIsolate());
1676 script->set_eval_from_shared(it.frame()->function()->shared());
1677 Code* code = it.frame()->LookupCode();
1678 int offset = static_cast<int>(
1679 it.frame()->pc() - code->instruction_start());
1680 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
1685 MaybeHandle<Object> Debug::MakeExecutionState() {
1686 // Create the execution state object.
1687 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
1688 return CallFunction("MakeExecutionState", arraysize(argv), argv);
1692 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
1693 // Create the new break event object.
1694 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
1696 return CallFunction("MakeBreakEvent", arraysize(argv), argv);
1700 MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
1702 Handle<Object> promise) {
1703 // Create the new exception event object.
1704 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
1706 isolate_->factory()->ToBoolean(uncaught),
1708 return CallFunction("MakeExceptionEvent", arraysize(argv), argv);
1712 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
1713 v8::DebugEvent type) {
1714 // Create the compile event object.
1715 Handle<Object> script_wrapper = Script::GetWrapper(script);
1716 Handle<Object> argv[] = { script_wrapper,
1717 isolate_->factory()->NewNumberFromInt(type) };
1718 return CallFunction("MakeCompileEvent", arraysize(argv), argv);
1722 MaybeHandle<Object> Debug::MakePromiseEvent(Handle<JSObject> event_data) {
1723 // Create the promise event object.
1724 Handle<Object> argv[] = { event_data };
1725 return CallFunction("MakePromiseEvent", arraysize(argv), argv);
1729 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
1730 // Create the async task event object.
1731 Handle<Object> argv[] = { task_event };
1732 return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv);
1736 void Debug::OnThrow(Handle<Object> exception) {
1737 if (in_debug_scope() || ignore_events()) return;
1738 // Temporarily clear any scheduled_exception to allow evaluating
1739 // JavaScript from the debug event handler.
1740 HandleScope scope(isolate_);
1741 Handle<Object> scheduled_exception;
1742 if (isolate_->has_scheduled_exception()) {
1743 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
1744 isolate_->clear_scheduled_exception();
1746 OnException(exception, isolate_->GetPromiseOnStackOnThrow());
1747 if (!scheduled_exception.is_null()) {
1748 isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
1753 void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
1754 if (in_debug_scope() || ignore_events()) return;
1755 HandleScope scope(isolate_);
1756 // Check whether the promise has been marked as having triggered a message.
1757 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1758 if (JSReceiver::GetDataProperty(promise, key)->IsUndefined()) {
1759 OnException(value, promise);
1764 MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler(
1765 Handle<JSObject> promise) {
1766 Handle<JSFunction> fun = isolate_->promise_has_user_defined_reject_handler();
1767 return Execution::Call(isolate_, fun, promise, 0, NULL);
1771 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
1772 // In our prediction, try-finally is not considered to catch.
1773 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
1774 bool uncaught = (catch_type == Isolate::NOT_CAUGHT);
1775 if (promise->IsJSObject()) {
1776 Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
1777 // Mark the promise as already having triggered a message.
1778 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1779 JSObject::SetProperty(jspromise, key, key, STRICT).Assert();
1780 // Check whether the promise reject is considered an uncaught exception.
1781 Handle<Object> has_reject_handler;
1782 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1783 isolate_, has_reject_handler,
1784 PromiseHasUserDefinedRejectHandler(jspromise), /* void */);
1785 uncaught = has_reject_handler->IsFalse();
1787 // Bail out if exception breaks are not active
1789 // Uncaught exceptions are reported by either flags.
1790 if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
1792 // Caught exceptions are reported is activated.
1793 if (!break_on_exception_) return;
1796 DebugScope debug_scope(this);
1797 if (debug_scope.failed()) return;
1799 // Clear all current stepping setup.
1802 // Create the event data object.
1803 Handle<Object> event_data;
1804 // Bail out and don't call debugger if exception.
1805 if (!MakeExceptionEvent(
1806 exception, uncaught, promise).ToHandle(&event_data)) {
1810 // Process debug event.
1811 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
1812 // Return to continue execution from where the exception was thrown.
1816 void Debug::OnCompileError(Handle<Script> script) {
1817 if (ignore_events()) return;
1819 if (in_debug_scope()) {
1820 ProcessCompileEventInDebugScope(v8::CompileError, script);
1824 HandleScope scope(isolate_);
1825 DebugScope debug_scope(this);
1826 if (debug_scope.failed()) return;
1828 // Create the compile state object.
1829 Handle<Object> event_data;
1830 // Bail out and don't call debugger if exception.
1831 if (!MakeCompileEvent(script, v8::CompileError).ToHandle(&event_data)) return;
1833 // Process debug event.
1834 ProcessDebugEvent(v8::CompileError, Handle<JSObject>::cast(event_data), true);
1838 void Debug::OnDebugBreak(Handle<Object> break_points_hit,
1839 bool auto_continue) {
1840 // The caller provided for DebugScope.
1841 AssertDebugContext();
1842 // Bail out if there is no listener for this event
1843 if (ignore_events()) return;
1845 HandleScope scope(isolate_);
1846 // Create the event data object.
1847 Handle<Object> event_data;
1848 // Bail out and don't call debugger if exception.
1849 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
1851 // Process debug event.
1852 ProcessDebugEvent(v8::Break,
1853 Handle<JSObject>::cast(event_data),
1858 void Debug::OnBeforeCompile(Handle<Script> script) {
1859 if (in_debug_scope() || ignore_events()) return;
1861 HandleScope scope(isolate_);
1862 DebugScope debug_scope(this);
1863 if (debug_scope.failed()) return;
1865 // Create the event data object.
1866 Handle<Object> event_data;
1867 // Bail out and don't call debugger if exception.
1868 if (!MakeCompileEvent(script, v8::BeforeCompile).ToHandle(&event_data))
1871 // Process debug event.
1872 ProcessDebugEvent(v8::BeforeCompile,
1873 Handle<JSObject>::cast(event_data),
1878 // Handle debugger actions when a new script is compiled.
1879 void Debug::OnAfterCompile(Handle<Script> script) {
1880 if (ignore_events()) return;
1882 if (in_debug_scope()) {
1883 ProcessCompileEventInDebugScope(v8::AfterCompile, script);
1887 HandleScope scope(isolate_);
1888 DebugScope debug_scope(this);
1889 if (debug_scope.failed()) return;
1891 // If debugging there might be script break points registered for this
1892 // script. Make sure that these break points are set.
1893 Handle<Object> argv[] = {Script::GetWrapper(script)};
1894 if (CallFunction("UpdateScriptBreakPoints", arraysize(argv), argv)
1899 // Create the compile state object.
1900 Handle<Object> event_data;
1901 // Bail out and don't call debugger if exception.
1902 if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return;
1904 // Process debug event.
1905 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
1909 void Debug::OnPromiseEvent(Handle<JSObject> data) {
1910 if (in_debug_scope() || ignore_events()) return;
1912 HandleScope scope(isolate_);
1913 DebugScope debug_scope(this);
1914 if (debug_scope.failed()) return;
1916 // Create the script collected state object.
1917 Handle<Object> event_data;
1918 // Bail out and don't call debugger if exception.
1919 if (!MakePromiseEvent(data).ToHandle(&event_data)) return;
1921 // Process debug event.
1922 ProcessDebugEvent(v8::PromiseEvent,
1923 Handle<JSObject>::cast(event_data),
1928 void Debug::OnAsyncTaskEvent(Handle<JSObject> data) {
1929 if (in_debug_scope() || ignore_events()) return;
1931 HandleScope scope(isolate_);
1932 DebugScope debug_scope(this);
1933 if (debug_scope.failed()) return;
1935 // Create the script collected state object.
1936 Handle<Object> event_data;
1937 // Bail out and don't call debugger if exception.
1938 if (!MakeAsyncTaskEvent(data).ToHandle(&event_data)) return;
1940 // Process debug event.
1941 ProcessDebugEvent(v8::AsyncTaskEvent,
1942 Handle<JSObject>::cast(event_data),
1947 void Debug::ProcessDebugEvent(v8::DebugEvent event,
1948 Handle<JSObject> event_data,
1949 bool auto_continue) {
1950 HandleScope scope(isolate_);
1952 // Create the execution state.
1953 Handle<Object> exec_state;
1954 // Bail out and don't call debugger if exception.
1955 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1957 // First notify the message handler if any.
1958 if (message_handler_ != NULL) {
1959 NotifyMessageHandler(event,
1960 Handle<JSObject>::cast(exec_state),
1964 // Notify registered debug event listener. This can be either a C or
1965 // a JavaScript function. Don't call event listener for v8::Break
1966 // here, if it's only a debug command -- they will be processed later.
1967 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
1968 CallEventCallback(event, exec_state, event_data, NULL);
1973 void Debug::CallEventCallback(v8::DebugEvent event,
1974 Handle<Object> exec_state,
1975 Handle<Object> event_data,
1976 v8::Debug::ClientData* client_data) {
1977 bool previous = in_debug_event_listener_;
1978 in_debug_event_listener_ = true;
1979 if (event_listener_->IsForeign()) {
1980 // Invoke the C debug event listener.
1981 v8::Debug::EventCallback callback =
1982 FUNCTION_CAST<v8::Debug::EventCallback>(
1983 Handle<Foreign>::cast(event_listener_)->foreign_address());
1984 EventDetailsImpl event_details(event,
1985 Handle<JSObject>::cast(exec_state),
1986 Handle<JSObject>::cast(event_data),
1987 event_listener_data_,
1989 callback(event_details);
1990 DCHECK(!isolate_->has_scheduled_exception());
1992 // Invoke the JavaScript debug event listener.
1993 DCHECK(event_listener_->IsJSFunction());
1994 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
1997 event_listener_data_ };
1998 Handle<JSReceiver> global(isolate_->global_proxy());
1999 Execution::TryCall(Handle<JSFunction>::cast(event_listener_),
2000 global, arraysize(argv), argv);
2002 in_debug_event_listener_ = previous;
2006 void Debug::ProcessCompileEventInDebugScope(v8::DebugEvent event,
2007 Handle<Script> script) {
2008 if (event_listener_.is_null()) return;
2010 SuppressDebug while_processing(this);
2011 DebugScope debug_scope(this);
2012 if (debug_scope.failed()) return;
2014 Handle<Object> event_data;
2015 // Bail out and don't call debugger if exception.
2016 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;
2018 // Create the execution state.
2019 Handle<Object> exec_state;
2020 // Bail out and don't call debugger if exception.
2021 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2023 CallEventCallback(event, exec_state, event_data, NULL);
2027 Handle<Context> Debug::GetDebugContext() {
2028 if (!is_loaded()) return Handle<Context>();
2029 DebugScope debug_scope(this);
2030 if (debug_scope.failed()) return Handle<Context>();
2031 // The global handle may be destroyed soon after. Return it reboxed.
2032 return handle(*debug_context(), isolate_);
2036 void Debug::NotifyMessageHandler(v8::DebugEvent event,
2037 Handle<JSObject> exec_state,
2038 Handle<JSObject> event_data,
2039 bool auto_continue) {
2040 // Prevent other interrupts from triggering, for example API callbacks,
2041 // while dispatching message handler callbacks.
2042 PostponeInterruptsScope no_interrupts(isolate_);
2044 HandleScope scope(isolate_);
2045 // Process the individual events.
2046 bool sendEventMessage = false;
2049 sendEventMessage = !auto_continue;
2051 case v8::NewFunction:
2052 case v8::BeforeCompile:
2053 case v8::CompileError:
2054 case v8::PromiseEvent:
2055 case v8::AsyncTaskEvent:
2058 case v8::AfterCompile:
2059 sendEventMessage = true;
2063 // The debug command interrupt flag might have been set when the command was
2064 // added. It should be enough to clear the flag only once while we are in the
2066 DCHECK(in_debug_scope());
2067 isolate_->stack_guard()->ClearDebugCommand();
2069 // Notify the debugger that a debug event has occurred unless auto continue is
2070 // active in which case no event is send.
2071 if (sendEventMessage) {
2072 MessageImpl message = MessageImpl::NewEvent(
2075 Handle<JSObject>::cast(exec_state),
2076 Handle<JSObject>::cast(event_data));
2077 InvokeMessageHandler(message);
2080 // If auto continue don't make the event cause a break, but process messages
2081 // in the queue if any. For script collected events don't even process
2082 // messages in the queue as the execution state might not be what is expected
2084 if (auto_continue && !has_commands()) return;
2086 // DebugCommandProcessor goes here.
2087 bool running = auto_continue;
2089 Handle<Object> cmd_processor_ctor = Object::GetProperty(
2090 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked();
2091 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
2092 Handle<Object> cmd_processor = Execution::Call(
2093 isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked();
2094 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
2095 Object::GetProperty(
2096 isolate_, cmd_processor, "processDebugRequest").ToHandleChecked());
2097 Handle<Object> is_running = Object::GetProperty(
2098 isolate_, cmd_processor, "isRunning").ToHandleChecked();
2100 // Process requests from the debugger.
2102 // Wait for new command in the queue.
2103 command_received_.Wait();
2105 // Get the command from the queue.
2106 CommandMessage command = command_queue_.Get();
2107 isolate_->logger()->DebugTag(
2108 "Got request from command queue, in interactive loop.");
2110 // Delete command text and user data.
2115 Vector<const uc16> command_text(
2116 const_cast<const uc16*>(command.text().start()),
2117 command.text().length());
2118 Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
2119 command_text).ToHandleChecked();
2120 Handle<Object> request_args[] = { request_text };
2121 Handle<Object> answer_value;
2122 Handle<String> answer;
2123 MaybeHandle<Object> maybe_exception;
2124 MaybeHandle<Object> maybe_result =
2125 Execution::TryCall(process_debug_request, cmd_processor, 1,
2126 request_args, &maybe_exception);
2128 if (maybe_result.ToHandle(&answer_value)) {
2129 if (answer_value->IsUndefined()) {
2130 answer = isolate_->factory()->empty_string();
2132 answer = Handle<String>::cast(answer_value);
2135 // Log the JSON request/response.
2136 if (FLAG_trace_debug_json) {
2137 PrintF("%s\n", request_text->ToCString().get());
2138 PrintF("%s\n", answer->ToCString().get());
2141 Handle<Object> is_running_args[] = { answer };
2142 maybe_result = Execution::Call(
2143 isolate_, is_running, cmd_processor, 1, is_running_args);
2144 Handle<Object> result;
2145 if (!maybe_result.ToHandle(&result)) break;
2146 running = result->IsTrue();
2148 Handle<Object> exception;
2149 if (!maybe_exception.ToHandle(&exception)) break;
2150 Handle<Object> result;
2151 if (!Object::ToString(isolate_, exception).ToHandle(&result)) break;
2152 answer = Handle<String>::cast(result);
2155 // Return the result.
2156 MessageImpl message = MessageImpl::NewResponse(
2157 event, running, exec_state, event_data, answer, command.client_data());
2158 InvokeMessageHandler(message);
2161 // Return from debug event processing if either the VM is put into the
2162 // running state (through a continue command) or auto continue is active
2163 // and there are no more commands queued.
2164 } while (!running || has_commands());
2165 command_queue_.Clear();
2169 void Debug::SetEventListener(Handle<Object> callback,
2170 Handle<Object> data) {
2171 GlobalHandles* global_handles = isolate_->global_handles();
2173 // Remove existing entry.
2174 GlobalHandles::Destroy(event_listener_.location());
2175 event_listener_ = Handle<Object>();
2176 GlobalHandles::Destroy(event_listener_data_.location());
2177 event_listener_data_ = Handle<Object>();
2180 if (!callback->IsUndefined() && !callback->IsNull()) {
2181 event_listener_ = global_handles->Create(*callback);
2182 if (data.is_null()) data = isolate_->factory()->undefined_value();
2183 event_listener_data_ = global_handles->Create(*data);
2190 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
2191 message_handler_ = handler;
2193 if (handler == NULL && in_debug_scope()) {
2194 // Send an empty command to the debugger if in a break to make JavaScript
2195 // run again if the debugger is closed.
2196 EnqueueCommandMessage(Vector<const uint16_t>::empty());
2202 void Debug::UpdateState() {
2203 bool is_active = message_handler_ != NULL || !event_listener_.is_null();
2204 if (is_active || in_debug_scope()) {
2205 // Note that the debug context could have already been loaded to
2206 // bootstrap test cases.
2207 isolate_->compilation_cache()->Disable();
2209 } else if (is_loaded()) {
2210 isolate_->compilation_cache()->Enable();
2213 is_active_ = is_active;
2217 // Calls the registered debug message handler. This callback is part of the
2219 void Debug::InvokeMessageHandler(MessageImpl message) {
2220 if (message_handler_ != NULL) message_handler_(message);
2224 // Puts a command coming from the public API on the queue. Creates
2225 // a copy of the command string managed by the debugger. Up to this
2226 // point, the command data was managed by the API client. Called
2227 // by the API client thread.
2228 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
2229 v8::Debug::ClientData* client_data) {
2230 // Need to cast away const.
2231 CommandMessage message = CommandMessage::New(
2232 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
2235 isolate_->logger()->DebugTag("Put command on command_queue.");
2236 command_queue_.Put(message);
2237 command_received_.Signal();
2239 // Set the debug command break flag to have the command processed.
2240 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
2244 MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) {
2245 DebugScope debug_scope(this);
2246 if (debug_scope.failed()) return isolate_->factory()->undefined_value();
2248 // Create the execution state.
2249 Handle<Object> exec_state;
2250 if (!MakeExecutionState().ToHandle(&exec_state)) {
2251 return isolate_->factory()->undefined_value();
2254 Handle<Object> argv[] = { exec_state, data };
2255 return Execution::Call(
2258 Handle<Object>(debug_context()->global_proxy(), isolate_),
2264 void Debug::HandleDebugBreak() {
2265 // Ignore debug break during bootstrapping.
2266 if (isolate_->bootstrapper()->IsActive()) return;
2267 // Just continue if breaks are disabled.
2268 if (break_disabled()) return;
2269 // Ignore debug break if debugger is not active.
2270 if (!is_active()) return;
2272 StackLimitCheck check(isolate_);
2273 if (check.HasOverflowed()) return;
2275 { JavaScriptFrameIterator it(isolate_);
2277 Object* fun = it.frame()->function();
2278 if (fun && fun->IsJSFunction()) {
2279 // Don't stop in builtin functions.
2280 if (!JSFunction::cast(fun)->IsSubjectToDebugging()) return;
2281 GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
2282 // Don't stop in debugger functions.
2283 if (IsDebugGlobal(global)) return;
2287 // Collect the break state before clearing the flags.
2288 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
2289 !isolate_->stack_guard()->CheckDebugBreak();
2291 isolate_->stack_guard()->ClearDebugBreak();
2293 ProcessDebugMessages(debug_command_only);
2297 void Debug::ProcessDebugMessages(bool debug_command_only) {
2298 isolate_->stack_guard()->ClearDebugCommand();
2300 StackLimitCheck check(isolate_);
2301 if (check.HasOverflowed()) return;
2303 HandleScope scope(isolate_);
2304 DebugScope debug_scope(this);
2305 if (debug_scope.failed()) return;
2307 // Notify the debug event listeners. Indicate auto continue if the break was
2308 // a debug command break.
2309 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
2313 DebugScope::DebugScope(Debug* debug)
2315 prev_(debug->debugger_entry()),
2316 save_(debug_->isolate_),
2317 no_termination_exceptons_(debug_->isolate_,
2318 StackGuard::TERMINATE_EXECUTION) {
2319 // Link recursive debugger entry.
2320 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2321 reinterpret_cast<base::AtomicWord>(this));
2323 // Store the previous break id and frame id.
2324 break_id_ = debug_->break_id();
2325 break_frame_id_ = debug_->break_frame_id();
2327 // Create the new break info. If there is no JavaScript frames there is no
2329 JavaScriptFrameIterator it(isolate());
2330 bool has_js_frames = !it.done();
2331 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
2332 : StackFrame::NO_ID;
2333 debug_->SetNextBreakId();
2335 debug_->UpdateState();
2336 // Make sure that debugger is loaded and enter the debugger context.
2337 // The previous context is kept in save_.
2338 failed_ = !debug_->is_loaded();
2339 if (!failed_) isolate()->set_context(*debug->debug_context());
2344 DebugScope::~DebugScope() {
2345 if (!failed_ && prev_ == NULL) {
2346 // Clear mirror cache when leaving the debugger. Skip this if there is a
2347 // pending exception as clearing the mirror cache calls back into
2348 // JavaScript. This can happen if the v8::Debug::Call is used in which
2349 // case the exception should end up in the calling code.
2350 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
2352 // If there are commands in the queue when leaving the debugger request
2353 // that these commands are processed.
2354 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
2357 // Leaving this debugger entry.
2358 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2359 reinterpret_cast<base::AtomicWord>(prev_));
2361 // Restore to the previous break state.
2362 debug_->thread_local_.break_frame_id_ = break_frame_id_;
2363 debug_->thread_local_.break_id_ = break_id_;
2365 debug_->UpdateState();
2369 MessageImpl MessageImpl::NewEvent(DebugEvent event,
2371 Handle<JSObject> exec_state,
2372 Handle<JSObject> event_data) {
2373 MessageImpl message(true, event, running,
2374 exec_state, event_data, Handle<String>(), NULL);
2379 MessageImpl MessageImpl::NewResponse(DebugEvent event,
2381 Handle<JSObject> exec_state,
2382 Handle<JSObject> event_data,
2383 Handle<String> response_json,
2384 v8::Debug::ClientData* client_data) {
2385 MessageImpl message(false, event, running,
2386 exec_state, event_data, response_json, client_data);
2391 MessageImpl::MessageImpl(bool is_event,
2394 Handle<JSObject> exec_state,
2395 Handle<JSObject> event_data,
2396 Handle<String> response_json,
2397 v8::Debug::ClientData* client_data)
2398 : is_event_(is_event),
2401 exec_state_(exec_state),
2402 event_data_(event_data),
2403 response_json_(response_json),
2404 client_data_(client_data) {}
2407 bool MessageImpl::IsEvent() const {
2412 bool MessageImpl::IsResponse() const {
2417 DebugEvent MessageImpl::GetEvent() const {
2422 bool MessageImpl::WillStartRunning() const {
2427 v8::Local<v8::Object> MessageImpl::GetExecutionState() const {
2428 return v8::Utils::ToLocal(exec_state_);
2432 v8::Isolate* MessageImpl::GetIsolate() const {
2433 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2437 v8::Local<v8::Object> MessageImpl::GetEventData() const {
2438 return v8::Utils::ToLocal(event_data_);
2442 v8::Local<v8::String> MessageImpl::GetJSON() const {
2443 Isolate* isolate = event_data_->GetIsolate();
2444 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
2447 // Call toJSONProtocol on the debug event object.
2448 Handle<Object> fun = Object::GetProperty(
2449 isolate, event_data_, "toJSONProtocol").ToHandleChecked();
2450 if (!fun->IsJSFunction()) {
2451 return v8::Local<v8::String>();
2454 MaybeHandle<Object> maybe_json =
2455 Execution::TryCall(Handle<JSFunction>::cast(fun), event_data_, 0, NULL);
2456 Handle<Object> json;
2457 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
2458 return v8::Local<v8::String>();
2460 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
2462 return v8::Utils::ToLocal(response_json_);
2467 v8::Local<v8::Context> MessageImpl::GetEventContext() const {
2468 Isolate* isolate = event_data_->GetIsolate();
2469 v8::Local<v8::Context> context = GetDebugEventContext(isolate);
2470 // Isolate::context() may be NULL when "script collected" event occurs.
2471 DCHECK(!context.IsEmpty());
2476 v8::Debug::ClientData* MessageImpl::GetClientData() const {
2477 return client_data_;
2481 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
2482 Handle<JSObject> exec_state,
2483 Handle<JSObject> event_data,
2484 Handle<Object> callback_data,
2485 v8::Debug::ClientData* client_data)
2487 exec_state_(exec_state),
2488 event_data_(event_data),
2489 callback_data_(callback_data),
2490 client_data_(client_data) {}
2493 DebugEvent EventDetailsImpl::GetEvent() const {
2498 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const {
2499 return v8::Utils::ToLocal(exec_state_);
2503 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const {
2504 return v8::Utils::ToLocal(event_data_);
2508 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const {
2509 return GetDebugEventContext(exec_state_->GetIsolate());
2513 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const {
2514 return v8::Utils::ToLocal(callback_data_);
2518 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
2519 return client_data_;
2523 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
2524 client_data_(NULL) {
2528 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
2529 v8::Debug::ClientData* data)
2531 client_data_(data) {
2535 void CommandMessage::Dispose() {
2537 delete client_data_;
2538 client_data_ = NULL;
2542 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
2543 v8::Debug::ClientData* data) {
2544 return CommandMessage(command.Clone(), data);
2548 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
2550 messages_ = NewArray<CommandMessage>(size);
2554 CommandMessageQueue::~CommandMessageQueue() {
2555 while (!IsEmpty()) Get().Dispose();
2556 DeleteArray(messages_);
2560 CommandMessage CommandMessageQueue::Get() {
2562 int result = start_;
2563 start_ = (start_ + 1) % size_;
2564 return messages_[result];
2568 void CommandMessageQueue::Put(const CommandMessage& message) {
2569 if ((end_ + 1) % size_ == start_) {
2572 messages_[end_] = message;
2573 end_ = (end_ + 1) % size_;
2577 void CommandMessageQueue::Expand() {
2578 CommandMessageQueue new_queue(size_ * 2);
2579 while (!IsEmpty()) {
2580 new_queue.Put(Get());
2582 CommandMessage* array_to_free = messages_;
2584 new_queue.messages_ = array_to_free;
2585 // Make the new_queue empty so that it doesn't call Dispose on any messages.
2586 new_queue.start_ = new_queue.end_;
2587 // Automatic destructor called on new_queue, freeing array_to_free.
2591 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
2592 : logger_(logger), queue_(size) {}
2595 bool LockingCommandMessageQueue::IsEmpty() const {
2596 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2597 return queue_.IsEmpty();
2601 CommandMessage LockingCommandMessageQueue::Get() {
2602 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2603 CommandMessage result = queue_.Get();
2604 logger_->DebugEvent("Get", result.text());
2609 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
2610 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2611 queue_.Put(message);
2612 logger_->DebugEvent("Put", message.text());
2616 void LockingCommandMessageQueue::Clear() {
2617 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2621 } // namespace internal