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/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 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
64 BreakLocatorType type) {
65 debug_info_ = debug_info;
67 reloc_iterator_ = NULL;
68 reloc_iterator_original_ = NULL;
69 Reset(); // Initialize the rest of the member variables.
73 BreakLocationIterator::~BreakLocationIterator() {
74 DCHECK(reloc_iterator_ != NULL);
75 DCHECK(reloc_iterator_original_ != NULL);
76 delete reloc_iterator_;
77 delete reloc_iterator_original_;
81 // Check whether a code stub with the specified major key is a possible break
82 // point location when looking for source break locations.
83 static bool IsSourceBreakStub(Code* code) {
84 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
85 return major_key == CodeStub::CallFunction;
89 // Check whether a code stub with the specified major key is a possible break
91 static bool IsBreakStub(Code* code) {
92 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
93 return major_key == CodeStub::CallFunction;
97 void BreakLocationIterator::Next() {
98 DisallowHeapAllocation no_gc;
101 // Iterate through reloc info for code and original code stopping at each
102 // breakable code target.
103 bool first = break_point_ == -1;
104 while (!RinfoDone()) {
105 if (!first) RinfoNext();
107 if (RinfoDone()) return;
109 // Whenever a statement position or (plain) position is passed update the
110 // current value of these.
111 if (RelocInfo::IsPosition(rmode())) {
112 if (RelocInfo::IsStatementPosition(rmode())) {
113 statement_position_ = static_cast<int>(
114 rinfo()->data() - debug_info_->shared()->start_position());
116 // Always update the position as we don't want that to be before the
117 // statement position.
118 position_ = static_cast<int>(
119 rinfo()->data() - debug_info_->shared()->start_position());
120 DCHECK(position_ >= 0);
121 DCHECK(statement_position_ >= 0);
124 if (IsDebugBreakSlot()) {
125 // There is always a possible break point at a debug break slot.
128 } else if (RelocInfo::IsCodeTarget(rmode())) {
129 // Check for breakable code target. Look in the original code as setting
130 // break points can cause the code targets in the running (debugged) code
131 // to be of a different kind than in the original code.
132 Address target = original_rinfo()->target_address();
133 Code* code = Code::GetCodeFromTargetAddress(target);
134 if ((code->is_inline_cache_stub() &&
135 !code->is_binary_op_stub() &&
136 !code->is_compare_ic_stub() &&
137 !code->is_to_boolean_ic_stub()) ||
138 RelocInfo::IsConstructCall(rmode())) {
142 if (code->kind() == Code::STUB) {
143 if (IsDebuggerStatement()) {
146 } else if (type_ == ALL_BREAK_LOCATIONS) {
147 if (IsBreakStub(code)) {
152 DCHECK(type_ == SOURCE_BREAK_LOCATIONS);
153 if (IsSourceBreakStub(code)) {
161 // Check for break at return.
162 if (RelocInfo::IsJSReturn(rmode())) {
163 // Set the positions to the end of the function.
164 if (debug_info_->shared()->HasSourceCode()) {
165 position_ = debug_info_->shared()->end_position() -
166 debug_info_->shared()->start_position() - 1;
170 statement_position_ = position_;
178 void BreakLocationIterator::Next(int count) {
186 // Find the break point at the supplied address, or the closest one before
188 void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
189 // Run through all break points to locate the one closest to the address.
190 int closest_break_point = 0;
191 int distance = kMaxInt;
193 // Check if this break point is closer that what was previously found.
194 if (this->pc() <= pc && pc - this->pc() < distance) {
195 closest_break_point = break_point();
196 distance = static_cast<int>(pc - this->pc());
197 // Check whether we can't get any closer.
198 if (distance == 0) break;
203 // Move to the break point found.
205 Next(closest_break_point);
209 // Find the break point closest to the supplied source position.
210 void BreakLocationIterator::FindBreakLocationFromPosition(int position,
211 BreakPositionAlignment alignment) {
212 // Run through all break points to locate the one closest to the source
214 int closest_break_point = 0;
215 int distance = kMaxInt;
220 case STATEMENT_ALIGNED:
221 next_position = this->statement_position();
223 case BREAK_POSITION_ALIGNED:
224 next_position = this->position();
228 next_position = this->statement_position();
230 // Check if this break point is closer that what was previously found.
231 if (position <= next_position && next_position - position < distance) {
232 closest_break_point = break_point();
233 distance = next_position - position;
234 // Check whether we can't get any closer.
235 if (distance == 0) break;
240 // Move to the break point found.
242 Next(closest_break_point);
246 void BreakLocationIterator::Reset() {
247 // Create relocation iterators for the two code objects.
248 if (reloc_iterator_ != NULL) delete reloc_iterator_;
249 if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
250 reloc_iterator_ = new RelocIterator(
252 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
253 reloc_iterator_original_ = new RelocIterator(
254 debug_info_->original_code(),
255 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
257 // Position at the first break point.
260 statement_position_ = 1;
265 bool BreakLocationIterator::Done() const {
270 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
271 // If there is not already a real break point here patch code with debug
273 if (!HasBreakPoint()) SetDebugBreak();
274 DCHECK(IsDebugBreak() || IsDebuggerStatement());
275 // Set the break point information.
276 DebugInfo::SetBreakPoint(debug_info_, code_position(),
277 position(), statement_position(),
282 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
283 // Clear the break point information.
284 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
285 // If there are no more break points here remove the debug break.
286 if (!HasBreakPoint()) {
288 DCHECK(!IsDebugBreak());
293 void BreakLocationIterator::SetOneShot() {
294 // Debugger statement always calls debugger. No need to modify it.
295 if (IsDebuggerStatement()) return;
297 // If there is a real break point here no more to do.
298 if (HasBreakPoint()) {
299 DCHECK(IsDebugBreak());
303 // Patch code with debug break.
308 void BreakLocationIterator::ClearOneShot() {
309 // Debugger statement always calls debugger. No need to modify it.
310 if (IsDebuggerStatement()) return;
312 // If there is a real break point here no more to do.
313 if (HasBreakPoint()) {
314 DCHECK(IsDebugBreak());
318 // Patch code removing debug break.
320 DCHECK(!IsDebugBreak());
324 void BreakLocationIterator::SetDebugBreak() {
325 // Debugger statement always calls debugger. No need to modify it.
326 if (IsDebuggerStatement()) return;
328 // If there is already a break point here just return. This might happen if
329 // the same code is flooded with break points twice. Flooding the same
330 // function twice might happen when stepping in a function with an exception
331 // handler as the handler and the function is the same.
332 if (IsDebugBreak()) return;
334 if (RelocInfo::IsJSReturn(rmode())) {
335 // Patch the frame exit code with a break point.
336 SetDebugBreakAtReturn();
337 } else if (IsDebugBreakSlot()) {
338 // Patch the code in the break slot.
339 SetDebugBreakAtSlot();
341 // Patch the IC call.
344 DCHECK(IsDebugBreak());
348 void BreakLocationIterator::ClearDebugBreak() {
349 // Debugger statement always calls debugger. No need to modify it.
350 if (IsDebuggerStatement()) return;
352 if (RelocInfo::IsJSReturn(rmode())) {
353 // Restore the frame exit code.
354 ClearDebugBreakAtReturn();
355 } else if (IsDebugBreakSlot()) {
356 // Restore the code in the break slot.
357 ClearDebugBreakAtSlot();
359 // Patch the IC call.
360 ClearDebugBreakAtIC();
362 DCHECK(!IsDebugBreak());
366 bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
367 if (RelocInfo::IsConstructCall(original_rmode())) {
369 } else if (RelocInfo::IsCodeTarget(rmode())) {
370 HandleScope scope(debug_info_->GetIsolate());
371 Address target = original_rinfo()->target_address();
372 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
373 if (target_code->kind() == Code::STUB) {
374 return CodeStub::GetMajorKey(*target_code) == CodeStub::CallFunction;
376 return target_code->is_call_stub();
382 void BreakLocationIterator::PrepareStepIn(Isolate* isolate) {
384 HandleScope scope(isolate);
385 // Step in can only be prepared if currently positioned on an IC call,
386 // construct call or CallFunction stub call.
387 Address target = rinfo()->target_address();
388 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
389 // All the following stuff is needed only for assertion checks so the code
390 // is wrapped in ifdef.
391 Handle<Code> maybe_call_function_stub = target_code;
392 if (IsDebugBreak()) {
393 Address original_target = original_rinfo()->target_address();
394 maybe_call_function_stub =
395 Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
397 bool is_call_function_stub =
398 (maybe_call_function_stub->kind() == Code::STUB &&
399 CodeStub::GetMajorKey(*maybe_call_function_stub) ==
400 CodeStub::CallFunction);
402 // Step in through construct call requires no changes to the running code.
403 // Step in through getters/setters should already be prepared as well
404 // because caller of this function (Debug::PrepareStep) is expected to
405 // flood the top frame's function with one shot breakpoints.
406 // Step in through CallFunction stub should also be prepared by caller of
407 // this function (Debug::PrepareStep) which should flood target function
409 DCHECK(RelocInfo::IsConstructCall(rmode()) ||
410 target_code->is_inline_cache_stub() ||
411 is_call_function_stub);
416 // Check whether the break point is at a position which will exit the function.
417 bool BreakLocationIterator::IsExit() const {
418 return (RelocInfo::IsJSReturn(rmode()));
422 bool BreakLocationIterator::HasBreakPoint() {
423 return debug_info_->HasBreakPoint(code_position());
427 // Check whether there is a debug break at the current position.
428 bool BreakLocationIterator::IsDebugBreak() {
429 if (RelocInfo::IsJSReturn(rmode())) {
430 return IsDebugBreakAtReturn();
431 } else if (IsDebugBreakSlot()) {
432 return IsDebugBreakAtSlot();
434 return Debug::IsDebugBreak(rinfo()->target_address());
439 // Find the builtin to use for invoking the debug break
440 static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
441 Isolate* isolate = code->GetIsolate();
443 // Find the builtin debug break function matching the calling convention
444 // used by the call site.
445 if (code->is_inline_cache_stub()) {
446 switch (code->kind()) {
448 return isolate->builtins()->CallICStub_DebugBreak();
451 return isolate->builtins()->LoadIC_DebugBreak();
454 return isolate->builtins()->StoreIC_DebugBreak();
456 case Code::KEYED_LOAD_IC:
457 return isolate->builtins()->KeyedLoadIC_DebugBreak();
459 case Code::KEYED_STORE_IC:
460 return isolate->builtins()->KeyedStoreIC_DebugBreak();
462 case Code::COMPARE_NIL_IC:
463 return isolate->builtins()->CompareNilIC_DebugBreak();
469 if (RelocInfo::IsConstructCall(mode)) {
470 if (code->has_function_cache()) {
471 return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
473 return isolate->builtins()->CallConstructStub_DebugBreak();
476 if (code->kind() == Code::STUB) {
477 DCHECK(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction);
478 return isolate->builtins()->CallFunctionStub_DebugBreak();
482 return Handle<Code>::null();
486 void BreakLocationIterator::SetDebugBreakAtIC() {
487 // Patch the original code with the current address as the current address
488 // might have changed by the inline caching since the code was copied.
489 original_rinfo()->set_target_address(rinfo()->target_address());
491 RelocInfo::Mode mode = rmode();
492 if (RelocInfo::IsCodeTarget(mode)) {
493 Address target = rinfo()->target_address();
494 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
496 // Patch the code to invoke the builtin debug break function matching the
497 // calling convention used by the call site.
498 Handle<Code> dbgbrk_code = DebugBreakForIC(target_code, mode);
499 rinfo()->set_target_address(dbgbrk_code->entry());
504 void BreakLocationIterator::ClearDebugBreakAtIC() {
505 // Patch the code to the original invoke.
506 rinfo()->set_target_address(original_rinfo()->target_address());
510 bool BreakLocationIterator::IsDebuggerStatement() {
511 return RelocInfo::DEBUG_BREAK == rmode();
515 bool BreakLocationIterator::IsDebugBreakSlot() {
516 return RelocInfo::DEBUG_BREAK_SLOT == rmode();
520 Object* BreakLocationIterator::BreakPointObjects() {
521 return debug_info_->GetBreakPointObjects(code_position());
525 // Clear out all the debug break code. This is ONLY supposed to be used when
526 // shutting down the debugger as it will leave the break point information in
527 // DebugInfo even though the code is patched back to the non break point state.
528 void BreakLocationIterator::ClearAllDebugBreak() {
536 bool BreakLocationIterator::RinfoDone() const {
537 DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done());
538 return reloc_iterator_->done();
542 void BreakLocationIterator::RinfoNext() {
543 reloc_iterator_->next();
544 reloc_iterator_original_->next();
546 DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done());
547 if (!reloc_iterator_->done()) {
548 DCHECK(rmode() == original_rmode());
554 // Threading support.
555 void Debug::ThreadInit() {
556 thread_local_.break_count_ = 0;
557 thread_local_.break_id_ = 0;
558 thread_local_.break_frame_id_ = StackFrame::NO_ID;
559 thread_local_.last_step_action_ = StepNone;
560 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
561 thread_local_.step_count_ = 0;
562 thread_local_.last_fp_ = 0;
563 thread_local_.queued_step_count_ = 0;
564 thread_local_.step_into_fp_ = 0;
565 thread_local_.step_out_fp_ = 0;
566 // TODO(isolates): frames_are_dropped_?
567 base::NoBarrier_Store(&thread_local_.current_debug_scope_,
568 static_cast<base::AtomicWord>(NULL));
569 thread_local_.restarter_frame_function_pointer_ = NULL;
573 char* Debug::ArchiveDebug(char* storage) {
575 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
577 return storage + ArchiveSpacePerThread();
581 char* Debug::RestoreDebug(char* storage) {
582 char* from = storage;
583 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
584 return storage + ArchiveSpacePerThread();
588 int Debug::ArchiveSpacePerThread() {
589 return sizeof(ThreadLocal);
593 ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch),
595 Heap* heap = isolate_->heap();
596 HandleScope scope(isolate_);
598 // Perform a GC to get rid of all unreferenced scripts.
599 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache");
601 // Scan heap for Script objects.
602 HeapIterator iterator(heap);
603 DisallowHeapAllocation no_allocation;
605 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
606 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
607 Add(Handle<Script>(Script::cast(obj)));
613 void ScriptCache::Add(Handle<Script> script) {
614 GlobalHandles* global_handles = isolate_->global_handles();
615 // Create an entry in the hash map for the script.
616 int id = script->id()->value();
617 HashMap::Entry* entry =
618 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
619 if (entry->value != NULL) {
621 // The code deserializer may introduce duplicate Script objects.
622 // Assert that the Script objects with the same id have the same name.
623 Handle<Script> found(reinterpret_cast<Script**>(entry->value));
624 DCHECK(script->id() == found->id());
625 DCHECK(!script->name()->IsString() ||
626 String::cast(script->name())->Equals(String::cast(found->name())));
630 // Globalize the script object, make it weak and use the location of the
631 // global handle as the value in the hash map.
632 Handle<Script> script_ =
633 Handle<Script>::cast(global_handles->Create(*script));
634 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
636 ScriptCache::HandleWeakScript);
637 entry->value = script_.location();
641 Handle<FixedArray> ScriptCache::GetScripts() {
642 Factory* factory = isolate_->factory();
643 Handle<FixedArray> instances = factory->NewFixedArray(occupancy());
645 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
646 DCHECK(entry->value != NULL);
647 if (entry->value != NULL) {
648 instances->set(count, *reinterpret_cast<Script**>(entry->value));
656 void ScriptCache::Clear() {
657 // Iterate the script cache to get rid of all the weak handles.
658 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
659 DCHECK(entry != NULL);
660 Object** location = reinterpret_cast<Object**>(entry->value);
661 DCHECK((*location)->IsScript());
662 GlobalHandles::ClearWeakness(location);
663 GlobalHandles::Destroy(location);
665 // Clear the content of the hash map.
670 void ScriptCache::HandleWeakScript(
671 const v8::WeakCallbackData<v8::Value, void>& data) {
672 // Retrieve the script identifier.
673 Handle<Object> object = Utils::OpenHandle(*data.GetValue());
674 int id = Handle<Script>::cast(object)->id()->value();
675 void* key = reinterpret_cast<void*>(id);
676 uint32_t hash = Hash(id);
678 // Remove the corresponding entry from the cache.
679 ScriptCache* script_cache =
680 reinterpret_cast<ScriptCache*>(data.GetParameter());
681 HashMap::Entry* entry = script_cache->Lookup(key, hash, false);
682 Object** location = reinterpret_cast<Object**>(entry->value);
683 script_cache->Remove(key, hash);
685 // Clear the weak handle.
686 GlobalHandles::Destroy(location);
690 void Debug::HandleWeakDebugInfo(
691 const v8::WeakCallbackData<v8::Value, void>& data) {
692 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug();
693 DebugInfoListNode* node =
694 reinterpret_cast<DebugInfoListNode*>(data.GetParameter());
695 debug->RemoveDebugInfo(node->debug_info().location());
697 for (DebugInfoListNode* n = debug->debug_info_list_;
706 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
707 // Globalize the request debug info object and make it weak.
708 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
709 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info));
710 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
711 this, Debug::HandleWeakDebugInfo,
712 GlobalHandles::Phantom);
716 DebugInfoListNode::~DebugInfoListNode() {
717 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
721 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
722 Factory* factory = isolate->factory();
723 HandleScope scope(isolate);
725 // Bail out if the index is invalid.
726 if (index == -1) return false;
728 // Find source and name for the requested script.
729 Handle<String> source_code =
730 isolate->bootstrapper()->NativesSourceLookup(index);
731 Vector<const char> name = Natives::GetScriptName(index);
732 Handle<String> script_name =
733 factory->NewStringFromAscii(name).ToHandleChecked();
734 Handle<Context> context = isolate->native_context();
736 // Compile the script.
737 Handle<SharedFunctionInfo> function_info;
738 function_info = Compiler::CompileScript(
739 source_code, script_name, 0, 0, false, context, NULL, NULL,
740 ScriptCompiler::kNoCompileOptions, NATIVES_CODE);
742 // Silently ignore stack overflows during compilation.
743 if (function_info.is_null()) {
744 DCHECK(isolate->has_pending_exception());
745 isolate->clear_pending_exception();
749 // Execute the shared function in the debugger context.
750 Handle<JSFunction> function =
751 factory->NewFunctionFromSharedFunctionInfo(function_info, context);
753 MaybeHandle<Object> maybe_exception;
754 MaybeHandle<Object> result = Execution::TryCall(
755 function, handle(context->global_proxy()), 0, NULL, &maybe_exception);
757 // Check for caught exceptions.
758 if (result.is_null()) {
759 DCHECK(!isolate->has_pending_exception());
760 MessageLocation computed_location;
761 isolate->ComputeLocation(&computed_location);
762 Handle<Object> message = MessageHandler::MakeMessageObject(
763 isolate, "error_loading_debugger", &computed_location,
764 Vector<Handle<Object> >::empty(), Handle<JSArray>());
765 DCHECK(!isolate->has_pending_exception());
766 Handle<Object> exception;
767 if (maybe_exception.ToHandle(&exception)) {
768 isolate->set_pending_exception(*exception);
769 MessageHandler::ReportMessage(isolate, NULL, message);
770 isolate->clear_pending_exception();
775 // Mark this script as native and return successfully.
776 Handle<Script> script(Script::cast(function->shared()->script()));
777 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
783 // Return if debugger is already loaded.
784 if (is_loaded()) return true;
786 // Bail out if we're already in the process of compiling the native
787 // JavaScript source code for the debugger.
788 if (is_suppressed_) return false;
789 SuppressDebug while_loading(this);
791 // Disable breakpoints and interrupts while compiling and running the
792 // debugger scripts including the context creation code.
793 DisableBreak disable(this, true);
794 PostponeInterruptsScope postpone(isolate_);
796 // Create the debugger context.
797 HandleScope scope(isolate_);
798 ExtensionConfiguration no_extensions;
799 Handle<Context> context =
800 isolate_->bootstrapper()->CreateEnvironment(
801 MaybeHandle<JSGlobalProxy>(),
802 v8::Handle<ObjectTemplate>(),
805 // Fail if no context could be created.
806 if (context.is_null()) return false;
808 // Use the debugger context.
809 SaveContext save(isolate_);
810 isolate_->set_context(*context);
812 // Expose the builtins object in the debugger context.
813 Handle<String> key = isolate_->factory()->InternalizeOneByteString(
814 STATIC_CHAR_VECTOR("builtins"));
815 Handle<GlobalObject> global =
816 Handle<GlobalObject>(context->global_object(), isolate_);
817 Handle<JSBuiltinsObject> builtin =
818 Handle<JSBuiltinsObject>(global->builtins(), isolate_);
819 RETURN_ON_EXCEPTION_VALUE(
820 isolate_, Object::SetProperty(global, key, builtin, SLOPPY), false);
822 // Compile the JavaScript for the debugger in the debugger context.
823 bool caught_exception =
824 !CompileDebuggerScript(isolate_, Natives::GetIndex("mirror")) ||
825 !CompileDebuggerScript(isolate_, Natives::GetIndex("debug"));
827 if (FLAG_enable_liveedit) {
828 caught_exception = caught_exception ||
829 !CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit"));
831 // Check for caught exceptions.
832 if (caught_exception) return false;
834 debug_context_ = Handle<Context>::cast(
835 isolate_->global_handles()->Create(*context));
840 void Debug::Unload() {
841 ClearAllBreakPoints();
844 // Return debugger is not loaded.
845 if (!is_loaded()) return;
847 // Clear the script cache.
848 if (script_cache_ != NULL) {
849 delete script_cache_;
850 script_cache_ = NULL;
853 // Clear debugger context global handle.
854 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
855 debug_context_ = Handle<Context>();
859 void Debug::Break(Arguments args, JavaScriptFrame* frame) {
860 Heap* heap = isolate_->heap();
861 HandleScope scope(isolate_);
862 DCHECK(args.length() == 0);
864 // Initialize LiveEdit.
865 LiveEdit::InitializeThreadLocal(this);
867 // Just continue if breaks are disabled or debugger cannot be loaded.
868 if (break_disabled()) return;
870 // Enter the debugger.
871 DebugScope debug_scope(this);
872 if (debug_scope.failed()) return;
874 // Postpone interrupt during breakpoint processing.
875 PostponeInterruptsScope postpone(isolate_);
877 // Get the debug info (create it if it does not exist).
878 Handle<SharedFunctionInfo> shared =
879 Handle<SharedFunctionInfo>(frame->function()->shared());
880 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
882 // Find the break point where execution has stopped.
883 BreakLocationIterator break_location_iterator(debug_info,
884 ALL_BREAK_LOCATIONS);
885 // pc points to the instruction after the current one, possibly a break
886 // location as well. So the "- 1" to exclude it from the search.
887 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
889 // Check whether step next reached a new statement.
890 if (!StepNextContinue(&break_location_iterator, frame)) {
891 // Decrease steps left if performing multiple steps.
892 if (thread_local_.step_count_ > 0) {
893 thread_local_.step_count_--;
897 // If there is one or more real break points check whether any of these are
899 Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
900 if (break_location_iterator.HasBreakPoint()) {
901 Handle<Object> break_point_objects =
902 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_);
903 break_points_hit = CheckBreakPoints(break_point_objects);
906 // If step out is active skip everything until the frame where we need to step
907 // out to is reached, unless real breakpoint is hit.
908 if (StepOutActive() &&
909 frame->fp() != thread_local_.step_out_fp_ &&
910 break_points_hit->IsUndefined() ) {
911 // Step count should always be 0 for StepOut.
912 DCHECK(thread_local_.step_count_ == 0);
913 } else if (!break_points_hit->IsUndefined() ||
914 (thread_local_.last_step_action_ != StepNone &&
915 thread_local_.step_count_ == 0)) {
916 // Notify debugger if a real break point is triggered or if performing
917 // single stepping with no more steps to perform. Otherwise do another step.
919 // Clear all current stepping setup.
922 if (thread_local_.queued_step_count_ > 0) {
923 // Perform queued steps
924 int step_count = thread_local_.queued_step_count_;
927 thread_local_.queued_step_count_ = 0;
929 PrepareStep(StepNext, step_count, StackFrame::NO_ID);
931 // Notify the debug event listeners.
932 OnDebugBreak(break_points_hit, false);
934 } else if (thread_local_.last_step_action_ != StepNone) {
935 // Hold on to last step action as it is cleared by the call to
937 StepAction step_action = thread_local_.last_step_action_;
938 int step_count = thread_local_.step_count_;
940 // If StepNext goes deeper in code, StepOut until original frame
941 // and keep step count queued up in the meantime.
942 if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
943 // Count frames until target frame
945 JavaScriptFrameIterator it(isolate_);
946 while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
951 // Check that we indeed found the frame we are looking for.
952 CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
953 if (step_count > 1) {
954 // Save old count and action to continue stepping after StepOut.
955 thread_local_.queued_step_count_ = step_count - 1;
958 // Set up for StepOut to reach target frame.
959 step_action = StepOut;
963 // Clear all current stepping setup.
966 // Set up for the remaining steps.
967 PrepareStep(step_action, step_count, StackFrame::NO_ID);
972 RUNTIME_FUNCTION(Debug_Break) {
973 // Get the top-most JavaScript frame.
974 JavaScriptFrameIterator it(isolate);
975 isolate->debug()->Break(args, it.frame());
976 isolate->debug()->SetAfterBreakTarget(it.frame());
977 return isolate->heap()->undefined_value();
981 // Check the break point objects for whether one or more are actually
982 // triggered. This function returns a JSArray with the break point objects
983 // which is triggered.
984 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
985 Factory* factory = isolate_->factory();
987 // Count the number of break points hit. If there are multiple break points
988 // they are in a FixedArray.
989 Handle<FixedArray> break_points_hit;
990 int break_points_hit_count = 0;
991 DCHECK(!break_point_objects->IsUndefined());
992 if (break_point_objects->IsFixedArray()) {
993 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
994 break_points_hit = factory->NewFixedArray(array->length());
995 for (int i = 0; i < array->length(); i++) {
996 Handle<Object> o(array->get(i), isolate_);
997 if (CheckBreakPoint(o)) {
998 break_points_hit->set(break_points_hit_count++, *o);
1002 break_points_hit = factory->NewFixedArray(1);
1003 if (CheckBreakPoint(break_point_objects)) {
1004 break_points_hit->set(break_points_hit_count++, *break_point_objects);
1008 // Return undefined if no break points were triggered.
1009 if (break_points_hit_count == 0) {
1010 return factory->undefined_value();
1012 // Return break points hit as a JSArray.
1013 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
1014 result->set_length(Smi::FromInt(break_points_hit_count));
1019 // Check whether a single break point object is triggered.
1020 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
1021 Factory* factory = isolate_->factory();
1022 HandleScope scope(isolate_);
1024 // Ignore check if break point object is not a JSObject.
1025 if (!break_point_object->IsJSObject()) return true;
1027 // Get the function IsBreakPointTriggered (defined in debug-debugger.js).
1028 Handle<String> is_break_point_triggered_string =
1029 factory->InternalizeOneByteString(
1030 STATIC_CHAR_VECTOR("IsBreakPointTriggered"));
1031 Handle<GlobalObject> debug_global(debug_context()->global_object());
1032 Handle<JSFunction> check_break_point =
1033 Handle<JSFunction>::cast(Object::GetProperty(
1034 debug_global, is_break_point_triggered_string).ToHandleChecked());
1036 // Get the break id as an object.
1037 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
1039 // Call HandleBreakPointx.
1040 Handle<Object> argv[] = { break_id, break_point_object };
1041 Handle<Object> result;
1042 if (!Execution::TryCall(check_break_point,
1043 isolate_->js_builtins_object(),
1045 argv).ToHandle(&result)) {
1049 // Return whether the break point is triggered.
1050 return result->IsTrue();
1054 // Check whether the function has debug information.
1055 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
1056 return !shared->debug_info()->IsUndefined();
1060 // Return the debug info for this function. EnsureDebugInfo must be called
1061 // prior to ensure the debug info has been generated for shared.
1062 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
1063 DCHECK(HasDebugInfo(shared));
1064 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
1068 bool Debug::SetBreakPoint(Handle<JSFunction> function,
1069 Handle<Object> break_point_object,
1070 int* source_position) {
1071 HandleScope scope(isolate_);
1073 PrepareForBreakPoints();
1075 // Make sure the function is compiled and has set up the debug info.
1076 Handle<SharedFunctionInfo> shared(function->shared());
1077 if (!EnsureDebugInfo(shared, function)) {
1078 // Return if retrieving debug info failed.
1082 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1083 // Source positions starts with zero.
1084 DCHECK(*source_position >= 0);
1086 // Find the break point and change it.
1087 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1088 it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED);
1089 it.SetBreakPoint(break_point_object);
1091 *source_position = it.statement_position();
1093 // At least one active break point now.
1094 return debug_info->GetBreakPointCount() > 0;
1098 bool Debug::SetBreakPointForScript(Handle<Script> script,
1099 Handle<Object> break_point_object,
1100 int* source_position,
1101 BreakPositionAlignment alignment) {
1102 HandleScope scope(isolate_);
1104 PrepareForBreakPoints();
1106 // Obtain shared function info for the function.
1107 Object* result = FindSharedFunctionInfoInScript(script, *source_position);
1108 if (result->IsUndefined()) return false;
1110 // Make sure the function has set up the debug info.
1111 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
1112 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1113 // Return if retrieving debug info failed.
1117 // Find position within function. The script position might be before the
1118 // source position of the first function.
1120 if (shared->start_position() > *source_position) {
1123 position = *source_position - shared->start_position();
1126 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1127 // Source positions starts with zero.
1128 DCHECK(position >= 0);
1130 // Find the break point and change it.
1131 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1132 it.FindBreakLocationFromPosition(position, alignment);
1133 it.SetBreakPoint(break_point_object);
1135 position = (alignment == STATEMENT_ALIGNED) ? it.statement_position()
1138 *source_position = position + shared->start_position();
1140 // At least one active break point now.
1141 DCHECK(debug_info->GetBreakPointCount() > 0);
1146 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1147 HandleScope scope(isolate_);
1149 DebugInfoListNode* node = debug_info_list_;
1150 while (node != NULL) {
1151 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
1152 break_point_object);
1153 if (!result->IsUndefined()) {
1154 // Get information in the break point.
1155 BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
1156 Handle<DebugInfo> debug_info = node->debug_info();
1158 // Find the break point and clear it.
1159 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1160 it.FindBreakLocationFromAddress(debug_info->code()->entry() +
1161 break_point_info->code_position()->value());
1162 it.ClearBreakPoint(break_point_object);
1164 // If there are no more break points left remove the debug info for this
1166 if (debug_info->GetBreakPointCount() == 0) {
1167 RemoveDebugInfoAndClearFromShared(debug_info);
1172 node = node->next();
1177 void Debug::ClearAllBreakPoints() {
1178 DebugInfoListNode* node = debug_info_list_;
1179 while (node != NULL) {
1180 // Remove all debug break code.
1181 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1182 it.ClearAllDebugBreak();
1183 node = node->next();
1186 // Remove all debug info.
1187 while (debug_info_list_ != NULL) {
1188 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
1193 void Debug::FloodWithOneShot(Handle<JSFunction> function) {
1194 PrepareForBreakPoints();
1196 // Make sure the function is compiled and has set up the debug info.
1197 Handle<SharedFunctionInfo> shared(function->shared());
1198 if (!EnsureDebugInfo(shared, function)) {
1199 // Return if we failed to retrieve the debug info.
1203 // Flood the function with break points.
1204 BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
1205 while (!it.Done()) {
1212 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
1213 Handle<FixedArray> new_bindings(function->function_bindings());
1214 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
1217 if (!bindee.is_null() && bindee->IsJSFunction() &&
1218 !JSFunction::cast(*bindee)->IsFromNativeScript()) {
1219 Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
1220 Debug::FloodWithOneShot(bindee_function);
1225 void Debug::FloodHandlerWithOneShot() {
1226 // Iterate through the JavaScript stack looking for handlers.
1227 StackFrame::Id id = break_frame_id();
1228 if (id == StackFrame::NO_ID) {
1229 // If there is no JavaScript stack don't do anything.
1232 for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
1233 JavaScriptFrame* frame = it.frame();
1234 if (frame->HasHandler()) {
1235 // Flood the function with the catch block with break points
1236 FloodWithOneShot(Handle<JSFunction>(frame->function()));
1243 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
1244 if (type == BreakUncaughtException) {
1245 break_on_uncaught_exception_ = enable;
1247 break_on_exception_ = enable;
1252 bool Debug::IsBreakOnException(ExceptionBreakType type) {
1253 if (type == BreakUncaughtException) {
1254 return break_on_uncaught_exception_;
1256 return break_on_exception_;
1261 void Debug::PrepareStep(StepAction step_action,
1263 StackFrame::Id frame_id) {
1264 HandleScope scope(isolate_);
1266 PrepareForBreakPoints();
1268 DCHECK(in_debug_scope());
1270 // Remember this step action and count.
1271 thread_local_.last_step_action_ = step_action;
1272 if (step_action == StepOut) {
1273 // For step out target frame will be found on the stack so there is no need
1274 // to set step counter for it. It's expected to always be 0 for StepOut.
1275 thread_local_.step_count_ = 0;
1277 thread_local_.step_count_ = step_count;
1280 // Get the frame where the execution has stopped and skip the debug frame if
1281 // any. The debug frame will only be present if execution was stopped due to
1282 // hitting a break point. In other situations (e.g. unhandled exception) the
1283 // debug frame is not present.
1284 StackFrame::Id id = break_frame_id();
1285 if (id == StackFrame::NO_ID) {
1286 // If there is no JavaScript stack don't do anything.
1289 if (frame_id != StackFrame::NO_ID) {
1292 JavaScriptFrameIterator frames_it(isolate_, id);
1293 JavaScriptFrame* frame = frames_it.frame();
1295 // First of all ensure there is one-shot break points in the top handler
1297 FloodHandlerWithOneShot();
1299 // If the function on the top frame is unresolved perform step out. This will
1300 // be the case when calling unknown functions and having the debugger stopped
1301 // in an unhandled exception.
1302 if (!frame->function()->IsJSFunction()) {
1303 // Step out: Find the calling JavaScript frame and flood it with
1305 frames_it.Advance();
1306 // Fill the function to return to with one-shot break points.
1307 JSFunction* function = frames_it.frame()->function();
1308 FloodWithOneShot(Handle<JSFunction>(function));
1312 // Get the debug info (create it if it does not exist).
1313 Handle<JSFunction> function(frame->function());
1314 Handle<SharedFunctionInfo> shared(function->shared());
1315 if (!EnsureDebugInfo(shared, function)) {
1316 // Return if ensuring debug info failed.
1319 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1321 // Find the break location where execution has stopped.
1322 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1323 // pc points to the instruction after the current one, possibly a break
1324 // location as well. So the "- 1" to exclude it from the search.
1325 it.FindBreakLocationFromAddress(frame->pc() - 1);
1327 // Compute whether or not the target is a call target.
1328 bool is_load_or_store = false;
1329 bool is_inline_cache_stub = false;
1330 bool is_at_restarted_function = false;
1331 Handle<Code> call_function_stub;
1333 if (thread_local_.restarter_frame_function_pointer_ == NULL) {
1334 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1335 bool is_call_target = false;
1336 Address target = it.rinfo()->target_address();
1337 Code* code = Code::GetCodeFromTargetAddress(target);
1338 if (code->is_call_stub()) {
1339 is_call_target = true;
1341 if (code->is_inline_cache_stub()) {
1342 is_inline_cache_stub = true;
1343 is_load_or_store = !is_call_target;
1346 // Check if target code is CallFunction stub.
1347 Code* maybe_call_function_stub = code;
1348 // If there is a breakpoint at this line look at the original code to
1349 // check if it is a CallFunction stub.
1350 if (it.IsDebugBreak()) {
1351 Address original_target = it.original_rinfo()->target_address();
1352 maybe_call_function_stub =
1353 Code::GetCodeFromTargetAddress(original_target);
1355 if ((maybe_call_function_stub->kind() == Code::STUB &&
1356 CodeStub::GetMajorKey(maybe_call_function_stub) ==
1357 CodeStub::CallFunction) ||
1358 maybe_call_function_stub->kind() == Code::CALL_IC) {
1359 // Save reference to the code as we may need it to find out arguments
1360 // count for 'step in' later.
1361 call_function_stub = Handle<Code>(maybe_call_function_stub);
1365 is_at_restarted_function = true;
1368 // If this is the last break code target step out is the only possibility.
1369 if (it.IsExit() || step_action == StepOut) {
1370 if (step_action == StepOut) {
1371 // Skip step_count frames starting with the current one.
1372 while (step_count-- > 0 && !frames_it.done()) {
1373 frames_it.Advance();
1376 DCHECK(it.IsExit());
1377 frames_it.Advance();
1379 // Skip builtin functions on the stack.
1380 while (!frames_it.done() &&
1381 frames_it.frame()->function()->IsFromNativeScript()) {
1382 frames_it.Advance();
1384 // Step out: If there is a JavaScript caller frame, we need to
1385 // flood it with breakpoints.
1386 if (!frames_it.done()) {
1387 // Fill the function to return to with one-shot break points.
1388 JSFunction* function = frames_it.frame()->function();
1389 FloodWithOneShot(Handle<JSFunction>(function));
1390 // Set target frame pointer.
1391 ActivateStepOut(frames_it.frame());
1393 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
1394 !call_function_stub.is_null() || is_at_restarted_function)
1395 || step_action == StepNext || step_action == StepMin) {
1396 // Step next or step min.
1398 // Fill the current function with one-shot break points.
1399 FloodWithOneShot(function);
1401 // Remember source position and frame to handle step next.
1402 thread_local_.last_statement_position_ =
1403 debug_info->code()->SourceStatementPosition(frame->pc());
1404 thread_local_.last_fp_ = frame->UnpaddedFP();
1406 // If there's restarter frame on top of the stack, just get the pointer
1407 // to function which is going to be restarted.
1408 if (is_at_restarted_function) {
1409 Handle<JSFunction> restarted_function(
1410 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
1411 FloodWithOneShot(restarted_function);
1412 } else if (!call_function_stub.is_null()) {
1413 // If it's CallFunction stub ensure target function is compiled and flood
1414 // it with one shot breakpoints.
1415 bool is_call_ic = call_function_stub->kind() == Code::CALL_IC;
1417 // Find out number of arguments from the stub minor key.
1418 uint32_t key = call_function_stub->stub_key();
1419 // Argc in the stub is the number of arguments passed - not the
1420 // expected arguments of the called function.
1421 int call_function_arg_count = is_call_ic
1422 ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key))
1423 : CallFunctionStub::ExtractArgcFromMinorKey(
1424 CodeStub::MinorKeyFromKey(key));
1426 DCHECK(is_call_ic ||
1427 CodeStub::GetMajorKey(*call_function_stub) ==
1428 CodeStub::MajorKeyFromKey(key));
1430 // Find target function on the expression stack.
1431 // Expression stack looks like this (top to bottom):
1437 int expressions_count = frame->ComputeExpressionsCount();
1438 DCHECK(expressions_count - 2 - call_function_arg_count >= 0);
1439 Object* fun = frame->GetExpression(
1440 expressions_count - 2 - call_function_arg_count);
1442 // Flood the actual target of call/apply.
1443 if (fun->IsJSFunction()) {
1444 Isolate* isolate = JSFunction::cast(fun)->GetIsolate();
1445 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply);
1446 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall);
1447 while (fun->IsJSFunction()) {
1448 Code* code = JSFunction::cast(fun)->shared()->code();
1449 if (code != apply && code != call) break;
1450 fun = frame->GetExpression(
1451 expressions_count - 1 - call_function_arg_count);
1455 if (fun->IsJSFunction()) {
1456 Handle<JSFunction> js_function(JSFunction::cast(fun));
1457 if (js_function->shared()->bound()) {
1458 Debug::FloodBoundFunctionWithOneShot(js_function);
1459 } else if (!js_function->IsFromNativeScript()) {
1460 // Don't step into builtins.
1461 // It will also compile target function if it's not compiled yet.
1462 FloodWithOneShot(js_function);
1467 // Fill the current function with one-shot break points even for step in on
1468 // a call target as the function called might be a native function for
1469 // which step in will not stop. It also prepares for stepping in
1471 FloodWithOneShot(function);
1473 if (is_load_or_store) {
1474 // Remember source position and frame to handle step in getter/setter. If
1475 // there is a custom getter/setter it will be handled in
1476 // Object::Get/SetPropertyWithAccessor, otherwise the step action will be
1477 // propagated on the next Debug::Break.
1478 thread_local_.last_statement_position_ =
1479 debug_info->code()->SourceStatementPosition(frame->pc());
1480 thread_local_.last_fp_ = frame->UnpaddedFP();
1483 // Step in or Step in min
1484 it.PrepareStepIn(isolate_);
1485 ActivateStepIn(frame);
1490 // Check whether the current debug break should be reported to the debugger. It
1491 // is used to have step next and step in only report break back to the debugger
1492 // if on a different frame or in a different statement. In some situations
1493 // there will be several break points in the same statement when the code is
1494 // flooded with one-shot break points. This function helps to perform several
1495 // steps before reporting break back to the debugger.
1496 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1497 JavaScriptFrame* frame) {
1498 // StepNext and StepOut shouldn't bring us deeper in code, so last frame
1499 // shouldn't be a parent of current frame.
1500 if (thread_local_.last_step_action_ == StepNext ||
1501 thread_local_.last_step_action_ == StepOut) {
1502 if (frame->fp() < thread_local_.last_fp_) return true;
1505 // If the step last action was step next or step in make sure that a new
1506 // statement is hit.
1507 if (thread_local_.last_step_action_ == StepNext ||
1508 thread_local_.last_step_action_ == StepIn) {
1509 // Never continue if returning from function.
1510 if (break_location_iterator->IsExit()) return false;
1512 // Continue if we are still on the same frame and in the same statement.
1513 int current_statement_position =
1514 break_location_iterator->code()->SourceStatementPosition(frame->pc());
1515 return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1516 thread_local_.last_statement_position_ == current_statement_position;
1519 // No step next action - don't continue.
1524 // Check whether the code object at the specified address is a debug break code
1526 bool Debug::IsDebugBreak(Address addr) {
1527 Code* code = Code::GetCodeFromTargetAddress(addr);
1528 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK;
1535 // Simple function for returning the source positions for active break points.
1536 Handle<Object> Debug::GetSourceBreakLocations(
1537 Handle<SharedFunctionInfo> shared,
1538 BreakPositionAlignment position_alignment) {
1539 Isolate* isolate = shared->GetIsolate();
1540 Heap* heap = isolate->heap();
1541 if (!HasDebugInfo(shared)) {
1542 return Handle<Object>(heap->undefined_value(), isolate);
1544 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1545 if (debug_info->GetBreakPointCount() == 0) {
1546 return Handle<Object>(heap->undefined_value(), isolate);
1548 Handle<FixedArray> locations =
1549 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1551 for (int i = 0; i < debug_info->break_points()->length(); i++) {
1552 if (!debug_info->break_points()->get(i)->IsUndefined()) {
1553 BreakPointInfo* break_point_info =
1554 BreakPointInfo::cast(debug_info->break_points()->get(i));
1555 if (break_point_info->GetBreakPointCount() > 0) {
1556 Smi* position = NULL;
1557 switch (position_alignment) {
1558 case STATEMENT_ALIGNED:
1559 position = break_point_info->statement_position();
1561 case BREAK_POSITION_ALIGNED:
1562 position = break_point_info->source_position();
1566 locations->set(count++, position);
1574 // Handle stepping into a function.
1575 void Debug::HandleStepIn(Handle<JSFunction> function,
1576 Handle<Object> holder,
1578 bool is_constructor) {
1579 Isolate* isolate = function->GetIsolate();
1580 // If the frame pointer is not supplied by the caller find it.
1582 StackFrameIterator it(isolate);
1584 // For constructor functions skip another frame.
1585 if (is_constructor) {
1586 DCHECK(it.frame()->is_construct());
1589 fp = it.frame()->fp();
1592 // Flood the function with one-shot break points if it is called from where
1593 // step into was requested.
1594 if (fp == thread_local_.step_into_fp_) {
1595 if (function->shared()->bound()) {
1596 // Handle Function.prototype.bind
1597 Debug::FloodBoundFunctionWithOneShot(function);
1598 } else if (!function->IsFromNativeScript()) {
1599 // Don't allow step into functions in the native context.
1600 if (function->shared()->code() ==
1601 isolate->builtins()->builtin(Builtins::kFunctionApply) ||
1602 function->shared()->code() ==
1603 isolate->builtins()->builtin(Builtins::kFunctionCall)) {
1604 // Handle function.apply and function.call separately to flood the
1605 // function to be called and not the code for Builtins::FunctionApply or
1606 // Builtins::FunctionCall. The receiver of call/apply is the target
1608 if (!holder.is_null() && holder->IsJSFunction()) {
1609 Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
1610 if (!js_function->IsFromNativeScript()) {
1611 Debug::FloodWithOneShot(js_function);
1612 } else if (js_function->shared()->bound()) {
1613 // Handle Function.prototype.bind
1614 Debug::FloodBoundFunctionWithOneShot(js_function);
1618 Debug::FloodWithOneShot(function);
1625 void Debug::ClearStepping() {
1626 // Clear the various stepping setup.
1632 // Clear multiple step counter.
1633 thread_local_.step_count_ = 0;
1637 // Clears all the one-shot break points that are currently set. Normally this
1638 // function is called each time a break point is hit as one shot break points
1639 // are used to support stepping.
1640 void Debug::ClearOneShot() {
1641 // The current implementation just runs through all the breakpoints. When the
1642 // last break point for a function is removed that function is automatically
1643 // removed from the list.
1645 DebugInfoListNode* node = debug_info_list_;
1646 while (node != NULL) {
1647 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1648 while (!it.Done()) {
1652 node = node->next();
1657 void Debug::ActivateStepIn(StackFrame* frame) {
1658 DCHECK(!StepOutActive());
1659 thread_local_.step_into_fp_ = frame->UnpaddedFP();
1663 void Debug::ClearStepIn() {
1664 thread_local_.step_into_fp_ = 0;
1668 void Debug::ActivateStepOut(StackFrame* frame) {
1669 DCHECK(!StepInActive());
1670 thread_local_.step_out_fp_ = frame->UnpaddedFP();
1674 void Debug::ClearStepOut() {
1675 thread_local_.step_out_fp_ = 0;
1679 void Debug::ClearStepNext() {
1680 thread_local_.last_step_action_ = StepNone;
1681 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1682 thread_local_.last_fp_ = 0;
1686 static void CollectActiveFunctionsFromThread(
1688 ThreadLocalTop* top,
1689 List<Handle<JSFunction> >* active_functions,
1690 Object* active_code_marker) {
1691 // Find all non-optimized code functions with activation frames
1692 // on the stack. This includes functions which have optimized
1693 // activations (including inlined functions) on the stack as the
1694 // non-optimized code is needed for the lazy deoptimization.
1695 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1696 JavaScriptFrame* frame = it.frame();
1697 if (frame->is_optimized()) {
1698 List<JSFunction*> functions(FLAG_max_inlining_levels + 1);
1699 frame->GetFunctions(&functions);
1700 for (int i = 0; i < functions.length(); i++) {
1701 JSFunction* function = functions[i];
1702 active_functions->Add(Handle<JSFunction>(function));
1703 function->shared()->code()->set_gc_metadata(active_code_marker);
1705 } else if (frame->function()->IsJSFunction()) {
1706 JSFunction* function = frame->function();
1707 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION);
1708 active_functions->Add(Handle<JSFunction>(function));
1709 function->shared()->code()->set_gc_metadata(active_code_marker);
1715 // Figure out how many bytes of "pc_offset" correspond to actual code by
1716 // subtracting off the bytes that correspond to constant/veneer pools. See
1717 // Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this
1718 // is only useful for architectures using constant pools or veneer pools.
1719 static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) {
1720 DCHECK_EQ(code->kind(), Code::FUNCTION);
1721 DCHECK(!code->has_debug_break_slots());
1722 DCHECK_LE(0, pc_offset);
1723 DCHECK_LT(pc_offset, code->instruction_end() - code->instruction_start());
1725 int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1726 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1727 byte *pc = code->instruction_start() + pc_offset;
1728 int code_offset = pc_offset;
1729 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1730 RelocInfo* info = it.rinfo();
1731 if (info->pc() >= pc) break;
1732 DCHECK(RelocInfo::IsConstPool(info->rmode()));
1733 code_offset -= static_cast<int>(info->data());
1734 DCHECK_LE(0, code_offset);
1741 // The inverse of ComputeCodeOffsetFromPcOffset.
1742 static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) {
1743 DCHECK_EQ(code->kind(), Code::FUNCTION);
1745 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
1746 RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1747 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1749 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1750 RelocInfo* info = it.rinfo();
1751 if (info->pc() - code->instruction_start() - reloc >= code_offset) break;
1752 if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
1753 reloc += Assembler::kDebugBreakSlotLength;
1755 DCHECK(RelocInfo::IsConstPool(info->rmode()));
1756 reloc += static_cast<int>(info->data());
1760 int pc_offset = code_offset + reloc;
1762 DCHECK_LT(code->instruction_start() + pc_offset, code->instruction_end());
1768 static void RedirectActivationsToRecompiledCodeOnThread(
1770 ThreadLocalTop* top) {
1771 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1772 JavaScriptFrame* frame = it.frame();
1774 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue;
1776 JSFunction* function = frame->function();
1778 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION);
1780 Handle<Code> frame_code(frame->LookupCode());
1781 if (frame_code->has_debug_break_slots()) continue;
1783 Handle<Code> new_code(function->shared()->code());
1784 if (new_code->kind() != Code::FUNCTION ||
1785 !new_code->has_debug_break_slots()) {
1790 static_cast<int>(frame->pc() - frame_code->instruction_start());
1791 int code_offset = ComputeCodeOffsetFromPcOffset(*frame_code, old_pc_offset);
1792 int new_pc_offset = ComputePcOffsetFromCodeOffset(*new_code, code_offset);
1794 // Compute the equivalent pc in the new code.
1795 byte* new_pc = new_code->instruction_start() + new_pc_offset;
1797 if (FLAG_trace_deopt) {
1798 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1799 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1801 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
1802 reinterpret_cast<intptr_t>(
1803 frame_code->instruction_start()),
1804 reinterpret_cast<intptr_t>(
1805 frame_code->instruction_start()) +
1806 frame_code->instruction_size(),
1807 frame_code->instruction_size(),
1808 reinterpret_cast<intptr_t>(new_code->instruction_start()),
1809 reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1810 new_code->instruction_size(),
1811 new_code->instruction_size(),
1812 reinterpret_cast<intptr_t>(frame->pc()),
1813 reinterpret_cast<intptr_t>(new_pc));
1816 if (FLAG_enable_ool_constant_pool) {
1817 // Update constant pool pointer for new code.
1818 frame->set_constant_pool(new_code->constant_pool());
1821 // Patch the return address to return into the code with
1822 // debug break slots.
1823 frame->set_pc(new_pc);
1828 class ActiveFunctionsCollector : public ThreadVisitor {
1830 explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
1831 Object* active_code_marker)
1832 : active_functions_(active_functions),
1833 active_code_marker_(active_code_marker) { }
1835 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1836 CollectActiveFunctionsFromThread(isolate,
1839 active_code_marker_);
1843 List<Handle<JSFunction> >* active_functions_;
1844 Object* active_code_marker_;
1848 class ActiveFunctionsRedirector : public ThreadVisitor {
1850 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1851 RedirectActivationsToRecompiledCodeOnThread(isolate, top);
1856 static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) {
1857 if (function->code()->kind() == Code::FUNCTION &&
1858 function->code()->has_debug_break_slots()) {
1859 // Nothing to do. Function code already had debug break slots.
1862 // Make sure that the shared full code is compiled with debug
1864 if (!function->shared()->code()->has_debug_break_slots()) {
1865 MaybeHandle<Code> code = Compiler::GetDebugCode(function);
1866 // Recompilation can fail. In that case leave the code as it was.
1867 if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked());
1869 // Simply use shared code if it has debug break slots.
1870 function->ReplaceCode(function->shared()->code());
1875 static void RecompileAndRelocateSuspendedGenerators(
1876 const List<Handle<JSGeneratorObject> > &generators) {
1877 for (int i = 0; i < generators.length(); i++) {
1878 Handle<JSFunction> fun(generators[i]->function());
1880 EnsureFunctionHasDebugBreakSlots(fun);
1882 int code_offset = generators[i]->continuation();
1883 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset);
1884 generators[i]->set_continuation(pc_offset);
1889 static bool SkipSharedFunctionInfo(SharedFunctionInfo* shared,
1890 Object* active_code_marker) {
1891 if (!shared->allows_lazy_compilation()) return true;
1892 if (!shared->script()->IsScript()) return true;
1893 Object* script = shared->script();
1894 if (!script->IsScript()) return true;
1895 if (Script::cast(script)->type()->value() == Script::TYPE_NATIVE) return true;
1896 Code* shared_code = shared->code();
1897 return shared_code->gc_metadata() == active_code_marker;
1901 static inline bool HasDebugBreakSlots(Code* code) {
1902 return code->kind() == Code::FUNCTION && code->has_debug_break_slots();
1906 void Debug::PrepareForBreakPoints() {
1907 // If preparing for the first break point make sure to deoptimize all
1908 // functions as debugging does not work with optimized code.
1909 if (!has_break_points_) {
1910 if (isolate_->concurrent_recompilation_enabled()) {
1911 isolate_->optimizing_compiler_thread()->Flush();
1914 Deoptimizer::DeoptimizeAll(isolate_);
1916 Handle<Code> lazy_compile = isolate_->builtins()->CompileLazy();
1918 // There will be at least one break point when we are done.
1919 has_break_points_ = true;
1921 // Keep the list of activated functions in a handlified list as it
1922 // is used both in GC and non-GC code.
1923 List<Handle<JSFunction> > active_functions(100);
1925 // A list of all suspended generators.
1926 List<Handle<JSGeneratorObject> > suspended_generators;
1928 // A list of all generator functions. We need to recompile all functions,
1929 // but we don't know until after visiting the whole heap which generator
1930 // functions have suspended activations and which do not. As in the case of
1931 // functions with activations on the stack, we need to be careful with
1932 // generator functions with suspended activations because although they
1933 // should be recompiled, recompilation can fail, and we need to avoid
1934 // leaving the heap in an inconsistent state.
1936 // We could perhaps avoid this list and instead re-use the GC metadata
1938 List<Handle<JSFunction> > generator_functions;
1941 // We are going to iterate heap to find all functions without
1942 // debug break slots.
1943 Heap* heap = isolate_->heap();
1944 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1945 "preparing for breakpoints");
1946 HeapIterator iterator(heap);
1948 // Ensure no GC in this scope as we are going to use gc_metadata
1949 // field in the Code object to mark active functions.
1950 DisallowHeapAllocation no_allocation;
1952 Object* active_code_marker = heap->the_hole_value();
1954 CollectActiveFunctionsFromThread(isolate_,
1955 isolate_->thread_local_top(),
1957 active_code_marker);
1958 ActiveFunctionsCollector active_functions_collector(&active_functions,
1959 active_code_marker);
1960 isolate_->thread_manager()->IterateArchivedThreads(
1961 &active_functions_collector);
1963 // Scan the heap for all non-optimized functions which have no
1964 // debug break slots and are not active or inlined into an active
1965 // function and mark them for lazy compilation.
1966 HeapObject* obj = NULL;
1967 while (((obj = iterator.next()) != NULL)) {
1968 if (obj->IsJSFunction()) {
1969 JSFunction* function = JSFunction::cast(obj);
1970 SharedFunctionInfo* shared = function->shared();
1971 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue;
1972 if (shared->is_generator()) {
1973 generator_functions.Add(Handle<JSFunction>(function, isolate_));
1976 if (HasDebugBreakSlots(function->code())) continue;
1977 Code* fallback = HasDebugBreakSlots(shared->code()) ? shared->code()
1979 Code::Kind kind = function->code()->kind();
1980 if (kind == Code::FUNCTION ||
1981 (kind == Code::BUILTIN && // Abort in-flight compilation.
1982 (function->IsInOptimizationQueue() ||
1983 function->IsMarkedForOptimization() ||
1984 function->IsMarkedForConcurrentOptimization()))) {
1985 function->ReplaceCode(fallback);
1987 if (kind == Code::OPTIMIZED_FUNCTION) {
1988 // Optimized code can only get here if DeoptimizeAll did not
1989 // deoptimize turbo fan code.
1990 DCHECK(!FLAG_turbo_deoptimization);
1991 DCHECK(function->code()->is_turbofanned());
1992 function->ReplaceCode(fallback);
1994 } else if (obj->IsJSGeneratorObject()) {
1995 JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
1996 if (!gen->is_suspended()) continue;
1998 JSFunction* fun = gen->function();
1999 DCHECK_EQ(fun->code()->kind(), Code::FUNCTION);
2000 if (fun->code()->has_debug_break_slots()) continue;
2002 int pc_offset = gen->continuation();
2003 DCHECK_LT(0, pc_offset);
2006 ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset);
2008 // This will be fixed after we recompile the functions.
2009 gen->set_continuation(code_offset);
2011 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_));
2012 } else if (obj->IsSharedFunctionInfo()) {
2013 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
2014 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue;
2015 if (shared->is_generator()) continue;
2016 if (HasDebugBreakSlots(shared->code())) continue;
2017 shared->ReplaceCode(*lazy_compile);
2021 // Clear gc_metadata field.
2022 for (int i = 0; i < active_functions.length(); i++) {
2023 Handle<JSFunction> function = active_functions[i];
2024 function->shared()->code()->set_gc_metadata(Smi::FromInt(0));
2028 // Recompile generator functions that have suspended activations, and
2029 // relocate those activations.
2030 RecompileAndRelocateSuspendedGenerators(suspended_generators);
2032 // Mark generator functions that didn't have suspended activations for lazy
2033 // recompilation. Note that this set does not include any active functions.
2034 for (int i = 0; i < generator_functions.length(); i++) {
2035 Handle<JSFunction> &function = generator_functions[i];
2036 if (function->code()->kind() != Code::FUNCTION) continue;
2037 if (function->code()->has_debug_break_slots()) continue;
2038 function->ReplaceCode(*lazy_compile);
2039 function->shared()->ReplaceCode(*lazy_compile);
2042 // Now recompile all functions with activation frames and and
2043 // patch the return address to run in the new compiled code. It could be
2044 // that some active functions were recompiled already by the suspended
2045 // generator recompilation pass above; a generator with suspended
2046 // activations could also have active activations. That's fine.
2047 for (int i = 0; i < active_functions.length(); i++) {
2048 Handle<JSFunction> function = active_functions[i];
2049 Handle<SharedFunctionInfo> shared(function->shared());
2051 // If recompilation is not possible just skip it.
2052 if (shared->is_toplevel()) continue;
2053 if (!shared->allows_lazy_compilation()) continue;
2054 if (shared->code()->kind() == Code::BUILTIN) continue;
2056 EnsureFunctionHasDebugBreakSlots(function);
2059 RedirectActivationsToRecompiledCodeOnThread(isolate_,
2060 isolate_->thread_local_top());
2062 ActiveFunctionsRedirector active_functions_redirector;
2063 isolate_->thread_manager()->IterateArchivedThreads(
2064 &active_functions_redirector);
2069 Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2071 // Iterate the heap looking for SharedFunctionInfo generated from the
2072 // script. The inner most SharedFunctionInfo containing the source position
2073 // for the requested break point is found.
2074 // NOTE: This might require several heap iterations. If the SharedFunctionInfo
2075 // which is found is not compiled it is compiled and the heap is iterated
2076 // again as the compilation might create inner functions from the newly
2077 // compiled function and the actual requested break point might be in one of
2079 // NOTE: The below fix-point iteration depends on all functions that cannot be
2080 // compiled lazily without a context to not be compiled at all. Compilation
2081 // will be triggered at points where we do not need a context.
2083 // The current candidate for the source position:
2084 int target_start_position = RelocInfo::kNoPosition;
2085 Handle<JSFunction> target_function;
2086 Handle<SharedFunctionInfo> target;
2087 Heap* heap = isolate_->heap();
2089 { // Extra scope for iterator.
2090 HeapIterator iterator(heap);
2091 for (HeapObject* obj = iterator.next();
2092 obj != NULL; obj = iterator.next()) {
2093 bool found_next_candidate = false;
2094 Handle<JSFunction> function;
2095 Handle<SharedFunctionInfo> shared;
2096 if (obj->IsJSFunction()) {
2097 function = Handle<JSFunction>(JSFunction::cast(obj));
2098 shared = Handle<SharedFunctionInfo>(function->shared());
2099 DCHECK(shared->allows_lazy_compilation() || shared->is_compiled());
2100 found_next_candidate = true;
2101 } else if (obj->IsSharedFunctionInfo()) {
2102 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj));
2103 // Skip functions that we cannot compile lazily without a context,
2104 // which is not available here, because there is no closure.
2105 found_next_candidate = shared->is_compiled() ||
2106 shared->allows_lazy_compilation_without_context();
2108 if (!found_next_candidate) continue;
2109 if (shared->script() == *script) {
2110 // If the SharedFunctionInfo found has the requested script data and
2111 // contains the source position it is a candidate.
2112 int start_position = shared->function_token_position();
2113 if (start_position == RelocInfo::kNoPosition) {
2114 start_position = shared->start_position();
2116 if (start_position <= position &&
2117 position <= shared->end_position()) {
2118 // If there is no candidate or this function is within the current
2119 // candidate this is the new candidate.
2120 if (target.is_null()) {
2121 target_start_position = start_position;
2122 target_function = function;
2125 if (target_start_position == start_position &&
2126 shared->end_position() == target->end_position()) {
2127 // If a top-level function contains only one function
2128 // declaration the source for the top-level and the function
2129 // is the same. In that case prefer the non top-level function.
2130 if (!shared->is_toplevel()) {
2131 target_start_position = start_position;
2132 target_function = function;
2135 } else if (target_start_position <= start_position &&
2136 shared->end_position() <= target->end_position()) {
2137 // This containment check includes equality as a function
2138 // inside a top-level function can share either start or end
2139 // position with the top-level function.
2140 target_start_position = start_position;
2141 target_function = function;
2148 } // End no-allocation scope.
2150 if (target.is_null()) return heap->undefined_value();
2152 // There will be at least one break point when we are done.
2153 has_break_points_ = true;
2155 // If the candidate found is compiled we are done.
2156 done = target->is_compiled();
2158 // If the candidate is not compiled, compile it to reveal any inner
2159 // functions which might contain the requested source position. This
2160 // will compile all inner functions that cannot be compiled without a
2161 // context, because Compiler::BuildFunctionInfo checks whether the
2162 // debugger is active.
2163 MaybeHandle<Code> maybe_result = target_function.is_null()
2164 ? Compiler::GetUnoptimizedCode(target)
2165 : Compiler::GetUnoptimizedCode(target_function);
2166 if (maybe_result.is_null()) return isolate_->heap()->undefined_value();
2168 } // End while loop.
2174 // Ensures the debug information is present for shared.
2175 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2176 Handle<JSFunction> function) {
2177 Isolate* isolate = shared->GetIsolate();
2179 // Return if we already have the debug info for shared.
2180 if (HasDebugInfo(shared)) {
2181 DCHECK(shared->is_compiled());
2185 // There will be at least one break point when we are done.
2186 has_break_points_ = true;
2188 // Ensure function is compiled. Return false if this failed.
2189 if (!function.is_null() &&
2190 !Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) {
2194 // Create the debug info object.
2195 Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared);
2197 // Add debug info to the list.
2198 DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
2199 node->set_next(debug_info_list_);
2200 debug_info_list_ = node;
2206 // This uses the location of a handle to look up the debug info in the debug
2207 // info list, but it doesn't use the actual debug info for anything. Therefore
2208 // if the debug info has been collected by the GC, we can be sure that this
2209 // method will not attempt to resurrect it.
2210 void Debug::RemoveDebugInfo(DebugInfo** debug_info) {
2211 DCHECK(debug_info_list_ != NULL);
2212 // Run through the debug info objects to find this one and remove it.
2213 DebugInfoListNode* prev = NULL;
2214 DebugInfoListNode* current = debug_info_list_;
2215 while (current != NULL) {
2216 if (current->debug_info().location() == debug_info) {
2217 // Unlink from list. If prev is NULL we are looking at the first element.
2219 debug_info_list_ = current->next();
2221 prev->set_next(current->next());
2225 // If there are no more debug info objects there are not more break
2227 has_break_points_ = debug_info_list_ != NULL;
2231 // Move to next in list.
2233 current = current->next();
2239 void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) {
2240 HandleScope scope(isolate_);
2241 Handle<SharedFunctionInfo> shared(debug_info->shared());
2243 RemoveDebugInfo(debug_info.location());
2245 shared->set_debug_info(isolate_->heap()->undefined_value());
2249 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
2250 after_break_target_ = NULL;
2252 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job.
2254 HandleScope scope(isolate_);
2255 PrepareForBreakPoints();
2257 // Get the executing function in which the debug break occurred.
2258 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2259 Handle<SharedFunctionInfo> shared(function->shared());
2260 if (!EnsureDebugInfo(shared, function)) {
2261 // Return if we failed to retrieve the debug info.
2264 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2265 Handle<Code> code(debug_info->code());
2266 Handle<Code> original_code(debug_info->original_code());
2268 // Get the code which is actually executing.
2269 Handle<Code> frame_code(frame->LookupCode());
2270 DCHECK(frame_code.is_identical_to(code));
2273 // Find the call address in the running code. This address holds the call to
2274 // either a DebugBreakXXX or to the debug break return entry code if the
2275 // break point is still active after processing the break point.
2276 Address addr = Assembler::break_address_from_return_address(frame->pc());
2278 // Check if the location is at JS exit or debug break slot.
2279 bool at_js_return = false;
2280 bool break_at_js_return_active = false;
2281 bool at_debug_break_slot = false;
2282 RelocIterator it(debug_info->code());
2283 while (!it.done() && !at_js_return && !at_debug_break_slot) {
2284 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2285 at_js_return = (it.rinfo()->pc() ==
2286 addr - Assembler::kPatchReturnSequenceAddressOffset);
2287 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
2289 if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2290 at_debug_break_slot = (it.rinfo()->pc() ==
2291 addr - Assembler::kPatchDebugBreakSlotAddressOffset);
2296 // Handle the jump to continue execution after break point depending on the
2299 // If the break point as return is still active jump to the corresponding
2300 // place in the original code. If not the break point was removed during
2301 // break point processing.
2302 if (break_at_js_return_active) {
2303 addr += original_code->instruction_start() - code->instruction_start();
2306 // Move back to where the call instruction sequence started.
2307 after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset;
2308 } else if (at_debug_break_slot) {
2309 // Address of where the debug break slot starts.
2310 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
2312 // Continue just after the slot.
2313 after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
2315 addr = Assembler::target_address_from_return_address(frame->pc());
2316 if (IsDebugBreak(Assembler::target_address_at(addr, *code))) {
2317 // We now know that there is still a debug break call at the target
2318 // address, so the break point is still there and the original code will
2319 // hold the address to jump to in order to complete the call which is
2320 // replaced by a call to DebugBreakXXX.
2322 // Find the corresponding address in the original code.
2323 addr += original_code->instruction_start() - code->instruction_start();
2325 // Install jump to the call address in the original code. This will be the
2326 // call which was overwritten by the call to DebugBreakXXX.
2327 after_break_target_ = Assembler::target_address_at(addr, *original_code);
2329 // There is no longer a break point present. Don't try to look in the
2330 // original code as the running code will have the right address. This
2331 // takes care of the case where the last break point is removed from the
2332 // function and therefore no "original code" is available.
2333 after_break_target_ = Assembler::target_address_at(addr, *code);
2339 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
2340 HandleScope scope(isolate_);
2342 // If there are no break points this cannot be break at return, as
2343 // the debugger statement and stack guard debug break cannot be at
2345 if (!has_break_points_) {
2349 PrepareForBreakPoints();
2351 // Get the executing function in which the debug break occurred.
2352 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2353 Handle<SharedFunctionInfo> shared(function->shared());
2354 if (!EnsureDebugInfo(shared, function)) {
2355 // Return if we failed to retrieve the debug info.
2358 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2359 Handle<Code> code(debug_info->code());
2361 // Get the code which is actually executing.
2362 Handle<Code> frame_code(frame->LookupCode());
2363 DCHECK(frame_code.is_identical_to(code));
2366 // Find the call address in the running code.
2367 Address addr = Assembler::break_address_from_return_address(frame->pc());
2369 // Check if the location is at JS return.
2370 RelocIterator it(debug_info->code());
2371 while (!it.done()) {
2372 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2373 return (it.rinfo()->pc() ==
2374 addr - Assembler::kPatchReturnSequenceAddressOffset);
2382 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
2383 LiveEdit::FrameDropMode mode,
2384 Object** restarter_frame_function_pointer) {
2385 if (mode != LiveEdit::CURRENTLY_SET_MODE) {
2386 thread_local_.frame_drop_mode_ = mode;
2388 thread_local_.break_frame_id_ = new_break_frame_id;
2389 thread_local_.restarter_frame_function_pointer_ =
2390 restarter_frame_function_pointer;
2394 bool Debug::IsDebugGlobal(GlobalObject* global) {
2395 return is_loaded() && global == debug_context()->global_object();
2399 void Debug::ClearMirrorCache() {
2400 PostponeInterruptsScope postpone(isolate_);
2401 HandleScope scope(isolate_);
2402 AssertDebugContext();
2403 Factory* factory = isolate_->factory();
2404 Handle<GlobalObject> global(isolate_->global_object());
2405 JSObject::SetProperty(global,
2406 factory->NewStringFromAsciiChecked("next_handle_"),
2407 handle(Smi::FromInt(0), isolate_), SLOPPY).Check();
2408 JSObject::SetProperty(global,
2409 factory->NewStringFromAsciiChecked("mirror_cache_"),
2410 factory->NewJSArray(0, FAST_ELEMENTS), SLOPPY).Check();
2414 Handle<FixedArray> Debug::GetLoadedScripts() {
2415 // Create and fill the script cache when the loaded scripts is requested for
2417 if (script_cache_ == NULL) script_cache_ = new ScriptCache(isolate_);
2419 // Perform GC to get unreferenced scripts evicted from the cache before
2420 // returning the content.
2421 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
2422 "Debug::GetLoadedScripts");
2424 // Get the scripts from the cache.
2425 return script_cache_->GetScripts();
2429 void Debug::RecordEvalCaller(Handle<Script> script) {
2430 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
2431 // For eval scripts add information on the function from which eval was
2433 StackTraceFrameIterator it(script->GetIsolate());
2435 script->set_eval_from_shared(it.frame()->function()->shared());
2436 Code* code = it.frame()->LookupCode();
2437 int offset = static_cast<int>(
2438 it.frame()->pc() - code->instruction_start());
2439 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
2444 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name,
2446 Handle<Object> argv[]) {
2447 AssertDebugContext();
2448 // Create the execution state object.
2449 Handle<GlobalObject> global(isolate_->global_object());
2450 Handle<Object> constructor = Object::GetProperty(
2451 isolate_, global, constructor_name).ToHandleChecked();
2452 DCHECK(constructor->IsJSFunction());
2453 if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
2454 // We do not handle interrupts here. In particular, termination interrupts.
2455 PostponeInterruptsScope no_interrupts(isolate_);
2456 return Execution::TryCall(Handle<JSFunction>::cast(constructor),
2457 handle(debug_context()->global_proxy()),
2463 MaybeHandle<Object> Debug::MakeExecutionState() {
2464 // Create the execution state object.
2465 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
2466 return MakeJSObject("MakeExecutionState", arraysize(argv), argv);
2470 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
2471 // Create the new break event object.
2472 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
2474 return MakeJSObject("MakeBreakEvent", arraysize(argv), argv);
2478 MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
2480 Handle<Object> promise) {
2481 // Create the new exception event object.
2482 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
2484 isolate_->factory()->ToBoolean(uncaught),
2486 return MakeJSObject("MakeExceptionEvent", arraysize(argv), argv);
2490 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
2491 v8::DebugEvent type) {
2492 // Create the compile event object.
2493 Handle<Object> script_wrapper = Script::GetWrapper(script);
2494 Handle<Object> argv[] = { script_wrapper,
2495 isolate_->factory()->NewNumberFromInt(type) };
2496 return MakeJSObject("MakeCompileEvent", arraysize(argv), argv);
2500 MaybeHandle<Object> Debug::MakePromiseEvent(Handle<JSObject> event_data) {
2501 // Create the promise event object.
2502 Handle<Object> argv[] = { event_data };
2503 return MakeJSObject("MakePromiseEvent", arraysize(argv), argv);
2507 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
2508 // Create the async task event object.
2509 Handle<Object> argv[] = { task_event };
2510 return MakeJSObject("MakeAsyncTaskEvent", arraysize(argv), argv);
2514 void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
2515 if (in_debug_scope() || ignore_events()) return;
2516 // Temporarily clear any scheduled_exception to allow evaluating
2517 // JavaScript from the debug event handler.
2518 HandleScope scope(isolate_);
2519 Handle<Object> scheduled_exception;
2520 if (isolate_->has_scheduled_exception()) {
2521 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
2522 isolate_->clear_scheduled_exception();
2524 OnException(exception, uncaught, isolate_->GetPromiseOnStackOnThrow());
2525 if (!scheduled_exception.is_null()) {
2526 isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
2531 void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
2532 if (in_debug_scope() || ignore_events()) return;
2533 HandleScope scope(isolate_);
2534 // Check whether the promise has been marked as having triggered a message.
2535 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
2536 if (JSObject::GetDataProperty(promise, key)->IsUndefined()) {
2537 OnException(value, false, promise);
2542 MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler(
2543 Handle<JSObject> promise) {
2544 Handle<JSFunction> fun = Handle<JSFunction>::cast(
2545 JSObject::GetDataProperty(isolate_->js_builtins_object(),
2546 isolate_->factory()->NewStringFromStaticChars(
2547 "PromiseHasUserDefinedRejectHandler")));
2548 return Execution::Call(isolate_, fun, promise, 0, NULL);
2552 void Debug::OnException(Handle<Object> exception, bool uncaught,
2553 Handle<Object> promise) {
2554 if (!uncaught && promise->IsJSObject()) {
2555 Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
2556 // Mark the promise as already having triggered a message.
2557 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
2558 JSObject::SetProperty(jspromise, key, key, STRICT).Assert();
2559 // Check whether the promise reject is considered an uncaught exception.
2560 Handle<Object> has_reject_handler;
2561 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2562 isolate_, has_reject_handler,
2563 PromiseHasUserDefinedRejectHandler(jspromise), /* void */);
2564 uncaught = has_reject_handler->IsFalse();
2566 // Bail out if exception breaks are not active
2568 // Uncaught exceptions are reported by either flags.
2569 if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
2571 // Caught exceptions are reported is activated.
2572 if (!break_on_exception_) return;
2575 DebugScope debug_scope(this);
2576 if (debug_scope.failed()) return;
2578 // Clear all current stepping setup.
2581 // Create the event data object.
2582 Handle<Object> event_data;
2583 // Bail out and don't call debugger if exception.
2584 if (!MakeExceptionEvent(
2585 exception, uncaught, promise).ToHandle(&event_data)) {
2589 // Process debug event.
2590 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
2591 // Return to continue execution from where the exception was thrown.
2595 void Debug::OnCompileError(Handle<Script> script) {
2596 // No more to do if not debugging.
2597 if (in_debug_scope() || ignore_events()) return;
2599 HandleScope scope(isolate_);
2600 DebugScope debug_scope(this);
2601 if (debug_scope.failed()) return;
2603 // Create the compile state object.
2604 Handle<Object> event_data;
2605 // Bail out and don't call debugger if exception.
2606 if (!MakeCompileEvent(script, v8::CompileError).ToHandle(&event_data)) return;
2608 // Process debug event.
2609 ProcessDebugEvent(v8::CompileError, Handle<JSObject>::cast(event_data), true);
2613 void Debug::OnDebugBreak(Handle<Object> break_points_hit,
2614 bool auto_continue) {
2615 // The caller provided for DebugScope.
2616 AssertDebugContext();
2617 // Bail out if there is no listener for this event
2618 if (ignore_events()) return;
2620 HandleScope scope(isolate_);
2621 // Create the event data object.
2622 Handle<Object> event_data;
2623 // Bail out and don't call debugger if exception.
2624 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
2626 // Process debug event.
2627 ProcessDebugEvent(v8::Break,
2628 Handle<JSObject>::cast(event_data),
2633 void Debug::OnBeforeCompile(Handle<Script> script) {
2634 if (in_debug_scope() || ignore_events()) return;
2636 HandleScope scope(isolate_);
2637 DebugScope debug_scope(this);
2638 if (debug_scope.failed()) return;
2640 // Create the event data object.
2641 Handle<Object> event_data;
2642 // Bail out and don't call debugger if exception.
2643 if (!MakeCompileEvent(script, v8::BeforeCompile).ToHandle(&event_data))
2646 // Process debug event.
2647 ProcessDebugEvent(v8::BeforeCompile,
2648 Handle<JSObject>::cast(event_data),
2653 // Handle debugger actions when a new script is compiled.
2654 void Debug::OnAfterCompile(Handle<Script> script) {
2655 // Add the newly compiled script to the script cache.
2656 if (script_cache_ != NULL) script_cache_->Add(script);
2658 // No more to do if not debugging.
2659 if (in_debug_scope() || ignore_events()) return;
2661 HandleScope scope(isolate_);
2662 DebugScope debug_scope(this);
2663 if (debug_scope.failed()) return;
2665 // If debugging there might be script break points registered for this
2666 // script. Make sure that these break points are set.
2668 // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js).
2669 Handle<String> update_script_break_points_string =
2670 isolate_->factory()->InternalizeOneByteString(
2671 STATIC_CHAR_VECTOR("UpdateScriptBreakPoints"));
2672 Handle<GlobalObject> debug_global(debug_context()->global_object());
2673 Handle<Object> update_script_break_points =
2674 Object::GetProperty(
2675 debug_global, update_script_break_points_string).ToHandleChecked();
2676 if (!update_script_break_points->IsJSFunction()) {
2679 DCHECK(update_script_break_points->IsJSFunction());
2681 // Wrap the script object in a proper JS object before passing it
2683 Handle<Object> wrapper = Script::GetWrapper(script);
2685 // Call UpdateScriptBreakPoints expect no exceptions.
2686 Handle<Object> argv[] = { wrapper };
2687 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
2688 isolate_->js_builtins_object(),
2694 // Create the compile state object.
2695 Handle<Object> event_data;
2696 // Bail out and don't call debugger if exception.
2697 if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return;
2699 // Process debug event.
2700 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
2704 void Debug::OnPromiseEvent(Handle<JSObject> data) {
2705 if (in_debug_scope() || ignore_events()) return;
2707 HandleScope scope(isolate_);
2708 DebugScope debug_scope(this);
2709 if (debug_scope.failed()) return;
2711 // Create the script collected state object.
2712 Handle<Object> event_data;
2713 // Bail out and don't call debugger if exception.
2714 if (!MakePromiseEvent(data).ToHandle(&event_data)) return;
2716 // Process debug event.
2717 ProcessDebugEvent(v8::PromiseEvent,
2718 Handle<JSObject>::cast(event_data),
2723 void Debug::OnAsyncTaskEvent(Handle<JSObject> data) {
2724 if (in_debug_scope() || ignore_events()) return;
2726 HandleScope scope(isolate_);
2727 DebugScope debug_scope(this);
2728 if (debug_scope.failed()) return;
2730 // Create the script collected state object.
2731 Handle<Object> event_data;
2732 // Bail out and don't call debugger if exception.
2733 if (!MakeAsyncTaskEvent(data).ToHandle(&event_data)) return;
2735 // Process debug event.
2736 ProcessDebugEvent(v8::AsyncTaskEvent,
2737 Handle<JSObject>::cast(event_data),
2742 void Debug::ProcessDebugEvent(v8::DebugEvent event,
2743 Handle<JSObject> event_data,
2744 bool auto_continue) {
2745 HandleScope scope(isolate_);
2747 // Create the execution state.
2748 Handle<Object> exec_state;
2749 // Bail out and don't call debugger if exception.
2750 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2752 // First notify the message handler if any.
2753 if (message_handler_ != NULL) {
2754 NotifyMessageHandler(event,
2755 Handle<JSObject>::cast(exec_state),
2759 // Notify registered debug event listener. This can be either a C or
2760 // a JavaScript function. Don't call event listener for v8::Break
2761 // here, if it's only a debug command -- they will be processed later.
2762 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
2763 CallEventCallback(event, exec_state, event_data, NULL);
2765 // Process pending debug commands.
2766 if (event == v8::Break) {
2767 while (!event_command_queue_.IsEmpty()) {
2768 CommandMessage command = event_command_queue_.Get();
2769 if (!event_listener_.is_null()) {
2770 CallEventCallback(v8::BreakForCommand,
2773 command.client_data());
2781 void Debug::CallEventCallback(v8::DebugEvent event,
2782 Handle<Object> exec_state,
2783 Handle<Object> event_data,
2784 v8::Debug::ClientData* client_data) {
2785 bool previous = in_debug_event_listener_;
2786 in_debug_event_listener_ = true;
2787 if (event_listener_->IsForeign()) {
2788 // Invoke the C debug event listener.
2789 v8::Debug::EventCallback callback =
2790 FUNCTION_CAST<v8::Debug::EventCallback>(
2791 Handle<Foreign>::cast(event_listener_)->foreign_address());
2792 EventDetailsImpl event_details(event,
2793 Handle<JSObject>::cast(exec_state),
2794 Handle<JSObject>::cast(event_data),
2795 event_listener_data_,
2797 callback(event_details);
2798 DCHECK(!isolate_->has_scheduled_exception());
2800 // Invoke the JavaScript debug event listener.
2801 DCHECK(event_listener_->IsJSFunction());
2802 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
2805 event_listener_data_ };
2806 Handle<JSReceiver> global(isolate_->global_proxy());
2807 Execution::TryCall(Handle<JSFunction>::cast(event_listener_),
2808 global, arraysize(argv), argv);
2810 in_debug_event_listener_ = previous;
2814 Handle<Context> Debug::GetDebugContext() {
2815 DebugScope debug_scope(this);
2816 // The global handle may be destroyed soon after. Return it reboxed.
2817 return handle(*debug_context(), isolate_);
2821 void Debug::NotifyMessageHandler(v8::DebugEvent event,
2822 Handle<JSObject> exec_state,
2823 Handle<JSObject> event_data,
2824 bool auto_continue) {
2825 // Prevent other interrupts from triggering, for example API callbacks,
2826 // while dispatching message handler callbacks.
2827 PostponeInterruptsScope no_interrupts(isolate_);
2829 HandleScope scope(isolate_);
2830 // Process the individual events.
2831 bool sendEventMessage = false;
2834 case v8::BreakForCommand:
2835 sendEventMessage = !auto_continue;
2838 sendEventMessage = true;
2840 case v8::BeforeCompile:
2842 case v8::AfterCompile:
2843 sendEventMessage = true;
2845 case v8::NewFunction:
2851 // The debug command interrupt flag might have been set when the command was
2852 // added. It should be enough to clear the flag only once while we are in the
2854 DCHECK(in_debug_scope());
2855 isolate_->stack_guard()->ClearDebugCommand();
2857 // Notify the debugger that a debug event has occurred unless auto continue is
2858 // active in which case no event is send.
2859 if (sendEventMessage) {
2860 MessageImpl message = MessageImpl::NewEvent(
2863 Handle<JSObject>::cast(exec_state),
2864 Handle<JSObject>::cast(event_data));
2865 InvokeMessageHandler(message);
2868 // If auto continue don't make the event cause a break, but process messages
2869 // in the queue if any. For script collected events don't even process
2870 // messages in the queue as the execution state might not be what is expected
2872 if (auto_continue && !has_commands()) return;
2874 // DebugCommandProcessor goes here.
2875 bool running = auto_continue;
2877 Handle<Object> cmd_processor_ctor = Object::GetProperty(
2878 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked();
2879 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
2880 Handle<Object> cmd_processor = Execution::Call(
2881 isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked();
2882 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
2883 Object::GetProperty(
2884 isolate_, cmd_processor, "processDebugRequest").ToHandleChecked());
2885 Handle<Object> is_running = Object::GetProperty(
2886 isolate_, cmd_processor, "isRunning").ToHandleChecked();
2888 // Process requests from the debugger.
2890 // Wait for new command in the queue.
2891 command_received_.Wait();
2893 // Get the command from the queue.
2894 CommandMessage command = command_queue_.Get();
2895 isolate_->logger()->DebugTag(
2896 "Got request from command queue, in interactive loop.");
2898 // Delete command text and user data.
2903 Vector<const uc16> command_text(
2904 const_cast<const uc16*>(command.text().start()),
2905 command.text().length());
2906 Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
2907 command_text).ToHandleChecked();
2908 Handle<Object> request_args[] = { request_text };
2909 Handle<Object> answer_value;
2910 Handle<String> answer;
2911 MaybeHandle<Object> maybe_exception;
2912 MaybeHandle<Object> maybe_result =
2913 Execution::TryCall(process_debug_request, cmd_processor, 1,
2914 request_args, &maybe_exception);
2916 if (maybe_result.ToHandle(&answer_value)) {
2917 if (answer_value->IsUndefined()) {
2918 answer = isolate_->factory()->empty_string();
2920 answer = Handle<String>::cast(answer_value);
2923 // Log the JSON request/response.
2924 if (FLAG_trace_debug_json) {
2925 PrintF("%s\n", request_text->ToCString().get());
2926 PrintF("%s\n", answer->ToCString().get());
2929 Handle<Object> is_running_args[] = { answer };
2930 maybe_result = Execution::Call(
2931 isolate_, is_running, cmd_processor, 1, is_running_args);
2932 Handle<Object> result;
2933 if (!maybe_result.ToHandle(&result)) break;
2934 running = result->IsTrue();
2936 Handle<Object> exception;
2937 if (!maybe_exception.ToHandle(&exception)) break;
2938 Handle<Object> result;
2939 if (!Execution::ToString(isolate_, exception).ToHandle(&result)) break;
2940 answer = Handle<String>::cast(result);
2943 // Return the result.
2944 MessageImpl message = MessageImpl::NewResponse(
2945 event, running, exec_state, event_data, answer, command.client_data());
2946 InvokeMessageHandler(message);
2949 // Return from debug event processing if either the VM is put into the
2950 // running state (through a continue command) or auto continue is active
2951 // and there are no more commands queued.
2952 } while (!running || has_commands());
2953 command_queue_.Clear();
2957 void Debug::SetEventListener(Handle<Object> callback,
2958 Handle<Object> data) {
2959 GlobalHandles* global_handles = isolate_->global_handles();
2961 // Remove existing entry.
2962 GlobalHandles::Destroy(event_listener_.location());
2963 event_listener_ = Handle<Object>();
2964 GlobalHandles::Destroy(event_listener_data_.location());
2965 event_listener_data_ = Handle<Object>();
2968 if (!callback->IsUndefined() && !callback->IsNull()) {
2969 event_listener_ = global_handles->Create(*callback);
2970 if (data.is_null()) data = isolate_->factory()->undefined_value();
2971 event_listener_data_ = global_handles->Create(*data);
2978 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
2979 message_handler_ = handler;
2981 if (handler == NULL && in_debug_scope()) {
2982 // Send an empty command to the debugger if in a break to make JavaScript
2983 // run again if the debugger is closed.
2984 EnqueueCommandMessage(Vector<const uint16_t>::empty());
2990 void Debug::UpdateState() {
2991 is_active_ = message_handler_ != NULL || !event_listener_.is_null();
2992 if (is_active_ || in_debug_scope()) {
2993 // Note that the debug context could have already been loaded to
2994 // bootstrap test cases.
2995 isolate_->compilation_cache()->Disable();
2996 is_active_ = Load();
2997 } else if (is_loaded()) {
2998 isolate_->compilation_cache()->Enable();
3004 // Calls the registered debug message handler. This callback is part of the
3006 void Debug::InvokeMessageHandler(MessageImpl message) {
3007 if (message_handler_ != NULL) message_handler_(message);
3011 // Puts a command coming from the public API on the queue. Creates
3012 // a copy of the command string managed by the debugger. Up to this
3013 // point, the command data was managed by the API client. Called
3014 // by the API client thread.
3015 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
3016 v8::Debug::ClientData* client_data) {
3017 // Need to cast away const.
3018 CommandMessage message = CommandMessage::New(
3019 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
3022 isolate_->logger()->DebugTag("Put command on command_queue.");
3023 command_queue_.Put(message);
3024 command_received_.Signal();
3026 // Set the debug command break flag to have the command processed.
3027 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
3031 void Debug::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
3032 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
3033 event_command_queue_.Put(message);
3035 // Set the debug command break flag to have the command processed.
3036 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
3040 MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) {
3041 DebugScope debug_scope(this);
3042 if (debug_scope.failed()) return isolate_->factory()->undefined_value();
3044 // Create the execution state.
3045 Handle<Object> exec_state;
3046 if (!MakeExecutionState().ToHandle(&exec_state)) {
3047 return isolate_->factory()->undefined_value();
3050 Handle<Object> argv[] = { exec_state, data };
3051 return Execution::Call(
3054 Handle<Object>(debug_context()->global_proxy(), isolate_),
3060 void Debug::HandleDebugBreak() {
3061 // Ignore debug break during bootstrapping.
3062 if (isolate_->bootstrapper()->IsActive()) return;
3063 // Just continue if breaks are disabled.
3064 if (break_disabled()) return;
3065 // Ignore debug break if debugger is not active.
3066 if (!is_active()) return;
3068 StackLimitCheck check(isolate_);
3069 if (check.HasOverflowed()) return;
3071 { JavaScriptFrameIterator it(isolate_);
3073 Object* fun = it.frame()->function();
3074 if (fun && fun->IsJSFunction()) {
3075 // Don't stop in builtin functions.
3076 if (JSFunction::cast(fun)->IsBuiltin()) return;
3077 GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
3078 // Don't stop in debugger functions.
3079 if (IsDebugGlobal(global)) return;
3083 // Collect the break state before clearing the flags.
3084 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
3085 !isolate_->stack_guard()->CheckDebugBreak();
3087 isolate_->stack_guard()->ClearDebugBreak();
3089 ProcessDebugMessages(debug_command_only);
3093 void Debug::ProcessDebugMessages(bool debug_command_only) {
3094 isolate_->stack_guard()->ClearDebugCommand();
3096 StackLimitCheck check(isolate_);
3097 if (check.HasOverflowed()) return;
3099 HandleScope scope(isolate_);
3100 DebugScope debug_scope(this);
3101 if (debug_scope.failed()) return;
3103 // Notify the debug event listeners. Indicate auto continue if the break was
3104 // a debug command break.
3105 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
3109 DebugScope::DebugScope(Debug* debug)
3111 prev_(debug->debugger_entry()),
3112 save_(debug_->isolate_),
3113 no_termination_exceptons_(debug_->isolate_,
3114 StackGuard::TERMINATE_EXECUTION) {
3115 // Link recursive debugger entry.
3116 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
3117 reinterpret_cast<base::AtomicWord>(this));
3119 // Store the previous break id and frame id.
3120 break_id_ = debug_->break_id();
3121 break_frame_id_ = debug_->break_frame_id();
3123 // Create the new break info. If there is no JavaScript frames there is no
3125 JavaScriptFrameIterator it(isolate());
3126 bool has_js_frames = !it.done();
3127 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
3128 : StackFrame::NO_ID;
3129 debug_->SetNextBreakId();
3131 debug_->UpdateState();
3132 // Make sure that debugger is loaded and enter the debugger context.
3133 // The previous context is kept in save_.
3134 failed_ = !debug_->is_loaded();
3135 if (!failed_) isolate()->set_context(*debug->debug_context());
3140 DebugScope::~DebugScope() {
3141 if (!failed_ && prev_ == NULL) {
3142 // Clear mirror cache when leaving the debugger. Skip this if there is a
3143 // pending exception as clearing the mirror cache calls back into
3144 // JavaScript. This can happen if the v8::Debug::Call is used in which
3145 // case the exception should end up in the calling code.
3146 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
3148 // If there are commands in the queue when leaving the debugger request
3149 // that these commands are processed.
3150 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
3153 // Leaving this debugger entry.
3154 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
3155 reinterpret_cast<base::AtomicWord>(prev_));
3157 // Restore to the previous break state.
3158 debug_->thread_local_.break_frame_id_ = break_frame_id_;
3159 debug_->thread_local_.break_id_ = break_id_;
3161 debug_->UpdateState();
3165 MessageImpl MessageImpl::NewEvent(DebugEvent event,
3167 Handle<JSObject> exec_state,
3168 Handle<JSObject> event_data) {
3169 MessageImpl message(true, event, running,
3170 exec_state, event_data, Handle<String>(), NULL);
3175 MessageImpl MessageImpl::NewResponse(DebugEvent event,
3177 Handle<JSObject> exec_state,
3178 Handle<JSObject> event_data,
3179 Handle<String> response_json,
3180 v8::Debug::ClientData* client_data) {
3181 MessageImpl message(false, event, running,
3182 exec_state, event_data, response_json, client_data);
3187 MessageImpl::MessageImpl(bool is_event,
3190 Handle<JSObject> exec_state,
3191 Handle<JSObject> event_data,
3192 Handle<String> response_json,
3193 v8::Debug::ClientData* client_data)
3194 : is_event_(is_event),
3197 exec_state_(exec_state),
3198 event_data_(event_data),
3199 response_json_(response_json),
3200 client_data_(client_data) {}
3203 bool MessageImpl::IsEvent() const {
3208 bool MessageImpl::IsResponse() const {
3213 DebugEvent MessageImpl::GetEvent() const {
3218 bool MessageImpl::WillStartRunning() const {
3223 v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
3224 return v8::Utils::ToLocal(exec_state_);
3228 v8::Isolate* MessageImpl::GetIsolate() const {
3229 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
3233 v8::Handle<v8::Object> MessageImpl::GetEventData() const {
3234 return v8::Utils::ToLocal(event_data_);
3238 v8::Handle<v8::String> MessageImpl::GetJSON() const {
3239 Isolate* isolate = event_data_->GetIsolate();
3240 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
3243 // Call toJSONProtocol on the debug event object.
3244 Handle<Object> fun = Object::GetProperty(
3245 isolate, event_data_, "toJSONProtocol").ToHandleChecked();
3246 if (!fun->IsJSFunction()) {
3247 return v8::Handle<v8::String>();
3250 MaybeHandle<Object> maybe_json =
3251 Execution::TryCall(Handle<JSFunction>::cast(fun), event_data_, 0, NULL);
3252 Handle<Object> json;
3253 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
3254 return v8::Handle<v8::String>();
3256 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
3258 return v8::Utils::ToLocal(response_json_);
3263 v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
3264 Isolate* isolate = event_data_->GetIsolate();
3265 v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
3266 // Isolate::context() may be NULL when "script collected" event occurs.
3267 DCHECK(!context.IsEmpty());
3272 v8::Debug::ClientData* MessageImpl::GetClientData() const {
3273 return client_data_;
3277 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
3278 Handle<JSObject> exec_state,
3279 Handle<JSObject> event_data,
3280 Handle<Object> callback_data,
3281 v8::Debug::ClientData* client_data)
3283 exec_state_(exec_state),
3284 event_data_(event_data),
3285 callback_data_(callback_data),
3286 client_data_(client_data) {}
3289 DebugEvent EventDetailsImpl::GetEvent() const {
3294 v8::Handle<v8::Object> EventDetailsImpl::GetExecutionState() const {
3295 return v8::Utils::ToLocal(exec_state_);
3299 v8::Handle<v8::Object> EventDetailsImpl::GetEventData() const {
3300 return v8::Utils::ToLocal(event_data_);
3304 v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const {
3305 return GetDebugEventContext(exec_state_->GetIsolate());
3309 v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const {
3310 return v8::Utils::ToLocal(callback_data_);
3314 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
3315 return client_data_;
3319 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
3320 client_data_(NULL) {
3324 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
3325 v8::Debug::ClientData* data)
3327 client_data_(data) {
3331 void CommandMessage::Dispose() {
3333 delete client_data_;
3334 client_data_ = NULL;
3338 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
3339 v8::Debug::ClientData* data) {
3340 return CommandMessage(command.Clone(), data);
3344 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
3346 messages_ = NewArray<CommandMessage>(size);
3350 CommandMessageQueue::~CommandMessageQueue() {
3351 while (!IsEmpty()) Get().Dispose();
3352 DeleteArray(messages_);
3356 CommandMessage CommandMessageQueue::Get() {
3358 int result = start_;
3359 start_ = (start_ + 1) % size_;
3360 return messages_[result];
3364 void CommandMessageQueue::Put(const CommandMessage& message) {
3365 if ((end_ + 1) % size_ == start_) {
3368 messages_[end_] = message;
3369 end_ = (end_ + 1) % size_;
3373 void CommandMessageQueue::Expand() {
3374 CommandMessageQueue new_queue(size_ * 2);
3375 while (!IsEmpty()) {
3376 new_queue.Put(Get());
3378 CommandMessage* array_to_free = messages_;
3380 new_queue.messages_ = array_to_free;
3381 // Make the new_queue empty so that it doesn't call Dispose on any messages.
3382 new_queue.start_ = new_queue.end_;
3383 // Automatic destructor called on new_queue, freeing array_to_free.
3387 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
3388 : logger_(logger), queue_(size) {}
3391 bool LockingCommandMessageQueue::IsEmpty() const {
3392 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3393 return queue_.IsEmpty();
3397 CommandMessage LockingCommandMessageQueue::Get() {
3398 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3399 CommandMessage result = queue_.Get();
3400 logger_->DebugEvent("Get", result.text());
3405 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
3406 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3407 queue_.Put(message);
3408 logger_->DebugEvent("Put", message.text());
3412 void LockingCommandMessageQueue::Clear() {
3413 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3417 } } // namespace v8::internal