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.
8 #include "src/arguments.h"
9 #include "src/bootstrapper.h"
10 #include "src/code-stubs.h"
11 #include "src/codegen.h"
12 #include "src/compilation-cache.h"
13 #include "src/compiler.h"
14 #include "src/debug.h"
15 #include "src/deoptimizer.h"
16 #include "src/execution.h"
17 #include "src/full-codegen.h"
18 #include "src/global-handles.h"
19 #include "src/isolate-inl.h"
22 #include "src/messages.h"
23 #include "src/snapshot/natives.h"
25 #include "include/v8-debug.h"
30 Debug::Debug(Isolate* isolate)
31 : debug_context_(Handle<Context>()),
32 event_listener_(Handle<Object>()),
33 event_listener_data_(Handle<Object>()),
34 message_handler_(NULL),
36 command_queue_(isolate->logger(), kQueueInitialSize),
37 event_command_queue_(isolate->logger(), kQueueInitialSize),
39 is_suppressed_(false),
40 live_edit_enabled_(true), // TODO(yangguo): set to false by default.
41 has_break_points_(false),
42 break_disabled_(false),
43 in_debug_event_listener_(false),
44 break_on_exception_(false),
45 break_on_uncaught_exception_(false),
47 debug_info_list_(NULL),
53 static v8::Handle<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
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);
63 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
64 BreakLocatorType type)
65 : debug_info_(debug_info),
67 reloc_iterator_(debug_info->code(),
68 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)),
69 reloc_iterator_original_(
70 debug_info->original_code(),
71 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)),
74 statement_position_(1) {
79 void BreakLocation::Iterator::Next() {
80 DisallowHeapAllocation no_gc;
83 // Iterate through reloc info for code and original code stopping at each
84 // breakable code target.
85 bool first = break_index_ == -1;
86 while (!RinfoDone()) {
87 if (!first) RinfoNext();
89 if (RinfoDone()) return;
91 // Whenever a statement position or (plain) position is passed update the
92 // current value of these.
93 if (RelocInfo::IsPosition(rmode())) {
94 if (RelocInfo::IsStatementPosition(rmode())) {
95 statement_position_ = static_cast<int>(
96 rinfo()->data() - debug_info_->shared()->start_position());
98 // Always update the position as we don't want that to be before the
99 // statement position.
100 position_ = static_cast<int>(rinfo()->data() -
101 debug_info_->shared()->start_position());
102 DCHECK(position_ >= 0);
103 DCHECK(statement_position_ >= 0);
106 // Check for break at return.
107 if (RelocInfo::IsJSReturn(rmode())) {
108 // Set the positions to the end of the function.
109 if (debug_info_->shared()->HasSourceCode()) {
110 position_ = debug_info_->shared()->end_position() -
111 debug_info_->shared()->start_position() - 1;
115 statement_position_ = position_;
120 if (RelocInfo::IsCodeTarget(rmode())) {
121 // Check for breakable code target. Look in the original code as setting
122 // break points can cause the code targets in the running (debugged) code
123 // to be of a different kind than in the original code.
124 Address target = original_rinfo()->target_address();
125 Code* code = Code::GetCodeFromTargetAddress(target);
127 if (RelocInfo::IsConstructCall(rmode()) || code->is_call_stub()) {
132 // Skip below if we only want locations for calls and returns.
133 if (type_ == CALLS_AND_RETURNS) continue;
135 if ((code->is_inline_cache_stub() && !code->is_binary_op_stub() &&
136 !code->is_compare_ic_stub() && !code->is_to_boolean_ic_stub())) {
140 if (code->kind() == Code::STUB) {
141 if (RelocInfo::IsDebuggerStatement(rmode())) {
144 } else if (CodeStub::GetMajorKey(code) == CodeStub::CallFunction) {
151 if (RelocInfo::IsDebugBreakSlot(rmode()) && type_ != CALLS_AND_RETURNS) {
152 // There is always a possible break point at a debug break slot.
160 // Find the break point at the supplied address, or the closest one before
162 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info,
163 BreakLocatorType type, Address pc) {
164 Iterator it(debug_info, type);
165 it.SkipTo(BreakIndexFromAddress(debug_info, type, pc));
166 return it.GetBreakLocation();
170 // Find the break point at the supplied address, or the closest one before
172 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info,
173 BreakLocatorType type, Address pc,
174 List<BreakLocation>* result_out) {
175 int break_index = BreakIndexFromAddress(debug_info, type, pc);
176 Iterator it(debug_info, type);
177 it.SkipTo(break_index);
178 int statement_position = it.statement_position();
179 while (!it.Done() && it.statement_position() == statement_position) {
180 result_out->Add(it.GetBreakLocation());
186 int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info,
187 BreakLocatorType type, Address pc) {
188 // Run through all break points to locate the one closest to the address.
189 int closest_break = 0;
190 int distance = kMaxInt;
191 for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
192 // Check if this break point is closer that what was previously found.
193 if (it.pc() <= pc && pc - it.pc() < distance) {
194 closest_break = it.break_index();
195 distance = static_cast<int>(pc - it.pc());
196 // Check whether we can't get any closer.
197 if (distance == 0) break;
200 return closest_break;
204 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
205 BreakLocatorType type, int position,
206 BreakPositionAlignment alignment) {
207 // Run through all break points to locate the one closest to the source
209 int closest_break = 0;
210 int distance = kMaxInt;
212 for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
214 if (alignment == STATEMENT_ALIGNED) {
215 next_position = it.statement_position();
217 DCHECK(alignment == BREAK_POSITION_ALIGNED);
218 next_position = it.position();
220 if (position <= next_position && next_position - position < distance) {
221 closest_break = it.break_index();
222 distance = next_position - position;
223 // Check whether we can't get any closer.
224 if (distance == 0) break;
228 Iterator it(debug_info, type);
229 it.SkipTo(closest_break);
230 return it.GetBreakLocation();
234 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) {
235 // If there is not already a real break point here patch code with debug
237 if (!HasBreakPoint()) SetDebugBreak();
238 DCHECK(IsDebugBreak() || IsDebuggerStatement());
239 // Set the break point information.
240 DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_,
241 statement_position_, break_point_object);
245 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
246 // Clear the break point information.
247 DebugInfo::ClearBreakPoint(debug_info_, pc_offset_, break_point_object);
248 // If there are no more break points here remove the debug break.
249 if (!HasBreakPoint()) {
251 DCHECK(!IsDebugBreak());
256 void BreakLocation::SetOneShot() {
257 // Debugger statement always calls debugger. No need to modify it.
258 if (IsDebuggerStatement()) return;
260 // If there is a real break point here no more to do.
261 if (HasBreakPoint()) {
262 DCHECK(IsDebugBreak());
266 // Patch code with debug break.
271 void BreakLocation::ClearOneShot() {
272 // Debugger statement always calls debugger. No need to modify it.
273 if (IsDebuggerStatement()) return;
275 // If there is a real break point here no more to do.
276 if (HasBreakPoint()) {
277 DCHECK(IsDebugBreak());
281 // Patch code removing debug break.
283 DCHECK(!IsDebugBreak());
287 void BreakLocation::SetDebugBreak() {
288 // Debugger statement always calls debugger. No need to modify it.
289 if (IsDebuggerStatement()) return;
291 // If there is already a break point here just return. This might happen if
292 // the same code is flooded with break points twice. Flooding the same
293 // function twice might happen when stepping in a function with an exception
294 // handler as the handler and the function is the same.
295 if (IsDebugBreak()) return;
298 // Patch the frame exit code with a break point.
299 SetDebugBreakAtReturn();
300 } else if (IsDebugBreakSlot()) {
301 // Patch the code in the break slot.
302 SetDebugBreakAtSlot();
304 // Patch the IC call.
307 DCHECK(IsDebugBreak());
311 void BreakLocation::ClearDebugBreak() {
312 // Debugger statement always calls debugger. No need to modify it.
313 if (IsDebuggerStatement()) return;
316 // Restore the frame exit code with a break point.
317 RestoreFromOriginal(Assembler::kJSReturnSequenceLength);
318 } else if (IsDebugBreakSlot()) {
319 // Restore the code in the break slot.
320 RestoreFromOriginal(Assembler::kDebugBreakSlotLength);
322 // Restore the IC call.
323 rinfo().set_target_address(original_rinfo().target_address());
324 // Some ICs store data in the feedback vector. Clear this to ensure we
325 // won't miss future stepping requirements.
326 SharedFunctionInfo* shared = debug_info_->shared();
327 shared->feedback_vector()->ClearICSlots(shared);
329 DCHECK(!IsDebugBreak());
333 void BreakLocation::RestoreFromOriginal(int length_in_bytes) {
334 memcpy(pc(), original_pc(), length_in_bytes);
335 CpuFeatures::FlushICache(pc(), length_in_bytes);
339 bool BreakLocation::IsStepInLocation() const {
340 if (IsConstructCall()) return true;
341 if (RelocInfo::IsCodeTarget(rmode())) {
342 HandleScope scope(debug_info_->GetIsolate());
343 Handle<Code> target_code = CodeTarget();
344 return target_code->is_call_stub();
350 bool BreakLocation::IsDebugBreak() const {
352 return rinfo().IsPatchedReturnSequence();
353 } else if (IsDebugBreakSlot()) {
354 return rinfo().IsPatchedDebugBreakSlotSequence();
356 return Debug::IsDebugBreak(rinfo().target_address());
361 // Find the builtin to use for invoking the debug break
362 static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
363 Isolate* isolate = code->GetIsolate();
365 // Find the builtin debug break function matching the calling convention
366 // used by the call site.
367 if (code->is_inline_cache_stub()) {
368 switch (code->kind()) {
370 return isolate->builtins()->CallICStub_DebugBreak();
373 return isolate->builtins()->LoadIC_DebugBreak();
376 return isolate->builtins()->StoreIC_DebugBreak();
378 case Code::KEYED_LOAD_IC:
379 return isolate->builtins()->KeyedLoadIC_DebugBreak();
381 case Code::KEYED_STORE_IC:
382 return isolate->builtins()->KeyedStoreIC_DebugBreak();
384 case Code::COMPARE_NIL_IC:
385 return isolate->builtins()->CompareNilIC_DebugBreak();
391 if (RelocInfo::IsConstructCall(mode)) {
392 if (code->has_function_cache()) {
393 return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
395 return isolate->builtins()->CallConstructStub_DebugBreak();
398 if (code->kind() == Code::STUB) {
399 DCHECK(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction);
400 return isolate->builtins()->CallFunctionStub_DebugBreak();
404 return Handle<Code>::null();
408 void BreakLocation::SetDebugBreakAtIC() {
409 // Patch the original code with the current address as the current address
410 // might have changed by the inline caching since the code was copied.
411 original_rinfo().set_target_address(rinfo().target_address());
413 if (RelocInfo::IsCodeTarget(rmode_)) {
414 Handle<Code> target_code = CodeTarget();
416 // Patch the code to invoke the builtin debug break function matching the
417 // calling convention used by the call site.
418 Handle<Code> debug_break_code = DebugBreakForIC(target_code, rmode_);
419 rinfo().set_target_address(debug_break_code->entry());
424 Handle<Object> BreakLocation::BreakPointObjects() const {
425 return debug_info_->GetBreakPointObjects(pc_offset_);
429 Handle<Code> BreakLocation::CodeTarget() const {
430 DCHECK(IsCodeTarget());
431 Address target = rinfo().target_address();
432 return Handle<Code>(Code::GetCodeFromTargetAddress(target));
436 Handle<Code> BreakLocation::OriginalCodeTarget() const {
437 DCHECK(IsCodeTarget());
438 Address target = original_rinfo().target_address();
439 return Handle<Code>(Code::GetCodeFromTargetAddress(target));
443 bool BreakLocation::Iterator::RinfoDone() const {
444 DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
445 return reloc_iterator_.done();
449 void BreakLocation::Iterator::RinfoNext() {
450 reloc_iterator_.next();
451 reloc_iterator_original_.next();
453 DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
454 DCHECK(reloc_iterator_.done() || rmode() == original_rmode());
459 // Threading support.
460 void Debug::ThreadInit() {
461 thread_local_.break_count_ = 0;
462 thread_local_.break_id_ = 0;
463 thread_local_.break_frame_id_ = StackFrame::NO_ID;
464 thread_local_.last_step_action_ = StepNone;
465 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
466 thread_local_.step_count_ = 0;
467 thread_local_.last_fp_ = 0;
468 thread_local_.queued_step_count_ = 0;
469 thread_local_.step_into_fp_ = 0;
470 thread_local_.step_out_fp_ = 0;
471 // TODO(isolates): frames_are_dropped_?
472 base::NoBarrier_Store(&thread_local_.current_debug_scope_,
473 static_cast<base::AtomicWord>(0));
474 thread_local_.restarter_frame_function_pointer_ = NULL;
478 char* Debug::ArchiveDebug(char* storage) {
480 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
482 return storage + ArchiveSpacePerThread();
486 char* Debug::RestoreDebug(char* storage) {
487 char* from = storage;
488 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
489 return storage + ArchiveSpacePerThread();
493 int Debug::ArchiveSpacePerThread() {
494 return sizeof(ThreadLocal);
498 ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch),
500 Heap* heap = isolate_->heap();
501 HandleScope scope(isolate_);
503 // Perform a GC to get rid of all unreferenced scripts.
504 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache");
506 // Scan heap for Script objects.
507 HeapIterator iterator(heap);
508 DisallowHeapAllocation no_allocation;
510 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
511 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
512 Add(Handle<Script>(Script::cast(obj)));
518 void ScriptCache::Add(Handle<Script> script) {
519 GlobalHandles* global_handles = isolate_->global_handles();
520 // Create an entry in the hash map for the script.
521 int id = script->id()->value();
522 HashMap::Entry* entry =
523 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
524 if (entry->value != NULL) {
526 // The code deserializer may introduce duplicate Script objects.
527 // Assert that the Script objects with the same id have the same name.
528 Handle<Script> found(reinterpret_cast<Script**>(entry->value));
529 DCHECK(script->id() == found->id());
530 DCHECK(!script->name()->IsString() ||
531 String::cast(script->name())->Equals(String::cast(found->name())));
535 // Globalize the script object, make it weak and use the location of the
536 // global handle as the value in the hash map.
537 Handle<Script> script_ =
538 Handle<Script>::cast(global_handles->Create(*script));
539 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
541 ScriptCache::HandleWeakScript);
542 entry->value = script_.location();
546 Handle<FixedArray> ScriptCache::GetScripts() {
547 Factory* factory = isolate_->factory();
548 Handle<FixedArray> instances = factory->NewFixedArray(occupancy());
550 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
551 DCHECK(entry->value != NULL);
552 if (entry->value != NULL) {
553 instances->set(count, *reinterpret_cast<Script**>(entry->value));
561 void ScriptCache::Clear() {
562 // Iterate the script cache to get rid of all the weak handles.
563 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
564 DCHECK(entry != NULL);
565 Object** location = reinterpret_cast<Object**>(entry->value);
566 DCHECK((*location)->IsScript());
567 GlobalHandles::ClearWeakness(location);
568 GlobalHandles::Destroy(location);
570 // Clear the content of the hash map.
575 void ScriptCache::HandleWeakScript(
576 const v8::WeakCallbackData<v8::Value, void>& data) {
577 // Retrieve the script identifier.
578 Handle<Object> object = Utils::OpenHandle(*data.GetValue());
579 int id = Handle<Script>::cast(object)->id()->value();
580 void* key = reinterpret_cast<void*>(id);
581 uint32_t hash = Hash(id);
583 // Remove the corresponding entry from the cache.
584 ScriptCache* script_cache =
585 reinterpret_cast<ScriptCache*>(data.GetParameter());
586 HashMap::Entry* entry = script_cache->Lookup(key, hash, false);
587 Object** location = reinterpret_cast<Object**>(entry->value);
588 script_cache->Remove(key, hash);
590 // Clear the weak handle.
591 GlobalHandles::Destroy(location);
595 void Debug::HandlePhantomDebugInfo(
596 const v8::WeakCallbackInfo<DebugInfoListNode>& data) {
597 DebugInfoListNode* node = data.GetParameter();
599 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug();
600 debug->RemoveDebugInfo(node);
602 for (DebugInfoListNode* n = debug->debug_info_list_;
611 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
612 // Globalize the request debug info object and make it weak.
613 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
615 Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location();
616 typedef WeakCallbackInfo<void>::Callback Callback;
617 GlobalHandles::MakeWeak(
618 reinterpret_cast<Object**>(debug_info_), this,
619 reinterpret_cast<Callback>(Debug::HandlePhantomDebugInfo),
620 v8::WeakCallbackType::kParameter);
624 void DebugInfoListNode::ClearInfo() {
625 if (debug_info_ == nullptr) return;
626 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_));
627 debug_info_ = nullptr;
631 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
632 Factory* factory = isolate->factory();
633 HandleScope scope(isolate);
635 // Bail out if the index is invalid.
636 if (index == -1) return false;
638 // Find source and name for the requested script.
639 Handle<String> source_code =
640 isolate->bootstrapper()->NativesSourceLookup(index);
641 Vector<const char> name = Natives::GetScriptName(index);
642 Handle<String> script_name =
643 factory->NewStringFromAscii(name).ToHandleChecked();
644 Handle<Context> context = isolate->native_context();
646 // Compile the script.
647 Handle<SharedFunctionInfo> function_info;
648 function_info = Compiler::CompileScript(
649 source_code, script_name, 0, 0, false, false, Handle<Object>(), context,
650 NULL, NULL, ScriptCompiler::kNoCompileOptions, NATIVES_CODE, false);
652 // Silently ignore stack overflows during compilation.
653 if (function_info.is_null()) {
654 DCHECK(isolate->has_pending_exception());
655 isolate->clear_pending_exception();
659 // Execute the shared function in the debugger context.
660 Handle<JSFunction> function =
661 factory->NewFunctionFromSharedFunctionInfo(function_info, context);
663 MaybeHandle<Object> maybe_exception;
664 MaybeHandle<Object> result = Execution::TryCall(
665 function, handle(context->global_proxy()), 0, NULL, &maybe_exception);
667 // Check for caught exceptions.
668 if (result.is_null()) {
669 DCHECK(!isolate->has_pending_exception());
670 MessageLocation computed_location;
671 isolate->ComputeLocation(&computed_location);
672 Handle<Object> message = MessageHandler::MakeMessageObject(
673 isolate, "error_loading_debugger", &computed_location,
674 Vector<Handle<Object> >::empty(), Handle<JSArray>());
675 DCHECK(!isolate->has_pending_exception());
676 Handle<Object> exception;
677 if (maybe_exception.ToHandle(&exception)) {
678 isolate->set_pending_exception(*exception);
679 MessageHandler::ReportMessage(isolate, NULL, message);
680 isolate->clear_pending_exception();
685 // Mark this script as native and return successfully.
686 Handle<Script> script(Script::cast(function->shared()->script()));
687 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
693 // Return if debugger is already loaded.
694 if (is_loaded()) return true;
696 // Bail out if we're already in the process of compiling the native
697 // JavaScript source code for the debugger.
698 if (is_suppressed_) return false;
699 SuppressDebug while_loading(this);
701 // Disable breakpoints and interrupts while compiling and running the
702 // debugger scripts including the context creation code.
703 DisableBreak disable(this, true);
704 PostponeInterruptsScope postpone(isolate_);
706 // Create the debugger context.
707 HandleScope scope(isolate_);
708 ExtensionConfiguration no_extensions;
709 Handle<Context> context =
710 isolate_->bootstrapper()->CreateEnvironment(
711 MaybeHandle<JSGlobalProxy>(),
712 v8::Handle<ObjectTemplate>(),
715 // Fail if no context could be created.
716 if (context.is_null()) return false;
718 // Use the debugger context.
719 SaveContext save(isolate_);
720 isolate_->set_context(*context);
722 // Expose the builtins object in the debugger context.
723 Handle<String> key = isolate_->factory()->InternalizeOneByteString(
724 STATIC_CHAR_VECTOR("builtins"));
725 Handle<GlobalObject> global =
726 Handle<GlobalObject>(context->global_object(), isolate_);
727 Handle<JSBuiltinsObject> builtin =
728 Handle<JSBuiltinsObject>(global->builtins(), isolate_);
729 RETURN_ON_EXCEPTION_VALUE(
730 isolate_, Object::SetProperty(global, key, builtin, SLOPPY), false);
732 // Compile the JavaScript for the debugger in the debugger context.
733 bool caught_exception =
734 !CompileDebuggerScript(isolate_, Natives::GetIndex("mirror")) ||
735 !CompileDebuggerScript(isolate_, Natives::GetIndex("debug"));
737 if (FLAG_enable_liveedit) {
738 caught_exception = caught_exception ||
739 !CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit"));
741 // Check for caught exceptions.
742 if (caught_exception) return false;
744 debug_context_ = Handle<Context>::cast(
745 isolate_->global_handles()->Create(*context));
750 void Debug::Unload() {
751 ClearAllBreakPoints();
754 // Return debugger is not loaded.
755 if (!is_loaded()) return;
757 // Clear the script cache.
758 if (script_cache_ != NULL) {
759 delete script_cache_;
760 script_cache_ = NULL;
763 // Clear debugger context global handle.
764 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
765 debug_context_ = Handle<Context>();
769 void Debug::Break(Arguments args, JavaScriptFrame* frame) {
770 Heap* heap = isolate_->heap();
771 HandleScope scope(isolate_);
772 DCHECK(args.length() == 0);
774 // Initialize LiveEdit.
775 LiveEdit::InitializeThreadLocal(this);
777 // Just continue if breaks are disabled or debugger cannot be loaded.
778 if (break_disabled()) return;
780 // Enter the debugger.
781 DebugScope debug_scope(this);
782 if (debug_scope.failed()) return;
784 // Postpone interrupt during breakpoint processing.
785 PostponeInterruptsScope postpone(isolate_);
787 // Get the debug info (create it if it does not exist).
788 Handle<SharedFunctionInfo> shared =
789 Handle<SharedFunctionInfo>(frame->function()->shared());
790 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
792 // Find the break point where execution has stopped.
793 // PC points to the instruction after the current one, possibly a break
794 // location as well. So the "- 1" to exclude it from the search.
795 Address call_pc = frame->pc() - 1;
796 BreakLocation break_location =
797 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
799 // Check whether step next reached a new statement.
800 if (!StepNextContinue(&break_location, frame)) {
801 // Decrease steps left if performing multiple steps.
802 if (thread_local_.step_count_ > 0) {
803 thread_local_.step_count_--;
807 // If there is one or more real break points check whether any of these are
809 Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
810 if (break_location.HasBreakPoint()) {
811 Handle<Object> break_point_objects = break_location.BreakPointObjects();
812 break_points_hit = CheckBreakPoints(break_point_objects);
815 // If step out is active skip everything until the frame where we need to step
816 // out to is reached, unless real breakpoint is hit.
817 if (StepOutActive() &&
818 frame->fp() != thread_local_.step_out_fp_ &&
819 break_points_hit->IsUndefined() ) {
820 // Step count should always be 0 for StepOut.
821 DCHECK(thread_local_.step_count_ == 0);
822 } else if (!break_points_hit->IsUndefined() ||
823 (thread_local_.last_step_action_ != StepNone &&
824 thread_local_.step_count_ == 0)) {
825 // Notify debugger if a real break point is triggered or if performing
826 // single stepping with no more steps to perform. Otherwise do another step.
828 // Clear all current stepping setup.
831 if (thread_local_.queued_step_count_ > 0) {
832 // Perform queued steps
833 int step_count = thread_local_.queued_step_count_;
836 thread_local_.queued_step_count_ = 0;
838 PrepareStep(StepNext, step_count, StackFrame::NO_ID);
840 // Notify the debug event listeners.
841 OnDebugBreak(break_points_hit, false);
843 } else if (thread_local_.last_step_action_ != StepNone) {
844 // Hold on to last step action as it is cleared by the call to
846 StepAction step_action = thread_local_.last_step_action_;
847 int step_count = thread_local_.step_count_;
849 // If StepNext goes deeper in code, StepOut until original frame
850 // and keep step count queued up in the meantime.
851 if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
852 // Count frames until target frame
854 JavaScriptFrameIterator it(isolate_);
855 while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
860 // Check that we indeed found the frame we are looking for.
861 CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
862 if (step_count > 1) {
863 // Save old count and action to continue stepping after StepOut.
864 thread_local_.queued_step_count_ = step_count - 1;
867 // Set up for StepOut to reach target frame.
868 step_action = StepOut;
872 // Clear all current stepping setup.
875 // Set up for the remaining steps.
876 PrepareStep(step_action, step_count, StackFrame::NO_ID);
881 RUNTIME_FUNCTION(Debug_Break) {
882 // Get the top-most JavaScript frame.
883 JavaScriptFrameIterator it(isolate);
884 isolate->debug()->Break(args, it.frame());
885 isolate->debug()->SetAfterBreakTarget(it.frame());
886 return isolate->heap()->undefined_value();
890 // Check the break point objects for whether one or more are actually
891 // triggered. This function returns a JSArray with the break point objects
892 // which is triggered.
893 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
894 Factory* factory = isolate_->factory();
896 // Count the number of break points hit. If there are multiple break points
897 // they are in a FixedArray.
898 Handle<FixedArray> break_points_hit;
899 int break_points_hit_count = 0;
900 DCHECK(!break_point_objects->IsUndefined());
901 if (break_point_objects->IsFixedArray()) {
902 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
903 break_points_hit = factory->NewFixedArray(array->length());
904 for (int i = 0; i < array->length(); i++) {
905 Handle<Object> o(array->get(i), isolate_);
906 if (CheckBreakPoint(o)) {
907 break_points_hit->set(break_points_hit_count++, *o);
911 break_points_hit = factory->NewFixedArray(1);
912 if (CheckBreakPoint(break_point_objects)) {
913 break_points_hit->set(break_points_hit_count++, *break_point_objects);
917 // Return undefined if no break points were triggered.
918 if (break_points_hit_count == 0) {
919 return factory->undefined_value();
921 // Return break points hit as a JSArray.
922 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
923 result->set_length(Smi::FromInt(break_points_hit_count));
928 // Check whether a single break point object is triggered.
929 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
930 Factory* factory = isolate_->factory();
931 HandleScope scope(isolate_);
933 // Ignore check if break point object is not a JSObject.
934 if (!break_point_object->IsJSObject()) return true;
936 // Get the function IsBreakPointTriggered (defined in debug-debugger.js).
937 Handle<String> is_break_point_triggered_string =
938 factory->InternalizeOneByteString(
939 STATIC_CHAR_VECTOR("IsBreakPointTriggered"));
940 Handle<GlobalObject> debug_global(debug_context()->global_object());
941 Handle<JSFunction> check_break_point =
942 Handle<JSFunction>::cast(Object::GetProperty(
943 debug_global, is_break_point_triggered_string).ToHandleChecked());
945 // Get the break id as an object.
946 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
948 // Call HandleBreakPointx.
949 Handle<Object> argv[] = { break_id, break_point_object };
950 Handle<Object> result;
951 if (!Execution::TryCall(check_break_point,
952 isolate_->js_builtins_object(),
954 argv).ToHandle(&result)) {
958 // Return whether the break point is triggered.
959 return result->IsTrue();
963 // Check whether the function has debug information.
964 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
965 return !shared->debug_info()->IsUndefined();
969 // Return the debug info for this function. EnsureDebugInfo must be called
970 // prior to ensure the debug info has been generated for shared.
971 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
972 DCHECK(HasDebugInfo(shared));
973 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
977 bool Debug::SetBreakPoint(Handle<JSFunction> function,
978 Handle<Object> break_point_object,
979 int* source_position) {
980 HandleScope scope(isolate_);
982 PrepareForBreakPoints();
984 // Make sure the function is compiled and has set up the debug info.
985 Handle<SharedFunctionInfo> shared(function->shared());
986 if (!EnsureDebugInfo(shared, function)) {
987 // Return if retrieving debug info failed.
991 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
992 // Source positions starts with zero.
993 DCHECK(*source_position >= 0);
995 // Find the break point and change it.
996 BreakLocation location = BreakLocation::FromPosition(
997 debug_info, SOURCE_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED);
998 *source_position = location.statement_position();
999 location.SetBreakPoint(break_point_object);
1001 // At least one active break point now.
1002 return debug_info->GetBreakPointCount() > 0;
1006 bool Debug::SetBreakPointForScript(Handle<Script> script,
1007 Handle<Object> break_point_object,
1008 int* source_position,
1009 BreakPositionAlignment alignment) {
1010 HandleScope scope(isolate_);
1012 PrepareForBreakPoints();
1014 // Obtain shared function info for the function.
1015 Handle<Object> result =
1016 FindSharedFunctionInfoInScript(script, *source_position);
1017 if (result->IsUndefined()) return false;
1019 // Make sure the function has set up the debug info.
1020 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
1021 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1022 // Return if retrieving debug info failed.
1026 // Find position within function. The script position might be before the
1027 // source position of the first function.
1029 if (shared->start_position() > *source_position) {
1032 position = *source_position - shared->start_position();
1035 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1036 // Source positions starts with zero.
1037 DCHECK(position >= 0);
1039 // Find the break point and change it.
1040 BreakLocation location = BreakLocation::FromPosition(
1041 debug_info, SOURCE_BREAK_LOCATIONS, position, alignment);
1042 location.SetBreakPoint(break_point_object);
1044 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position()
1045 : location.position();
1047 *source_position = position + shared->start_position();
1049 // At least one active break point now.
1050 DCHECK(debug_info->GetBreakPointCount() > 0);
1055 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1056 HandleScope scope(isolate_);
1058 DebugInfoListNode* node = debug_info_list_;
1059 while (node != NULL) {
1060 Handle<Object> result =
1061 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
1062 if (!result->IsUndefined()) {
1063 // Get information in the break point.
1064 Handle<BreakPointInfo> break_point_info =
1065 Handle<BreakPointInfo>::cast(result);
1066 Handle<DebugInfo> debug_info = node->debug_info();
1068 // Find the break point and clear it.
1069 Address pc = debug_info->code()->entry() +
1070 break_point_info->code_position()->value();
1072 BreakLocation location =
1073 BreakLocation::FromAddress(debug_info, SOURCE_BREAK_LOCATIONS, pc);
1074 location.ClearBreakPoint(break_point_object);
1076 // If there are no more break points left remove the debug info for this
1078 if (debug_info->GetBreakPointCount() == 0) {
1079 RemoveDebugInfoAndClearFromShared(debug_info);
1084 node = node->next();
1089 // Clear out all the debug break code. This is ONLY supposed to be used when
1090 // shutting down the debugger as it will leave the break point information in
1091 // DebugInfo even though the code is patched back to the non break point state.
1092 void Debug::ClearAllBreakPoints() {
1093 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
1094 node = node->next()) {
1095 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1096 !it.Done(); it.Next()) {
1097 it.GetBreakLocation().ClearDebugBreak();
1100 // Remove all debug info.
1101 while (debug_info_list_ != NULL) {
1102 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
1107 void Debug::FloodWithOneShot(Handle<JSFunction> function,
1108 BreakLocatorType type) {
1109 // Do not ever break in native functions.
1110 if (function->IsFromNativeScript()) return;
1112 PrepareForBreakPoints();
1114 // Make sure the function is compiled and has set up the debug info.
1115 Handle<SharedFunctionInfo> shared(function->shared());
1116 if (!EnsureDebugInfo(shared, function)) {
1117 // Return if we failed to retrieve the debug info.
1121 // Flood the function with break points.
1122 for (BreakLocation::Iterator it(GetDebugInfo(shared), type); !it.Done();
1124 it.GetBreakLocation().SetOneShot();
1129 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
1130 Handle<FixedArray> new_bindings(function->function_bindings());
1131 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
1134 if (!bindee.is_null() && bindee->IsJSFunction() &&
1135 !JSFunction::cast(*bindee)->IsFromNativeScript()) {
1136 Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
1137 FloodWithOneShotGeneric(bindee_function);
1142 void Debug::FloodDefaultConstructorWithOneShot(Handle<JSFunction> function) {
1143 DCHECK(function->shared()->is_default_constructor());
1144 // Instead of stepping into the function we directly step into the super class
1146 Isolate* isolate = function->GetIsolate();
1147 PrototypeIterator iter(isolate, function);
1148 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
1149 if (!proto->IsJSFunction()) return; // Object.prototype
1150 Handle<JSFunction> function_proto = Handle<JSFunction>::cast(proto);
1151 FloodWithOneShotGeneric(function_proto);
1155 void Debug::FloodWithOneShotGeneric(Handle<JSFunction> function,
1156 Handle<Object> holder) {
1157 if (function->shared()->bound()) {
1158 FloodBoundFunctionWithOneShot(function);
1159 } else if (function->shared()->is_default_constructor()) {
1160 FloodDefaultConstructorWithOneShot(function);
1162 Isolate* isolate = function->GetIsolate();
1163 // Don't allow step into functions in the native context.
1164 if (function->shared()->code() ==
1165 isolate->builtins()->builtin(Builtins::kFunctionApply) ||
1166 function->shared()->code() ==
1167 isolate->builtins()->builtin(Builtins::kFunctionCall)) {
1168 // Handle function.apply and function.call separately to flood the
1169 // function to be called and not the code for Builtins::FunctionApply or
1170 // Builtins::FunctionCall. The receiver of call/apply is the target
1172 if (!holder.is_null() && holder->IsJSFunction()) {
1173 Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
1174 FloodWithOneShotGeneric(js_function);
1177 FloodWithOneShot(function);
1183 void Debug::FloodHandlerWithOneShot() {
1184 // Iterate through the JavaScript stack looking for handlers.
1185 StackFrame::Id id = break_frame_id();
1186 if (id == StackFrame::NO_ID) {
1187 // If there is no JavaScript stack don't do anything.
1190 for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
1191 JavaScriptFrame* frame = it.frame();
1192 int stack_slots = 0; // The computed stack slot count is not used.
1193 if (frame->LookupExceptionHandlerInTable(&stack_slots) > 0) {
1194 // Flood the function with the catch/finally block with break points.
1195 FloodWithOneShot(Handle<JSFunction>(frame->function()));
1202 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
1203 if (type == BreakUncaughtException) {
1204 break_on_uncaught_exception_ = enable;
1206 break_on_exception_ = enable;
1211 bool Debug::IsBreakOnException(ExceptionBreakType type) {
1212 if (type == BreakUncaughtException) {
1213 return break_on_uncaught_exception_;
1215 return break_on_exception_;
1220 void Debug::PrepareStep(StepAction step_action,
1222 StackFrame::Id frame_id) {
1223 HandleScope scope(isolate_);
1225 PrepareForBreakPoints();
1227 DCHECK(in_debug_scope());
1229 // Remember this step action and count.
1230 thread_local_.last_step_action_ = step_action;
1231 if (step_action == StepOut) {
1232 // For step out target frame will be found on the stack so there is no need
1233 // to set step counter for it. It's expected to always be 0 for StepOut.
1234 thread_local_.step_count_ = 0;
1236 thread_local_.step_count_ = step_count;
1239 // Get the frame where the execution has stopped and skip the debug frame if
1240 // any. The debug frame will only be present if execution was stopped due to
1241 // hitting a break point. In other situations (e.g. unhandled exception) the
1242 // debug frame is not present.
1243 StackFrame::Id id = break_frame_id();
1244 if (id == StackFrame::NO_ID) {
1245 // If there is no JavaScript stack don't do anything.
1248 if (frame_id != StackFrame::NO_ID) {
1251 JavaScriptFrameIterator frames_it(isolate_, id);
1252 JavaScriptFrame* frame = frames_it.frame();
1254 // First of all ensure there is one-shot break points in the top handler
1256 FloodHandlerWithOneShot();
1258 // If the function on the top frame is unresolved perform step out. This will
1259 // be the case when calling unknown function and having the debugger stopped
1260 // in an unhandled exception.
1261 if (!frame->function()->IsJSFunction()) {
1262 // Step out: Find the calling JavaScript frame and flood it with
1264 frames_it.Advance();
1265 // Fill the function to return to with one-shot break points.
1266 JSFunction* function = frames_it.frame()->function();
1267 FloodWithOneShot(Handle<JSFunction>(function));
1271 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
1272 frames_it.frame()->Summarize(&frames);
1273 FrameSummary summary = frames.first();
1275 // Get the debug info (create it if it does not exist).
1276 Handle<JSFunction> function(summary.function());
1277 Handle<SharedFunctionInfo> shared(function->shared());
1278 if (!EnsureDebugInfo(shared, function)) {
1279 // Return if ensuring debug info failed.
1282 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1284 // Compute whether or not the target is a call target.
1285 bool is_load_or_store = false;
1286 bool is_inline_cache_stub = false;
1287 bool is_at_restarted_function = false;
1288 Handle<Code> call_function_stub;
1290 // PC points to the instruction after the current one, possibly a break
1291 // location as well. So the "- 1" to exclude it from the search.
1292 Address call_pc = summary.pc() - 1;
1293 BreakLocation location =
1294 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
1296 if (thread_local_.restarter_frame_function_pointer_ == NULL) {
1297 if (location.IsCodeTarget()) {
1298 Handle<Code> target_code = location.CodeTarget();
1299 is_inline_cache_stub = target_code->is_inline_cache_stub();
1300 is_load_or_store = is_inline_cache_stub && !target_code->is_call_stub();
1302 // Check if target code is CallFunction stub.
1303 Handle<Code> maybe_call_function_stub = target_code;
1304 // If there is a breakpoint at this line look at the original code to
1305 // check if it is a CallFunction stub.
1306 if (location.IsDebugBreak()) {
1307 maybe_call_function_stub = location.OriginalCodeTarget();
1309 if ((maybe_call_function_stub->kind() == Code::STUB &&
1310 CodeStub::GetMajorKey(*maybe_call_function_stub) ==
1311 CodeStub::CallFunction) ||
1312 maybe_call_function_stub->is_call_stub()) {
1313 // Save reference to the code as we may need it to find out arguments
1314 // count for 'step in' later.
1315 call_function_stub = maybe_call_function_stub;
1319 is_at_restarted_function = true;
1322 // If this is the last break code target step out is the only possibility.
1323 if (location.IsExit() || step_action == StepOut) {
1324 if (step_action == StepOut) {
1325 // Skip step_count frames starting with the current one.
1326 while (step_count-- > 0 && !frames_it.done()) {
1327 frames_it.Advance();
1330 DCHECK(location.IsExit());
1331 frames_it.Advance();
1333 // Skip builtin functions on the stack.
1334 while (!frames_it.done() &&
1335 frames_it.frame()->function()->IsFromNativeScript()) {
1336 frames_it.Advance();
1338 // Step out: If there is a JavaScript caller frame, we need to
1339 // flood it with breakpoints.
1340 if (!frames_it.done()) {
1341 // Fill the function to return to with one-shot break points.
1342 JSFunction* function = frames_it.frame()->function();
1343 FloodWithOneShot(Handle<JSFunction>(function));
1344 // Set target frame pointer.
1345 ActivateStepOut(frames_it.frame());
1347 } else if (!(is_inline_cache_stub || location.IsConstructCall() ||
1348 !call_function_stub.is_null() || is_at_restarted_function) ||
1349 step_action == StepNext || step_action == StepMin) {
1350 // Step next or step min.
1352 // Fill the current function with one-shot break points.
1353 // If we are stepping into another frame, only fill calls and returns.
1354 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
1355 : ALL_BREAK_LOCATIONS);
1357 // Remember source position and frame to handle step next.
1358 thread_local_.last_statement_position_ =
1359 debug_info->code()->SourceStatementPosition(summary.pc());
1360 thread_local_.last_fp_ = frame->UnpaddedFP();
1362 // If there's restarter frame on top of the stack, just get the pointer
1363 // to function which is going to be restarted.
1364 if (is_at_restarted_function) {
1365 Handle<JSFunction> restarted_function(
1366 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
1367 FloodWithOneShot(restarted_function);
1368 } else if (!call_function_stub.is_null()) {
1369 // If it's CallFunction stub ensure target function is compiled and flood
1370 // it with one shot breakpoints.
1371 bool is_call_ic = call_function_stub->kind() == Code::CALL_IC;
1373 // Find out number of arguments from the stub minor key.
1374 uint32_t key = call_function_stub->stub_key();
1375 // Argc in the stub is the number of arguments passed - not the
1376 // expected arguments of the called function.
1377 int call_function_arg_count = is_call_ic
1378 ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key))
1379 : CallFunctionStub::ExtractArgcFromMinorKey(
1380 CodeStub::MinorKeyFromKey(key));
1382 DCHECK(is_call_ic ||
1383 CodeStub::GetMajorKey(*call_function_stub) ==
1384 CodeStub::MajorKeyFromKey(key));
1386 // Find target function on the expression stack.
1387 // Expression stack looks like this (top to bottom):
1393 int expressions_count = frame->ComputeExpressionsCount();
1394 DCHECK(expressions_count - 2 - call_function_arg_count >= 0);
1395 Object* fun = frame->GetExpression(
1396 expressions_count - 2 - call_function_arg_count);
1398 // Flood the actual target of call/apply.
1399 if (fun->IsJSFunction()) {
1400 Isolate* isolate = JSFunction::cast(fun)->GetIsolate();
1401 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply);
1402 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall);
1403 while (fun->IsJSFunction()) {
1404 Code* code = JSFunction::cast(fun)->shared()->code();
1405 if (code != apply && code != call) break;
1406 fun = frame->GetExpression(
1407 expressions_count - 1 - call_function_arg_count);
1411 if (fun->IsJSFunction()) {
1412 Handle<JSFunction> js_function(JSFunction::cast(fun));
1413 FloodWithOneShotGeneric(js_function);
1417 // Fill the current function with one-shot break points even for step in on
1418 // a call target as the function called might be a native function for
1419 // which step in will not stop. It also prepares for stepping in
1421 // If we are stepping into another frame, only fill calls and returns.
1422 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
1423 : ALL_BREAK_LOCATIONS);
1425 if (is_load_or_store) {
1426 // Remember source position and frame to handle step in getter/setter. If
1427 // there is a custom getter/setter it will be handled in
1428 // Object::Get/SetPropertyWithAccessor, otherwise the step action will be
1429 // propagated on the next Debug::Break.
1430 thread_local_.last_statement_position_ =
1431 debug_info->code()->SourceStatementPosition(summary.pc());
1432 thread_local_.last_fp_ = frame->UnpaddedFP();
1435 // Step in or Step in min
1436 // Step in through construct call requires no changes to the running code.
1437 // Step in through getters/setters should already be prepared as well
1438 // because caller of this function (Debug::PrepareStep) is expected to
1439 // flood the top frame's function with one shot breakpoints.
1440 // Step in through CallFunction stub should also be prepared by caller of
1441 // this function (Debug::PrepareStep) which should flood target function
1442 // with breakpoints.
1443 DCHECK(location.IsConstructCall() || is_inline_cache_stub ||
1444 !call_function_stub.is_null() || is_at_restarted_function);
1445 ActivateStepIn(frame);
1450 // Check whether the current debug break should be reported to the debugger. It
1451 // is used to have step next and step in only report break back to the debugger
1452 // if on a different frame or in a different statement. In some situations
1453 // there will be several break points in the same statement when the code is
1454 // flooded with one-shot break points. This function helps to perform several
1455 // steps before reporting break back to the debugger.
1456 bool Debug::StepNextContinue(BreakLocation* break_location,
1457 JavaScriptFrame* frame) {
1458 // StepNext and StepOut shouldn't bring us deeper in code, so last frame
1459 // shouldn't be a parent of current frame.
1460 StepAction step_action = thread_local_.last_step_action_;
1462 if (step_action == StepNext || step_action == StepOut) {
1463 if (frame->fp() < thread_local_.last_fp_) return true;
1466 // We stepped into a new frame if the frame pointer changed.
1467 if (step_action == StepFrame) {
1468 return frame->UnpaddedFP() == thread_local_.last_fp_;
1471 // If the step last action was step next or step in make sure that a new
1472 // statement is hit.
1473 if (step_action == StepNext || step_action == StepIn) {
1474 // Never continue if returning from function.
1475 if (break_location->IsExit()) return false;
1477 // Continue if we are still on the same frame and in the same statement.
1478 int current_statement_position =
1479 break_location->code()->SourceStatementPosition(frame->pc());
1480 return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1481 thread_local_.last_statement_position_ == current_statement_position;
1484 // No step next action - don't continue.
1489 // Check whether the code object at the specified address is a debug break code
1491 bool Debug::IsDebugBreak(Address addr) {
1492 Code* code = Code::GetCodeFromTargetAddress(addr);
1493 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK;
1497 // Simple function for returning the source positions for active break points.
1498 Handle<Object> Debug::GetSourceBreakLocations(
1499 Handle<SharedFunctionInfo> shared,
1500 BreakPositionAlignment position_alignment) {
1501 Isolate* isolate = shared->GetIsolate();
1502 Heap* heap = isolate->heap();
1503 if (!HasDebugInfo(shared)) {
1504 return Handle<Object>(heap->undefined_value(), isolate);
1506 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1507 if (debug_info->GetBreakPointCount() == 0) {
1508 return Handle<Object>(heap->undefined_value(), isolate);
1510 Handle<FixedArray> locations =
1511 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1513 for (int i = 0; i < debug_info->break_points()->length(); ++i) {
1514 if (!debug_info->break_points()->get(i)->IsUndefined()) {
1515 BreakPointInfo* break_point_info =
1516 BreakPointInfo::cast(debug_info->break_points()->get(i));
1517 int break_points = break_point_info->GetBreakPointCount();
1518 if (break_points == 0) continue;
1519 Smi* position = NULL;
1520 switch (position_alignment) {
1521 case STATEMENT_ALIGNED:
1522 position = break_point_info->statement_position();
1524 case BREAK_POSITION_ALIGNED:
1525 position = break_point_info->source_position();
1528 for (int j = 0; j < break_points; ++j) locations->set(count++, position);
1535 // Handle stepping into a function.
1536 void Debug::HandleStepIn(Handle<Object> function_obj, Handle<Object> holder,
1537 Address fp, bool is_constructor) {
1538 // Flood getter/setter if we either step in or step to another frame.
1539 bool step_frame = thread_local_.last_step_action_ == StepFrame;
1540 if (!StepInActive() && !step_frame) return;
1541 if (!function_obj->IsJSFunction()) return;
1542 Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj);
1543 Isolate* isolate = function->GetIsolate();
1544 // If the frame pointer is not supplied by the caller find it.
1546 StackFrameIterator it(isolate);
1548 // For constructor functions skip another frame.
1549 if (is_constructor) {
1550 DCHECK(it.frame()->is_construct());
1553 fp = it.frame()->fp();
1556 // Flood the function with one-shot break points if it is called from where
1557 // step into was requested, or when stepping into a new frame.
1558 if (fp == thread_local_.step_into_fp_ || step_frame) {
1559 FloodWithOneShotGeneric(function, holder);
1564 void Debug::ClearStepping() {
1565 // Clear the various stepping setup.
1571 // Clear multiple step counter.
1572 thread_local_.step_count_ = 0;
1576 // Clears all the one-shot break points that are currently set. Normally this
1577 // function is called each time a break point is hit as one shot break points
1578 // are used to support stepping.
1579 void Debug::ClearOneShot() {
1580 // The current implementation just runs through all the breakpoints. When the
1581 // last break point for a function is removed that function is automatically
1582 // removed from the list.
1583 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
1584 node = node->next()) {
1585 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1586 !it.Done(); it.Next()) {
1587 it.GetBreakLocation().ClearOneShot();
1593 void Debug::ActivateStepIn(StackFrame* frame) {
1594 DCHECK(!StepOutActive());
1595 thread_local_.step_into_fp_ = frame->UnpaddedFP();
1599 void Debug::ClearStepIn() {
1600 thread_local_.step_into_fp_ = 0;
1604 void Debug::ActivateStepOut(StackFrame* frame) {
1605 DCHECK(!StepInActive());
1606 thread_local_.step_out_fp_ = frame->UnpaddedFP();
1610 void Debug::ClearStepOut() {
1611 thread_local_.step_out_fp_ = 0;
1615 void Debug::ClearStepNext() {
1616 thread_local_.last_step_action_ = StepNone;
1617 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1618 thread_local_.last_fp_ = 0;
1622 static void CollectActiveFunctionsFromThread(
1624 ThreadLocalTop* top,
1625 List<Handle<JSFunction> >* active_functions,
1626 Object* active_code_marker) {
1627 // Find all non-optimized code functions with activation frames
1628 // on the stack. This includes functions which have optimized
1629 // activations (including inlined functions) on the stack as the
1630 // non-optimized code is needed for the lazy deoptimization.
1631 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1632 JavaScriptFrame* frame = it.frame();
1633 if (frame->is_optimized()) {
1634 List<JSFunction*> functions(FLAG_max_inlining_levels + 1);
1635 frame->GetFunctions(&functions);
1636 for (int i = 0; i < functions.length(); i++) {
1637 JSFunction* function = functions[i];
1638 active_functions->Add(Handle<JSFunction>(function));
1639 function->shared()->code()->set_gc_metadata(active_code_marker);
1641 } else if (frame->function()->IsJSFunction()) {
1642 JSFunction* function = frame->function();
1643 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION);
1644 active_functions->Add(Handle<JSFunction>(function));
1645 function->shared()->code()->set_gc_metadata(active_code_marker);
1651 // Figure out how many bytes of "pc_offset" correspond to actual code by
1652 // subtracting off the bytes that correspond to constant/veneer pools. See
1653 // Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this
1654 // is only useful for architectures using constant pools or veneer pools.
1655 static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) {
1656 DCHECK_EQ(code->kind(), Code::FUNCTION);
1657 DCHECK(!code->has_debug_break_slots());
1658 DCHECK_LE(0, pc_offset);
1659 DCHECK_LT(pc_offset, code->instruction_end() - code->instruction_start());
1661 int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1662 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1663 byte *pc = code->instruction_start() + pc_offset;
1664 int code_offset = pc_offset;
1665 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1666 RelocInfo* info = it.rinfo();
1667 if (info->pc() >= pc) break;
1668 DCHECK(RelocInfo::IsConstPool(info->rmode()));
1669 code_offset -= static_cast<int>(info->data());
1670 DCHECK_LE(0, code_offset);
1677 // The inverse of ComputeCodeOffsetFromPcOffset.
1678 static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) {
1679 DCHECK_EQ(code->kind(), Code::FUNCTION);
1681 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
1682 RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1683 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1685 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1686 RelocInfo* info = it.rinfo();
1687 if (info->pc() - code->instruction_start() - reloc >= code_offset) break;
1688 if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
1689 reloc += Assembler::kDebugBreakSlotLength;
1691 DCHECK(RelocInfo::IsConstPool(info->rmode()));
1692 reloc += static_cast<int>(info->data());
1696 int pc_offset = code_offset + reloc;
1698 DCHECK_LT(code->instruction_start() + pc_offset, code->instruction_end());
1704 static void RedirectActivationsToRecompiledCodeOnThread(
1706 ThreadLocalTop* top) {
1707 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1708 JavaScriptFrame* frame = it.frame();
1710 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue;
1712 JSFunction* function = frame->function();
1714 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION);
1716 Handle<Code> frame_code(frame->LookupCode());
1717 if (frame_code->has_debug_break_slots()) continue;
1719 Handle<Code> new_code(function->shared()->code());
1720 if (new_code->kind() != Code::FUNCTION ||
1721 !new_code->has_debug_break_slots()) {
1726 static_cast<int>(frame->pc() - frame_code->instruction_start());
1727 int code_offset = ComputeCodeOffsetFromPcOffset(*frame_code, old_pc_offset);
1728 int new_pc_offset = ComputePcOffsetFromCodeOffset(*new_code, code_offset);
1730 // Compute the equivalent pc in the new code.
1731 byte* new_pc = new_code->instruction_start() + new_pc_offset;
1733 if (FLAG_trace_deopt) {
1734 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1735 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1737 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
1738 reinterpret_cast<intptr_t>(
1739 frame_code->instruction_start()),
1740 reinterpret_cast<intptr_t>(
1741 frame_code->instruction_start()) +
1742 frame_code->instruction_size(),
1743 frame_code->instruction_size(),
1744 reinterpret_cast<intptr_t>(new_code->instruction_start()),
1745 reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1746 new_code->instruction_size(),
1747 new_code->instruction_size(),
1748 reinterpret_cast<intptr_t>(frame->pc()),
1749 reinterpret_cast<intptr_t>(new_pc));
1752 if (FLAG_enable_ool_constant_pool) {
1753 // Update constant pool pointer for new code.
1754 frame->set_constant_pool(new_code->constant_pool());
1757 // Patch the return address to return into the code with
1758 // debug break slots.
1759 frame->set_pc(new_pc);
1764 class ActiveFunctionsCollector : public ThreadVisitor {
1766 explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
1767 Object* active_code_marker)
1768 : active_functions_(active_functions),
1769 active_code_marker_(active_code_marker) { }
1771 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1772 CollectActiveFunctionsFromThread(isolate,
1775 active_code_marker_);
1779 List<Handle<JSFunction> >* active_functions_;
1780 Object* active_code_marker_;
1784 class ActiveFunctionsRedirector : public ThreadVisitor {
1786 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1787 RedirectActivationsToRecompiledCodeOnThread(isolate, top);
1792 static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) {
1793 if (function->code()->kind() == Code::FUNCTION &&
1794 function->code()->has_debug_break_slots()) {
1795 // Nothing to do. Function code already had debug break slots.
1798 // Make sure that the shared full code is compiled with debug
1800 if (!function->shared()->code()->has_debug_break_slots()) {
1801 MaybeHandle<Code> code = Compiler::GetDebugCode(function);
1802 // Recompilation can fail. In that case leave the code as it was.
1803 if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked());
1805 // Simply use shared code if it has debug break slots.
1806 function->ReplaceCode(function->shared()->code());
1811 static void RecompileAndRelocateSuspendedGenerators(
1812 const List<Handle<JSGeneratorObject> > &generators) {
1813 for (int i = 0; i < generators.length(); i++) {
1814 Handle<JSFunction> fun(generators[i]->function());
1816 EnsureFunctionHasDebugBreakSlots(fun);
1818 int code_offset = generators[i]->continuation();
1819 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset);
1820 generators[i]->set_continuation(pc_offset);
1825 static bool SkipSharedFunctionInfo(SharedFunctionInfo* shared,
1826 Object* active_code_marker) {
1827 if (!shared->allows_lazy_compilation()) return true;
1828 Object* script = shared->script();
1829 if (!script->IsScript()) return true;
1830 if (Script::cast(script)->type()->value() == Script::TYPE_NATIVE) return true;
1831 Code* shared_code = shared->code();
1832 return shared_code->gc_metadata() == active_code_marker;
1836 static inline bool HasDebugBreakSlots(Code* code) {
1837 return code->kind() == Code::FUNCTION && code->has_debug_break_slots();
1841 void Debug::PrepareForBreakPoints() {
1842 // If preparing for the first break point make sure to deoptimize all
1843 // functions as debugging does not work with optimized code.
1844 if (!has_break_points_) {
1845 if (isolate_->concurrent_recompilation_enabled()) {
1846 isolate_->optimizing_compiler_thread()->Flush();
1849 Deoptimizer::DeoptimizeAll(isolate_);
1851 Handle<Code> lazy_compile = isolate_->builtins()->CompileLazy();
1853 // There will be at least one break point when we are done.
1854 has_break_points_ = true;
1856 // Keep the list of activated functions in a handlified list as it
1857 // is used both in GC and non-GC code.
1858 List<Handle<JSFunction> > active_functions(100);
1860 // A list of all suspended generators.
1861 List<Handle<JSGeneratorObject> > suspended_generators;
1863 // A list of all generator functions. We need to recompile all functions,
1864 // but we don't know until after visiting the whole heap which generator
1865 // functions have suspended activations and which do not. As in the case of
1866 // functions with activations on the stack, we need to be careful with
1867 // generator functions with suspended activations because although they
1868 // should be recompiled, recompilation can fail, and we need to avoid
1869 // leaving the heap in an inconsistent state.
1871 // We could perhaps avoid this list and instead re-use the GC metadata
1873 List<Handle<JSFunction> > generator_functions;
1876 // We are going to iterate heap to find all functions without
1877 // debug break slots.
1878 Heap* heap = isolate_->heap();
1879 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1880 "preparing for breakpoints");
1881 HeapIterator iterator(heap);
1883 // Ensure no GC in this scope as we are going to use gc_metadata
1884 // field in the Code object to mark active functions.
1885 DisallowHeapAllocation no_allocation;
1887 Object* active_code_marker = heap->the_hole_value();
1889 CollectActiveFunctionsFromThread(isolate_,
1890 isolate_->thread_local_top(),
1892 active_code_marker);
1893 ActiveFunctionsCollector active_functions_collector(&active_functions,
1894 active_code_marker);
1895 isolate_->thread_manager()->IterateArchivedThreads(
1896 &active_functions_collector);
1898 // Scan the heap for all non-optimized functions which have no
1899 // debug break slots and are not active or inlined into an active
1900 // function and mark them for lazy compilation.
1901 HeapObject* obj = NULL;
1902 while (((obj = iterator.next()) != NULL)) {
1903 if (obj->IsJSFunction()) {
1904 JSFunction* function = JSFunction::cast(obj);
1905 SharedFunctionInfo* shared = function->shared();
1906 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue;
1907 if (shared->is_generator()) {
1908 generator_functions.Add(Handle<JSFunction>(function, isolate_));
1911 if (HasDebugBreakSlots(function->code())) continue;
1912 Code* fallback = HasDebugBreakSlots(shared->code()) ? shared->code()
1914 Code::Kind kind = function->code()->kind();
1915 if (kind == Code::FUNCTION ||
1916 (kind == Code::BUILTIN && // Abort in-flight compilation.
1917 (function->IsInOptimizationQueue() ||
1918 function->IsMarkedForOptimization() ||
1919 function->IsMarkedForConcurrentOptimization()))) {
1920 function->ReplaceCode(fallback);
1922 if (kind == Code::OPTIMIZED_FUNCTION) {
1923 // Optimized code can only get here if DeoptimizeAll did not
1924 // deoptimize turbo fan code.
1925 DCHECK(!FLAG_turbo_deoptimization);
1926 DCHECK(function->code()->is_turbofanned());
1927 function->ReplaceCode(fallback);
1929 } else if (obj->IsJSGeneratorObject()) {
1930 JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
1931 if (!gen->is_suspended()) continue;
1933 JSFunction* fun = gen->function();
1934 DCHECK_EQ(fun->code()->kind(), Code::FUNCTION);
1935 if (fun->code()->has_debug_break_slots()) continue;
1937 int pc_offset = gen->continuation();
1938 DCHECK_LT(0, pc_offset);
1941 ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset);
1943 // This will be fixed after we recompile the functions.
1944 gen->set_continuation(code_offset);
1946 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_));
1947 } else if (obj->IsSharedFunctionInfo()) {
1948 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
1949 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue;
1950 if (shared->is_generator()) continue;
1951 if (HasDebugBreakSlots(shared->code())) continue;
1952 shared->ReplaceCode(*lazy_compile);
1956 // Clear gc_metadata field.
1957 for (int i = 0; i < active_functions.length(); i++) {
1958 Handle<JSFunction> function = active_functions[i];
1959 function->shared()->code()->set_gc_metadata(Smi::FromInt(0));
1963 // Recompile generator functions that have suspended activations, and
1964 // relocate those activations.
1965 RecompileAndRelocateSuspendedGenerators(suspended_generators);
1967 // Mark generator functions that didn't have suspended activations for lazy
1968 // recompilation. Note that this set does not include any active functions.
1969 for (int i = 0; i < generator_functions.length(); i++) {
1970 Handle<JSFunction> &function = generator_functions[i];
1971 if (function->code()->kind() != Code::FUNCTION) continue;
1972 if (function->code()->has_debug_break_slots()) continue;
1973 function->ReplaceCode(*lazy_compile);
1974 function->shared()->ReplaceCode(*lazy_compile);
1977 // Now recompile all functions with activation frames and and
1978 // patch the return address to run in the new compiled code. It could be
1979 // that some active functions were recompiled already by the suspended
1980 // generator recompilation pass above; a generator with suspended
1981 // activations could also have active activations. That's fine.
1982 for (int i = 0; i < active_functions.length(); i++) {
1983 Handle<JSFunction> function = active_functions[i];
1984 Handle<SharedFunctionInfo> shared(function->shared());
1986 // If recompilation is not possible just skip it.
1987 if (shared->is_toplevel()) continue;
1988 if (!shared->allows_lazy_compilation()) continue;
1989 if (shared->code()->kind() == Code::BUILTIN) continue;
1991 EnsureFunctionHasDebugBreakSlots(function);
1994 RedirectActivationsToRecompiledCodeOnThread(isolate_,
1995 isolate_->thread_local_top());
1997 ActiveFunctionsRedirector active_functions_redirector;
1998 isolate_->thread_manager()->IterateArchivedThreads(
1999 &active_functions_redirector);
2004 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2006 // Iterate the heap looking for SharedFunctionInfo generated from the
2007 // script. The inner most SharedFunctionInfo containing the source position
2008 // for the requested break point is found.
2009 // NOTE: This might require several heap iterations. If the SharedFunctionInfo
2010 // which is found is not compiled it is compiled and the heap is iterated
2011 // again as the compilation might create inner functions from the newly
2012 // compiled function and the actual requested break point might be in one of
2014 // NOTE: The below fix-point iteration depends on all functions that cannot be
2015 // compiled lazily without a context to not be compiled at all. Compilation
2016 // will be triggered at points where we do not need a context.
2018 // The current candidate for the source position:
2019 int target_start_position = RelocInfo::kNoPosition;
2020 Handle<JSFunction> target_function;
2021 Handle<SharedFunctionInfo> target;
2022 Heap* heap = isolate_->heap();
2024 { // Extra scope for iterator.
2025 // If lazy compilation is off, we won't have duplicate shared function
2026 // infos that need to be filtered.
2027 HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering
2028 : HeapIterator::kFilterUnreachable);
2029 for (HeapObject* obj = iterator.next();
2030 obj != NULL; obj = iterator.next()) {
2031 bool found_next_candidate = false;
2032 Handle<JSFunction> function;
2033 Handle<SharedFunctionInfo> shared;
2034 if (obj->IsJSFunction()) {
2035 function = Handle<JSFunction>(JSFunction::cast(obj));
2036 shared = Handle<SharedFunctionInfo>(function->shared());
2037 DCHECK(shared->allows_lazy_compilation() || shared->is_compiled());
2038 found_next_candidate = true;
2039 } else if (obj->IsSharedFunctionInfo()) {
2040 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj));
2041 // Skip functions that we cannot compile lazily without a context,
2042 // which is not available here, because there is no closure.
2043 found_next_candidate = shared->is_compiled() ||
2044 shared->allows_lazy_compilation_without_context();
2046 if (!found_next_candidate) continue;
2047 if (shared->script() == *script) {
2048 // If the SharedFunctionInfo found has the requested script data and
2049 // contains the source position it is a candidate.
2050 int start_position = shared->function_token_position();
2051 if (start_position == RelocInfo::kNoPosition) {
2052 start_position = shared->start_position();
2054 if (start_position <= position &&
2055 position <= shared->end_position()) {
2056 // If there is no candidate or this function is within the current
2057 // candidate this is the new candidate.
2058 if (target.is_null()) {
2059 target_start_position = start_position;
2060 target_function = function;
2063 if (target_start_position == start_position &&
2064 shared->end_position() == target->end_position()) {
2065 // If a top-level function contains only one function
2066 // declaration the source for the top-level and the function
2067 // is the same. In that case prefer the non top-level function.
2068 if (!shared->is_toplevel()) {
2069 target_start_position = start_position;
2070 target_function = function;
2073 } else if (target_start_position <= start_position &&
2074 shared->end_position() <= target->end_position()) {
2075 // This containment check includes equality as a function
2076 // inside a top-level function can share either start or end
2077 // position with the top-level function.
2078 target_start_position = start_position;
2079 target_function = function;
2086 } // End no-allocation scope.
2088 if (target.is_null()) return isolate_->factory()->undefined_value();
2090 // There will be at least one break point when we are done.
2091 has_break_points_ = true;
2093 // If the candidate found is compiled we are done.
2094 done = target->is_compiled();
2096 // If the candidate is not compiled, compile it to reveal any inner
2097 // functions which might contain the requested source position. This
2098 // will compile all inner functions that cannot be compiled without a
2099 // context, because Compiler::BuildFunctionInfo checks whether the
2100 // debugger is active.
2101 MaybeHandle<Code> maybe_result = target_function.is_null()
2102 ? Compiler::GetUnoptimizedCode(target)
2103 : Compiler::GetUnoptimizedCode(target_function);
2104 if (maybe_result.is_null()) return isolate_->factory()->undefined_value();
2106 } // End while loop.
2108 // JSFunctions from the same literal may not have the same shared function
2109 // info. Find those JSFunctions and deduplicate the shared function info.
2110 HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering
2111 : HeapIterator::kFilterUnreachable);
2112 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
2113 if (!obj->IsJSFunction()) continue;
2114 JSFunction* function = JSFunction::cast(obj);
2115 SharedFunctionInfo* shared = function->shared();
2116 if (shared != *target && shared->script() == target->script() &&
2117 shared->start_position_and_type() ==
2118 target->start_position_and_type()) {
2119 function->set_shared(*target);
2127 // Ensures the debug information is present for shared.
2128 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2129 Handle<JSFunction> function) {
2130 Isolate* isolate = shared->GetIsolate();
2132 // Return if we already have the debug info for shared.
2133 if (HasDebugInfo(shared)) {
2134 DCHECK(shared->is_compiled());
2138 // There will be at least one break point when we are done.
2139 has_break_points_ = true;
2141 // Ensure function is compiled. Return false if this failed.
2142 if (!function.is_null() &&
2143 !Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) {
2147 // Make sure IC state is clean.
2148 shared->code()->ClearInlineCaches();
2149 shared->feedback_vector()->ClearICSlots(*shared);
2151 // Create the debug info object.
2152 Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared);
2154 // Add debug info to the list.
2155 DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
2156 node->set_next(debug_info_list_);
2157 debug_info_list_ = node;
2163 void Debug::RemoveDebugInfo(DebugInfoListNode* prev, DebugInfoListNode* node) {
2164 // Unlink from list. If prev is NULL we are looking at the first element.
2166 debug_info_list_ = node->next();
2168 prev->set_next(node->next());
2172 // If there are no more debug info objects there are not more break
2174 has_break_points_ = debug_info_list_ != NULL;
2178 void Debug::RemoveDebugInfo(DebugInfo** debug_info) {
2179 DCHECK(debug_info_list_ != NULL);
2180 // Run through the debug info objects to find this one and remove it.
2181 DebugInfoListNode* prev = NULL;
2182 DebugInfoListNode* current = debug_info_list_;
2183 while (current != NULL) {
2184 if (current->debug_info().location() == debug_info) {
2185 RemoveDebugInfo(prev, current);
2188 // Move to next in list.
2190 current = current->next();
2196 void Debug::RemoveDebugInfo(DebugInfoListNode* node) {
2197 DCHECK(debug_info_list_ != NULL);
2198 // Run through the debug info objects to find this one and remove it.
2199 DebugInfoListNode* prev = NULL;
2200 DebugInfoListNode* current = debug_info_list_;
2201 while (current != NULL) {
2202 if (current == node) {
2203 RemoveDebugInfo(prev, node);
2206 // Move to next in list.
2208 current = current->next();
2214 void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) {
2215 HandleScope scope(isolate_);
2216 Handle<SharedFunctionInfo> shared(debug_info->shared());
2218 RemoveDebugInfo(debug_info.location());
2220 shared->set_debug_info(isolate_->heap()->undefined_value());
2224 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
2225 after_break_target_ = NULL;
2227 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job.
2229 HandleScope scope(isolate_);
2230 PrepareForBreakPoints();
2232 // Get the executing function in which the debug break occurred.
2233 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2234 Handle<SharedFunctionInfo> shared(function->shared());
2235 if (!EnsureDebugInfo(shared, function)) {
2236 // Return if we failed to retrieve the debug info.
2239 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2240 Handle<Code> code(debug_info->code());
2241 Handle<Code> original_code(debug_info->original_code());
2243 // Get the code which is actually executing.
2244 Handle<Code> frame_code(frame->LookupCode());
2245 DCHECK(frame_code.is_identical_to(code));
2248 // Find the call address in the running code. This address holds the call to
2249 // either a DebugBreakXXX or to the debug break return entry code if the
2250 // break point is still active after processing the break point.
2251 Address addr = Assembler::break_address_from_return_address(frame->pc());
2253 // Check if the location is at JS exit or debug break slot.
2254 bool at_js_return = false;
2255 bool break_at_js_return_active = false;
2256 bool at_debug_break_slot = false;
2257 RelocIterator it(debug_info->code());
2258 while (!it.done() && !at_js_return && !at_debug_break_slot) {
2259 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2260 at_js_return = (it.rinfo()->pc() ==
2261 addr - Assembler::kPatchReturnSequenceAddressOffset);
2262 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
2264 if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2265 at_debug_break_slot = (it.rinfo()->pc() ==
2266 addr - Assembler::kPatchDebugBreakSlotAddressOffset);
2271 // Handle the jump to continue execution after break point depending on the
2274 // If the break point at return is still active jump to the corresponding
2275 // place in the original code. If not the break point was removed during
2276 // break point processing.
2277 if (break_at_js_return_active) {
2278 addr += original_code->instruction_start() - code->instruction_start();
2281 // Move back to where the call instruction sequence started.
2282 after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset;
2283 } else if (at_debug_break_slot) {
2284 // Address of where the debug break slot starts.
2285 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
2287 // Continue just after the slot.
2288 after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
2290 addr = Assembler::target_address_from_return_address(frame->pc());
2291 if (IsDebugBreak(Assembler::target_address_at(addr, *code))) {
2292 // We now know that there is still a debug break call at the target
2293 // address, so the break point is still there and the original code will
2294 // hold the address to jump to in order to complete the call which is
2295 // replaced by a call to DebugBreakXXX.
2297 // Find the corresponding address in the original code.
2298 addr += original_code->instruction_start() - code->instruction_start();
2300 // Install jump to the call address in the original code. This will be the
2301 // call which was overwritten by the call to DebugBreakXXX.
2302 after_break_target_ = Assembler::target_address_at(addr, *original_code);
2304 // There is no longer a break point present. Don't try to look in the
2305 // original code as the running code will have the right address. This
2306 // takes care of the case where the last break point is removed from the
2307 // function and therefore no "original code" is available.
2308 after_break_target_ = Assembler::target_address_at(addr, *code);
2314 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
2315 HandleScope scope(isolate_);
2317 // If there are no break points this cannot be break at return, as
2318 // the debugger statement and stack guard debug break cannot be at
2320 if (!has_break_points_) {
2324 PrepareForBreakPoints();
2326 // Get the executing function in which the debug break occurred.
2327 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2328 Handle<SharedFunctionInfo> shared(function->shared());
2329 if (!EnsureDebugInfo(shared, function)) {
2330 // Return if we failed to retrieve the debug info.
2333 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2334 Handle<Code> code(debug_info->code());
2336 // Get the code which is actually executing.
2337 Handle<Code> frame_code(frame->LookupCode());
2338 DCHECK(frame_code.is_identical_to(code));
2341 // Find the call address in the running code.
2342 Address addr = Assembler::break_address_from_return_address(frame->pc());
2344 // Check if the location is at JS return.
2345 RelocIterator it(debug_info->code());
2346 while (!it.done()) {
2347 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2348 return (it.rinfo()->pc() ==
2349 addr - Assembler::kPatchReturnSequenceAddressOffset);
2357 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
2358 LiveEdit::FrameDropMode mode,
2359 Object** restarter_frame_function_pointer) {
2360 if (mode != LiveEdit::CURRENTLY_SET_MODE) {
2361 thread_local_.frame_drop_mode_ = mode;
2363 thread_local_.break_frame_id_ = new_break_frame_id;
2364 thread_local_.restarter_frame_function_pointer_ =
2365 restarter_frame_function_pointer;
2369 bool Debug::IsDebugGlobal(GlobalObject* global) {
2370 return is_loaded() && global == debug_context()->global_object();
2374 void Debug::ClearMirrorCache() {
2375 PostponeInterruptsScope postpone(isolate_);
2376 HandleScope scope(isolate_);
2377 AssertDebugContext();
2378 Factory* factory = isolate_->factory();
2379 Handle<GlobalObject> global(isolate_->global_object());
2380 JSObject::SetProperty(global,
2381 factory->NewStringFromAsciiChecked("next_handle_"),
2382 handle(Smi::FromInt(0), isolate_), SLOPPY).Check();
2383 JSObject::SetProperty(global,
2384 factory->NewStringFromAsciiChecked("mirror_cache_"),
2385 factory->NewJSArray(0, FAST_ELEMENTS), SLOPPY).Check();
2389 Handle<FixedArray> Debug::GetLoadedScripts() {
2390 // Create and fill the script cache when the loaded scripts is requested for
2392 if (script_cache_ == NULL) script_cache_ = new ScriptCache(isolate_);
2394 // Perform GC to get unreferenced scripts evicted from the cache before
2395 // returning the content.
2396 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
2397 "Debug::GetLoadedScripts");
2399 // Get the scripts from the cache.
2400 return script_cache_->GetScripts();
2404 void Debug::RecordEvalCaller(Handle<Script> script) {
2405 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
2406 // For eval scripts add information on the function from which eval was
2408 StackTraceFrameIterator it(script->GetIsolate());
2410 script->set_eval_from_shared(it.frame()->function()->shared());
2411 Code* code = it.frame()->LookupCode();
2412 int offset = static_cast<int>(
2413 it.frame()->pc() - code->instruction_start());
2414 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
2419 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name,
2421 Handle<Object> argv[]) {
2422 AssertDebugContext();
2423 // Create the execution state object.
2424 Handle<GlobalObject> global(isolate_->global_object());
2425 Handle<Object> constructor = Object::GetProperty(
2426 isolate_, global, constructor_name).ToHandleChecked();
2427 DCHECK(constructor->IsJSFunction());
2428 if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
2429 // We do not handle interrupts here. In particular, termination interrupts.
2430 PostponeInterruptsScope no_interrupts(isolate_);
2431 return Execution::TryCall(Handle<JSFunction>::cast(constructor),
2432 handle(debug_context()->global_proxy()),
2438 MaybeHandle<Object> Debug::MakeExecutionState() {
2439 // Create the execution state object.
2440 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
2441 return MakeJSObject("MakeExecutionState", arraysize(argv), argv);
2445 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
2446 // Create the new break event object.
2447 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
2449 return MakeJSObject("MakeBreakEvent", arraysize(argv), argv);
2453 MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
2455 Handle<Object> promise) {
2456 // Create the new exception event object.
2457 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
2459 isolate_->factory()->ToBoolean(uncaught),
2461 return MakeJSObject("MakeExceptionEvent", arraysize(argv), argv);
2465 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
2466 v8::DebugEvent type) {
2467 // Create the compile event object.
2468 Handle<Object> script_wrapper = Script::GetWrapper(script);
2469 Handle<Object> argv[] = { script_wrapper,
2470 isolate_->factory()->NewNumberFromInt(type) };
2471 return MakeJSObject("MakeCompileEvent", arraysize(argv), argv);
2475 MaybeHandle<Object> Debug::MakePromiseEvent(Handle<JSObject> event_data) {
2476 // Create the promise event object.
2477 Handle<Object> argv[] = { event_data };
2478 return MakeJSObject("MakePromiseEvent", arraysize(argv), argv);
2482 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
2483 // Create the async task event object.
2484 Handle<Object> argv[] = { task_event };
2485 return MakeJSObject("MakeAsyncTaskEvent", arraysize(argv), argv);
2489 void Debug::OnThrow(Handle<Object> exception) {
2490 if (in_debug_scope() || ignore_events()) return;
2491 // Temporarily clear any scheduled_exception to allow evaluating
2492 // JavaScript from the debug event handler.
2493 HandleScope scope(isolate_);
2494 Handle<Object> scheduled_exception;
2495 if (isolate_->has_scheduled_exception()) {
2496 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
2497 isolate_->clear_scheduled_exception();
2499 OnException(exception, isolate_->GetPromiseOnStackOnThrow());
2500 if (!scheduled_exception.is_null()) {
2501 isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
2506 void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
2507 if (in_debug_scope() || ignore_events()) return;
2508 HandleScope scope(isolate_);
2509 // Check whether the promise has been marked as having triggered a message.
2510 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
2511 if (JSObject::GetDataProperty(promise, key)->IsUndefined()) {
2512 OnException(value, promise);
2517 MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler(
2518 Handle<JSObject> promise) {
2519 Handle<JSFunction> fun = Handle<JSFunction>::cast(
2520 JSObject::GetDataProperty(isolate_->js_builtins_object(),
2521 isolate_->factory()->NewStringFromStaticChars(
2522 "PromiseHasUserDefinedRejectHandler")));
2523 return Execution::Call(isolate_, fun, promise, 0, NULL);
2527 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
2528 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
2529 bool uncaught = (catch_type == Isolate::NOT_CAUGHT);
2530 if (promise->IsJSObject()) {
2531 Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
2532 // Mark the promise as already having triggered a message.
2533 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
2534 JSObject::SetProperty(jspromise, key, key, STRICT).Assert();
2535 // Check whether the promise reject is considered an uncaught exception.
2536 Handle<Object> has_reject_handler;
2537 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2538 isolate_, has_reject_handler,
2539 PromiseHasUserDefinedRejectHandler(jspromise), /* void */);
2540 uncaught = has_reject_handler->IsFalse();
2542 // Bail out if exception breaks are not active
2544 // Uncaught exceptions are reported by either flags.
2545 if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
2547 // Caught exceptions are reported is activated.
2548 if (!break_on_exception_) return;
2551 DebugScope debug_scope(this);
2552 if (debug_scope.failed()) return;
2554 // Clear all current stepping setup.
2557 // Create the event data object.
2558 Handle<Object> event_data;
2559 // Bail out and don't call debugger if exception.
2560 if (!MakeExceptionEvent(
2561 exception, uncaught, promise).ToHandle(&event_data)) {
2565 // Process debug event.
2566 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
2567 // Return to continue execution from where the exception was thrown.
2571 void Debug::OnCompileError(Handle<Script> script) {
2572 if (ignore_events()) return;
2574 if (in_debug_scope()) {
2575 ProcessCompileEventInDebugScope(v8::CompileError, script);
2579 HandleScope scope(isolate_);
2580 DebugScope debug_scope(this);
2581 if (debug_scope.failed()) return;
2583 // Create the compile state object.
2584 Handle<Object> event_data;
2585 // Bail out and don't call debugger if exception.
2586 if (!MakeCompileEvent(script, v8::CompileError).ToHandle(&event_data)) return;
2588 // Process debug event.
2589 ProcessDebugEvent(v8::CompileError, Handle<JSObject>::cast(event_data), true);
2593 void Debug::OnDebugBreak(Handle<Object> break_points_hit,
2594 bool auto_continue) {
2595 // The caller provided for DebugScope.
2596 AssertDebugContext();
2597 // Bail out if there is no listener for this event
2598 if (ignore_events()) return;
2600 HandleScope scope(isolate_);
2601 // Create the event data object.
2602 Handle<Object> event_data;
2603 // Bail out and don't call debugger if exception.
2604 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
2606 // Process debug event.
2607 ProcessDebugEvent(v8::Break,
2608 Handle<JSObject>::cast(event_data),
2613 void Debug::OnBeforeCompile(Handle<Script> script) {
2614 if (in_debug_scope() || ignore_events()) return;
2616 HandleScope scope(isolate_);
2617 DebugScope debug_scope(this);
2618 if (debug_scope.failed()) return;
2620 // Create the event data object.
2621 Handle<Object> event_data;
2622 // Bail out and don't call debugger if exception.
2623 if (!MakeCompileEvent(script, v8::BeforeCompile).ToHandle(&event_data))
2626 // Process debug event.
2627 ProcessDebugEvent(v8::BeforeCompile,
2628 Handle<JSObject>::cast(event_data),
2633 // Handle debugger actions when a new script is compiled.
2634 void Debug::OnAfterCompile(Handle<Script> script) {
2635 // Add the newly compiled script to the script cache.
2636 if (script_cache_ != NULL) script_cache_->Add(script);
2638 if (ignore_events()) return;
2640 if (in_debug_scope()) {
2641 ProcessCompileEventInDebugScope(v8::AfterCompile, script);
2645 HandleScope scope(isolate_);
2646 DebugScope debug_scope(this);
2647 if (debug_scope.failed()) return;
2649 // If debugging there might be script break points registered for this
2650 // script. Make sure that these break points are set.
2652 // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js).
2653 Handle<String> update_script_break_points_string =
2654 isolate_->factory()->InternalizeOneByteString(
2655 STATIC_CHAR_VECTOR("UpdateScriptBreakPoints"));
2656 Handle<GlobalObject> debug_global(debug_context()->global_object());
2657 Handle<Object> update_script_break_points =
2658 Object::GetProperty(
2659 debug_global, update_script_break_points_string).ToHandleChecked();
2660 if (!update_script_break_points->IsJSFunction()) {
2663 DCHECK(update_script_break_points->IsJSFunction());
2665 // Wrap the script object in a proper JS object before passing it
2667 Handle<Object> wrapper = Script::GetWrapper(script);
2669 // Call UpdateScriptBreakPoints expect no exceptions.
2670 Handle<Object> argv[] = { wrapper };
2671 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
2672 isolate_->js_builtins_object(),
2678 // Create the compile state object.
2679 Handle<Object> event_data;
2680 // Bail out and don't call debugger if exception.
2681 if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return;
2683 // Process debug event.
2684 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
2688 void Debug::OnPromiseEvent(Handle<JSObject> data) {
2689 if (in_debug_scope() || ignore_events()) return;
2691 HandleScope scope(isolate_);
2692 DebugScope debug_scope(this);
2693 if (debug_scope.failed()) return;
2695 // Create the script collected state object.
2696 Handle<Object> event_data;
2697 // Bail out and don't call debugger if exception.
2698 if (!MakePromiseEvent(data).ToHandle(&event_data)) return;
2700 // Process debug event.
2701 ProcessDebugEvent(v8::PromiseEvent,
2702 Handle<JSObject>::cast(event_data),
2707 void Debug::OnAsyncTaskEvent(Handle<JSObject> data) {
2708 if (in_debug_scope() || ignore_events()) return;
2710 HandleScope scope(isolate_);
2711 DebugScope debug_scope(this);
2712 if (debug_scope.failed()) return;
2714 // Create the script collected state object.
2715 Handle<Object> event_data;
2716 // Bail out and don't call debugger if exception.
2717 if (!MakeAsyncTaskEvent(data).ToHandle(&event_data)) return;
2719 // Process debug event.
2720 ProcessDebugEvent(v8::AsyncTaskEvent,
2721 Handle<JSObject>::cast(event_data),
2726 void Debug::ProcessDebugEvent(v8::DebugEvent event,
2727 Handle<JSObject> event_data,
2728 bool auto_continue) {
2729 HandleScope scope(isolate_);
2731 // Create the execution state.
2732 Handle<Object> exec_state;
2733 // Bail out and don't call debugger if exception.
2734 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2736 // First notify the message handler if any.
2737 if (message_handler_ != NULL) {
2738 NotifyMessageHandler(event,
2739 Handle<JSObject>::cast(exec_state),
2743 // Notify registered debug event listener. This can be either a C or
2744 // a JavaScript function. Don't call event listener for v8::Break
2745 // here, if it's only a debug command -- they will be processed later.
2746 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
2747 CallEventCallback(event, exec_state, event_data, NULL);
2749 // Process pending debug commands.
2750 if (event == v8::Break) {
2751 while (!event_command_queue_.IsEmpty()) {
2752 CommandMessage command = event_command_queue_.Get();
2753 if (!event_listener_.is_null()) {
2754 CallEventCallback(v8::BreakForCommand,
2757 command.client_data());
2765 void Debug::CallEventCallback(v8::DebugEvent event,
2766 Handle<Object> exec_state,
2767 Handle<Object> event_data,
2768 v8::Debug::ClientData* client_data) {
2769 bool previous = in_debug_event_listener_;
2770 in_debug_event_listener_ = true;
2771 if (event_listener_->IsForeign()) {
2772 // Invoke the C debug event listener.
2773 v8::Debug::EventCallback callback =
2774 FUNCTION_CAST<v8::Debug::EventCallback>(
2775 Handle<Foreign>::cast(event_listener_)->foreign_address());
2776 EventDetailsImpl event_details(event,
2777 Handle<JSObject>::cast(exec_state),
2778 Handle<JSObject>::cast(event_data),
2779 event_listener_data_,
2781 callback(event_details);
2782 DCHECK(!isolate_->has_scheduled_exception());
2784 // Invoke the JavaScript debug event listener.
2785 DCHECK(event_listener_->IsJSFunction());
2786 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
2789 event_listener_data_ };
2790 Handle<JSReceiver> global(isolate_->global_proxy());
2791 Execution::TryCall(Handle<JSFunction>::cast(event_listener_),
2792 global, arraysize(argv), argv);
2794 in_debug_event_listener_ = previous;
2798 void Debug::ProcessCompileEventInDebugScope(v8::DebugEvent event,
2799 Handle<Script> script) {
2800 if (event_listener_.is_null()) return;
2802 SuppressDebug while_processing(this);
2803 DebugScope debug_scope(this);
2804 if (debug_scope.failed()) return;
2806 Handle<Object> event_data;
2807 // Bail out and don't call debugger if exception.
2808 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;
2810 // Create the execution state.
2811 Handle<Object> exec_state;
2812 // Bail out and don't call debugger if exception.
2813 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2815 CallEventCallback(event, exec_state, event_data, NULL);
2819 Handle<Context> Debug::GetDebugContext() {
2820 DebugScope debug_scope(this);
2821 // The global handle may be destroyed soon after. Return it reboxed.
2822 return handle(*debug_context(), isolate_);
2826 void Debug::NotifyMessageHandler(v8::DebugEvent event,
2827 Handle<JSObject> exec_state,
2828 Handle<JSObject> event_data,
2829 bool auto_continue) {
2830 // Prevent other interrupts from triggering, for example API callbacks,
2831 // while dispatching message handler callbacks.
2832 PostponeInterruptsScope no_interrupts(isolate_);
2834 HandleScope scope(isolate_);
2835 // Process the individual events.
2836 bool sendEventMessage = false;
2839 case v8::BreakForCommand:
2840 sendEventMessage = !auto_continue;
2843 sendEventMessage = true;
2845 case v8::BeforeCompile:
2847 case v8::AfterCompile:
2848 sendEventMessage = true;
2850 case v8::NewFunction:
2856 // The debug command interrupt flag might have been set when the command was
2857 // added. It should be enough to clear the flag only once while we are in the
2859 DCHECK(in_debug_scope());
2860 isolate_->stack_guard()->ClearDebugCommand();
2862 // Notify the debugger that a debug event has occurred unless auto continue is
2863 // active in which case no event is send.
2864 if (sendEventMessage) {
2865 MessageImpl message = MessageImpl::NewEvent(
2868 Handle<JSObject>::cast(exec_state),
2869 Handle<JSObject>::cast(event_data));
2870 InvokeMessageHandler(message);
2873 // If auto continue don't make the event cause a break, but process messages
2874 // in the queue if any. For script collected events don't even process
2875 // messages in the queue as the execution state might not be what is expected
2877 if (auto_continue && !has_commands()) return;
2879 // DebugCommandProcessor goes here.
2880 bool running = auto_continue;
2882 Handle<Object> cmd_processor_ctor = Object::GetProperty(
2883 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked();
2884 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
2885 Handle<Object> cmd_processor = Execution::Call(
2886 isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked();
2887 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
2888 Object::GetProperty(
2889 isolate_, cmd_processor, "processDebugRequest").ToHandleChecked());
2890 Handle<Object> is_running = Object::GetProperty(
2891 isolate_, cmd_processor, "isRunning").ToHandleChecked();
2893 // Process requests from the debugger.
2895 // Wait for new command in the queue.
2896 command_received_.Wait();
2898 // Get the command from the queue.
2899 CommandMessage command = command_queue_.Get();
2900 isolate_->logger()->DebugTag(
2901 "Got request from command queue, in interactive loop.");
2903 // Delete command text and user data.
2908 Vector<const uc16> command_text(
2909 const_cast<const uc16*>(command.text().start()),
2910 command.text().length());
2911 Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
2912 command_text).ToHandleChecked();
2913 Handle<Object> request_args[] = { request_text };
2914 Handle<Object> answer_value;
2915 Handle<String> answer;
2916 MaybeHandle<Object> maybe_exception;
2917 MaybeHandle<Object> maybe_result =
2918 Execution::TryCall(process_debug_request, cmd_processor, 1,
2919 request_args, &maybe_exception);
2921 if (maybe_result.ToHandle(&answer_value)) {
2922 if (answer_value->IsUndefined()) {
2923 answer = isolate_->factory()->empty_string();
2925 answer = Handle<String>::cast(answer_value);
2928 // Log the JSON request/response.
2929 if (FLAG_trace_debug_json) {
2930 PrintF("%s\n", request_text->ToCString().get());
2931 PrintF("%s\n", answer->ToCString().get());
2934 Handle<Object> is_running_args[] = { answer };
2935 maybe_result = Execution::Call(
2936 isolate_, is_running, cmd_processor, 1, is_running_args);
2937 Handle<Object> result;
2938 if (!maybe_result.ToHandle(&result)) break;
2939 running = result->IsTrue();
2941 Handle<Object> exception;
2942 if (!maybe_exception.ToHandle(&exception)) break;
2943 Handle<Object> result;
2944 if (!Execution::ToString(isolate_, exception).ToHandle(&result)) break;
2945 answer = Handle<String>::cast(result);
2948 // Return the result.
2949 MessageImpl message = MessageImpl::NewResponse(
2950 event, running, exec_state, event_data, answer, command.client_data());
2951 InvokeMessageHandler(message);
2954 // Return from debug event processing if either the VM is put into the
2955 // running state (through a continue command) or auto continue is active
2956 // and there are no more commands queued.
2957 } while (!running || has_commands());
2958 command_queue_.Clear();
2962 void Debug::SetEventListener(Handle<Object> callback,
2963 Handle<Object> data) {
2964 GlobalHandles* global_handles = isolate_->global_handles();
2966 // Remove existing entry.
2967 GlobalHandles::Destroy(event_listener_.location());
2968 event_listener_ = Handle<Object>();
2969 GlobalHandles::Destroy(event_listener_data_.location());
2970 event_listener_data_ = Handle<Object>();
2973 if (!callback->IsUndefined() && !callback->IsNull()) {
2974 event_listener_ = global_handles->Create(*callback);
2975 if (data.is_null()) data = isolate_->factory()->undefined_value();
2976 event_listener_data_ = global_handles->Create(*data);
2983 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
2984 message_handler_ = handler;
2986 if (handler == NULL && in_debug_scope()) {
2987 // Send an empty command to the debugger if in a break to make JavaScript
2988 // run again if the debugger is closed.
2989 EnqueueCommandMessage(Vector<const uint16_t>::empty());
2995 void Debug::UpdateState() {
2996 is_active_ = message_handler_ != NULL || !event_listener_.is_null();
2997 if (is_active_ || in_debug_scope()) {
2998 // Note that the debug context could have already been loaded to
2999 // bootstrap test cases.
3000 isolate_->compilation_cache()->Disable();
3001 is_active_ = Load();
3002 } else if (is_loaded()) {
3003 isolate_->compilation_cache()->Enable();
3009 // Calls the registered debug message handler. This callback is part of the
3011 void Debug::InvokeMessageHandler(MessageImpl message) {
3012 if (message_handler_ != NULL) message_handler_(message);
3016 // Puts a command coming from the public API on the queue. Creates
3017 // a copy of the command string managed by the debugger. Up to this
3018 // point, the command data was managed by the API client. Called
3019 // by the API client thread.
3020 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
3021 v8::Debug::ClientData* client_data) {
3022 // Need to cast away const.
3023 CommandMessage message = CommandMessage::New(
3024 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
3027 isolate_->logger()->DebugTag("Put command on command_queue.");
3028 command_queue_.Put(message);
3029 command_received_.Signal();
3031 // Set the debug command break flag to have the command processed.
3032 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
3036 void Debug::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
3037 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
3038 event_command_queue_.Put(message);
3040 // Set the debug command break flag to have the command processed.
3041 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
3045 MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) {
3046 DebugScope debug_scope(this);
3047 if (debug_scope.failed()) return isolate_->factory()->undefined_value();
3049 // Create the execution state.
3050 Handle<Object> exec_state;
3051 if (!MakeExecutionState().ToHandle(&exec_state)) {
3052 return isolate_->factory()->undefined_value();
3055 Handle<Object> argv[] = { exec_state, data };
3056 return Execution::Call(
3059 Handle<Object>(debug_context()->global_proxy(), isolate_),
3065 void Debug::HandleDebugBreak() {
3066 // Ignore debug break during bootstrapping.
3067 if (isolate_->bootstrapper()->IsActive()) return;
3068 // Just continue if breaks are disabled.
3069 if (break_disabled()) return;
3070 // Ignore debug break if debugger is not active.
3071 if (!is_active()) return;
3073 StackLimitCheck check(isolate_);
3074 if (check.HasOverflowed()) return;
3076 { JavaScriptFrameIterator it(isolate_);
3078 Object* fun = it.frame()->function();
3079 if (fun && fun->IsJSFunction()) {
3080 // Don't stop in builtin functions.
3081 if (JSFunction::cast(fun)->IsBuiltin()) return;
3082 GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
3083 // Don't stop in debugger functions.
3084 if (IsDebugGlobal(global)) return;
3088 // Collect the break state before clearing the flags.
3089 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
3090 !isolate_->stack_guard()->CheckDebugBreak();
3092 bool is_debugger_statement = !isolate_->stack_guard()->CheckDebugCommand() &&
3093 !isolate_->stack_guard()->CheckDebugBreak();
3095 isolate_->stack_guard()->ClearDebugBreak();
3097 if (is_debugger_statement) {
3098 // If we have been called via 'debugger' Javascript statement,
3099 // we might not be prepared for breakpoints.
3100 // TODO(dslomov,yangguo): CheckDebugBreak may race with RequestDebugBreak.
3101 // Revisit this to clean-up.
3102 HandleScope handle_scope(isolate_);
3103 PrepareForBreakPoints();
3105 ProcessDebugMessages(debug_command_only);
3109 void Debug::ProcessDebugMessages(bool debug_command_only) {
3110 isolate_->stack_guard()->ClearDebugCommand();
3112 StackLimitCheck check(isolate_);
3113 if (check.HasOverflowed()) return;
3115 HandleScope scope(isolate_);
3116 DebugScope debug_scope(this);
3117 if (debug_scope.failed()) return;
3119 // Notify the debug event listeners. Indicate auto continue if the break was
3120 // a debug command break.
3121 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
3125 DebugScope::DebugScope(Debug* debug)
3127 prev_(debug->debugger_entry()),
3128 save_(debug_->isolate_),
3129 no_termination_exceptons_(debug_->isolate_,
3130 StackGuard::TERMINATE_EXECUTION) {
3131 // Link recursive debugger entry.
3132 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
3133 reinterpret_cast<base::AtomicWord>(this));
3135 // Store the previous break id and frame id.
3136 break_id_ = debug_->break_id();
3137 break_frame_id_ = debug_->break_frame_id();
3139 // Create the new break info. If there is no JavaScript frames there is no
3141 JavaScriptFrameIterator it(isolate());
3142 bool has_js_frames = !it.done();
3143 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
3144 : StackFrame::NO_ID;
3145 debug_->SetNextBreakId();
3147 debug_->UpdateState();
3148 // Make sure that debugger is loaded and enter the debugger context.
3149 // The previous context is kept in save_.
3150 failed_ = !debug_->is_loaded();
3151 if (!failed_) isolate()->set_context(*debug->debug_context());
3156 DebugScope::~DebugScope() {
3157 if (!failed_ && prev_ == NULL) {
3158 // Clear mirror cache when leaving the debugger. Skip this if there is a
3159 // pending exception as clearing the mirror cache calls back into
3160 // JavaScript. This can happen if the v8::Debug::Call is used in which
3161 // case the exception should end up in the calling code.
3162 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
3164 // If there are commands in the queue when leaving the debugger request
3165 // that these commands are processed.
3166 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
3169 // Leaving this debugger entry.
3170 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
3171 reinterpret_cast<base::AtomicWord>(prev_));
3173 // Restore to the previous break state.
3174 debug_->thread_local_.break_frame_id_ = break_frame_id_;
3175 debug_->thread_local_.break_id_ = break_id_;
3177 debug_->UpdateState();
3181 MessageImpl MessageImpl::NewEvent(DebugEvent event,
3183 Handle<JSObject> exec_state,
3184 Handle<JSObject> event_data) {
3185 MessageImpl message(true, event, running,
3186 exec_state, event_data, Handle<String>(), NULL);
3191 MessageImpl MessageImpl::NewResponse(DebugEvent event,
3193 Handle<JSObject> exec_state,
3194 Handle<JSObject> event_data,
3195 Handle<String> response_json,
3196 v8::Debug::ClientData* client_data) {
3197 MessageImpl message(false, event, running,
3198 exec_state, event_data, response_json, client_data);
3203 MessageImpl::MessageImpl(bool is_event,
3206 Handle<JSObject> exec_state,
3207 Handle<JSObject> event_data,
3208 Handle<String> response_json,
3209 v8::Debug::ClientData* client_data)
3210 : is_event_(is_event),
3213 exec_state_(exec_state),
3214 event_data_(event_data),
3215 response_json_(response_json),
3216 client_data_(client_data) {}
3219 bool MessageImpl::IsEvent() const {
3224 bool MessageImpl::IsResponse() const {
3229 DebugEvent MessageImpl::GetEvent() const {
3234 bool MessageImpl::WillStartRunning() const {
3239 v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
3240 return v8::Utils::ToLocal(exec_state_);
3244 v8::Isolate* MessageImpl::GetIsolate() const {
3245 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
3249 v8::Handle<v8::Object> MessageImpl::GetEventData() const {
3250 return v8::Utils::ToLocal(event_data_);
3254 v8::Handle<v8::String> MessageImpl::GetJSON() const {
3255 Isolate* isolate = event_data_->GetIsolate();
3256 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
3259 // Call toJSONProtocol on the debug event object.
3260 Handle<Object> fun = Object::GetProperty(
3261 isolate, event_data_, "toJSONProtocol").ToHandleChecked();
3262 if (!fun->IsJSFunction()) {
3263 return v8::Handle<v8::String>();
3266 MaybeHandle<Object> maybe_json =
3267 Execution::TryCall(Handle<JSFunction>::cast(fun), event_data_, 0, NULL);
3268 Handle<Object> json;
3269 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
3270 return v8::Handle<v8::String>();
3272 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
3274 return v8::Utils::ToLocal(response_json_);
3279 v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
3280 Isolate* isolate = event_data_->GetIsolate();
3281 v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
3282 // Isolate::context() may be NULL when "script collected" event occurs.
3283 DCHECK(!context.IsEmpty());
3288 v8::Debug::ClientData* MessageImpl::GetClientData() const {
3289 return client_data_;
3293 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
3294 Handle<JSObject> exec_state,
3295 Handle<JSObject> event_data,
3296 Handle<Object> callback_data,
3297 v8::Debug::ClientData* client_data)
3299 exec_state_(exec_state),
3300 event_data_(event_data),
3301 callback_data_(callback_data),
3302 client_data_(client_data) {}
3305 DebugEvent EventDetailsImpl::GetEvent() const {
3310 v8::Handle<v8::Object> EventDetailsImpl::GetExecutionState() const {
3311 return v8::Utils::ToLocal(exec_state_);
3315 v8::Handle<v8::Object> EventDetailsImpl::GetEventData() const {
3316 return v8::Utils::ToLocal(event_data_);
3320 v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const {
3321 return GetDebugEventContext(exec_state_->GetIsolate());
3325 v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const {
3326 return v8::Utils::ToLocal(callback_data_);
3330 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
3331 return client_data_;
3335 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
3336 client_data_(NULL) {
3340 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
3341 v8::Debug::ClientData* data)
3343 client_data_(data) {
3347 void CommandMessage::Dispose() {
3349 delete client_data_;
3350 client_data_ = NULL;
3354 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
3355 v8::Debug::ClientData* data) {
3356 return CommandMessage(command.Clone(), data);
3360 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
3362 messages_ = NewArray<CommandMessage>(size);
3366 CommandMessageQueue::~CommandMessageQueue() {
3367 while (!IsEmpty()) Get().Dispose();
3368 DeleteArray(messages_);
3372 CommandMessage CommandMessageQueue::Get() {
3374 int result = start_;
3375 start_ = (start_ + 1) % size_;
3376 return messages_[result];
3380 void CommandMessageQueue::Put(const CommandMessage& message) {
3381 if ((end_ + 1) % size_ == start_) {
3384 messages_[end_] = message;
3385 end_ = (end_ + 1) % size_;
3389 void CommandMessageQueue::Expand() {
3390 CommandMessageQueue new_queue(size_ * 2);
3391 while (!IsEmpty()) {
3392 new_queue.Put(Get());
3394 CommandMessage* array_to_free = messages_;
3396 new_queue.messages_ = array_to_free;
3397 // Make the new_queue empty so that it doesn't call Dispose on any messages.
3398 new_queue.start_ = new_queue.end_;
3399 // Automatic destructor called on new_queue, freeing array_to_free.
3403 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
3404 : logger_(logger), queue_(size) {}
3407 bool LockingCommandMessageQueue::IsEmpty() const {
3408 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3409 return queue_.IsEmpty();
3413 CommandMessage LockingCommandMessageQueue::Get() {
3414 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3415 CommandMessage result = queue_.Get();
3416 logger_->DebugEvent("Get", result.text());
3421 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
3422 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3423 queue_.Put(message);
3424 logger_->DebugEvent("Put", message.text());
3428 void LockingCommandMessageQueue::Clear() {
3429 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3433 } } // namespace v8::internal