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.
9 #include "bootstrapper.h"
10 #include "code-stubs.h"
12 #include "compilation-cache.h"
15 #include "deoptimizer.h"
16 #include "execution.h"
17 #include "full-codegen.h"
18 #include "global-handles.h"
21 #include "isolate-inl.h"
25 #include "stub-cache.h"
28 #include "../include/v8-debug.h"
33 Debug::Debug(Isolate* isolate)
34 : has_break_points_(false),
36 debug_info_list_(NULL),
37 disable_break_(false),
38 break_on_exception_(false),
39 break_on_uncaught_exception_(false),
40 promise_catch_handlers_(0),
43 memset(registers_, 0, sizeof(JSCallerSavedBuffer));
52 static void PrintLn(v8::Local<v8::Value> value) {
53 v8::Local<v8::String> s = value->ToString();
54 ScopedVector<char> data(s->Utf8Length() + 1);
55 if (data.start() == NULL) {
56 V8::FatalProcessOutOfMemory("PrintLn");
59 s->WriteUtf8(data.start());
60 PrintF("%s\n", data.start());
64 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
65 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
66 // Isolate::context() may have been NULL when "script collected" event
68 if (context.is_null()) return v8::Local<v8::Context>();
69 Handle<Context> native_context(context->native_context());
70 return v8::Utils::ToLocal(native_context);
74 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
75 BreakLocatorType type) {
76 debug_info_ = debug_info;
78 reloc_iterator_ = NULL;
79 reloc_iterator_original_ = NULL;
80 Reset(); // Initialize the rest of the member variables.
84 BreakLocationIterator::~BreakLocationIterator() {
85 ASSERT(reloc_iterator_ != NULL);
86 ASSERT(reloc_iterator_original_ != NULL);
87 delete reloc_iterator_;
88 delete reloc_iterator_original_;
92 void BreakLocationIterator::Next() {
93 DisallowHeapAllocation no_gc;
96 // Iterate through reloc info for code and original code stopping at each
97 // breakable code target.
98 bool first = break_point_ == -1;
99 while (!RinfoDone()) {
100 if (!first) RinfoNext();
102 if (RinfoDone()) return;
104 // Whenever a statement position or (plain) position is passed update the
105 // current value of these.
106 if (RelocInfo::IsPosition(rmode())) {
107 if (RelocInfo::IsStatementPosition(rmode())) {
108 statement_position_ = static_cast<int>(
109 rinfo()->data() - debug_info_->shared()->start_position());
111 // Always update the position as we don't want that to be before the
112 // statement position.
113 position_ = static_cast<int>(
114 rinfo()->data() - debug_info_->shared()->start_position());
115 ASSERT(position_ >= 0);
116 ASSERT(statement_position_ >= 0);
119 if (IsDebugBreakSlot()) {
120 // There is always a possible break point at a debug break slot.
123 } else if (RelocInfo::IsCodeTarget(rmode())) {
124 // Check for breakable code target. Look in the original code as setting
125 // break points can cause the code targets in the running (debugged) code
126 // to be of a different kind than in the original code.
127 Address target = original_rinfo()->target_address();
128 Code* code = Code::GetCodeFromTargetAddress(target);
129 if ((code->is_inline_cache_stub() &&
130 !code->is_binary_op_stub() &&
131 !code->is_compare_ic_stub() &&
132 !code->is_to_boolean_ic_stub()) ||
133 RelocInfo::IsConstructCall(rmode())) {
137 if (code->kind() == Code::STUB) {
138 if (IsDebuggerStatement()) {
142 if (type_ == ALL_BREAK_LOCATIONS) {
143 if (Debug::IsBreakStub(code)) {
148 ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
149 if (Debug::IsSourceBreakStub(code)) {
157 // Check for break at return.
158 if (RelocInfo::IsJSReturn(rmode())) {
159 // Set the positions to the end of the function.
160 if (debug_info_->shared()->HasSourceCode()) {
161 position_ = debug_info_->shared()->end_position() -
162 debug_info_->shared()->start_position() - 1;
166 statement_position_ = position_;
174 void BreakLocationIterator::Next(int count) {
182 // Find the break point at the supplied address, or the closest one before
184 void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
185 // Run through all break points to locate the one closest to the address.
186 int closest_break_point = 0;
187 int distance = kMaxInt;
189 // Check if this break point is closer that what was previously found.
190 if (this->pc() <= pc && pc - this->pc() < distance) {
191 closest_break_point = break_point();
192 distance = static_cast<int>(pc - this->pc());
193 // Check whether we can't get any closer.
194 if (distance == 0) break;
199 // Move to the break point found.
201 Next(closest_break_point);
205 // Find the break point closest to the supplied source position.
206 void BreakLocationIterator::FindBreakLocationFromPosition(int position,
207 BreakPositionAlignment alignment) {
208 // Run through all break points to locate the one closest to the source
210 int closest_break_point = 0;
211 int distance = kMaxInt;
216 case STATEMENT_ALIGNED:
217 next_position = this->statement_position();
219 case BREAK_POSITION_ALIGNED:
220 next_position = this->position();
224 next_position = this->statement_position();
226 // Check if this break point is closer that what was previously found.
227 if (position <= next_position && next_position - position < distance) {
228 closest_break_point = break_point();
229 distance = next_position - position;
230 // Check whether we can't get any closer.
231 if (distance == 0) break;
236 // Move to the break point found.
238 Next(closest_break_point);
242 void BreakLocationIterator::Reset() {
243 // Create relocation iterators for the two code objects.
244 if (reloc_iterator_ != NULL) delete reloc_iterator_;
245 if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
246 reloc_iterator_ = new RelocIterator(
248 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
249 reloc_iterator_original_ = new RelocIterator(
250 debug_info_->original_code(),
251 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
253 // Position at the first break point.
256 statement_position_ = 1;
261 bool BreakLocationIterator::Done() const {
266 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
267 // If there is not already a real break point here patch code with debug
269 if (!HasBreakPoint()) {
272 ASSERT(IsDebugBreak() || IsDebuggerStatement());
273 // Set the break point information.
274 DebugInfo::SetBreakPoint(debug_info_, code_position(),
275 position(), statement_position(),
280 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
281 // Clear the break point information.
282 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
283 // If there are no more break points here remove the debug break.
284 if (!HasBreakPoint()) {
286 ASSERT(!IsDebugBreak());
291 void BreakLocationIterator::SetOneShot() {
292 // Debugger statement always calls debugger. No need to modify it.
293 if (IsDebuggerStatement()) {
297 // If there is a real break point here no more to do.
298 if (HasBreakPoint()) {
299 ASSERT(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()) {
314 // If there is a real break point here no more to do.
315 if (HasBreakPoint()) {
316 ASSERT(IsDebugBreak());
320 // Patch code removing debug break.
322 ASSERT(!IsDebugBreak());
326 void BreakLocationIterator::SetDebugBreak() {
327 // Debugger statement always calls debugger. No need to modify it.
328 if (IsDebuggerStatement()) {
332 // If there is already a break point here just return. This might happen if
333 // the same code is flooded with break points twice. Flooding the same
334 // function twice might happen when stepping in a function with an exception
335 // handler as the handler and the function is the same.
336 if (IsDebugBreak()) {
340 if (RelocInfo::IsJSReturn(rmode())) {
341 // Patch the frame exit code with a break point.
342 SetDebugBreakAtReturn();
343 } else if (IsDebugBreakSlot()) {
344 // Patch the code in the break slot.
345 SetDebugBreakAtSlot();
347 // Patch the IC call.
350 ASSERT(IsDebugBreak());
354 void BreakLocationIterator::ClearDebugBreak() {
355 // Debugger statement always calls debugger. No need to modify it.
356 if (IsDebuggerStatement()) {
360 if (RelocInfo::IsJSReturn(rmode())) {
361 // Restore the frame exit code.
362 ClearDebugBreakAtReturn();
363 } else if (IsDebugBreakSlot()) {
364 // Restore the code in the break slot.
365 ClearDebugBreakAtSlot();
367 // Patch the IC call.
368 ClearDebugBreakAtIC();
370 ASSERT(!IsDebugBreak());
374 bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
375 if (RelocInfo::IsConstructCall(original_rmode())) {
377 } else if (RelocInfo::IsCodeTarget(rmode())) {
378 HandleScope scope(debug_info_->GetIsolate());
379 Address target = original_rinfo()->target_address();
380 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
381 if (target_code->kind() == Code::STUB) {
382 return target_code->major_key() == CodeStub::CallFunction;
384 return target_code->is_call_stub();
390 void BreakLocationIterator::PrepareStepIn(Isolate* isolate) {
392 HandleScope scope(isolate);
393 // Step in can only be prepared if currently positioned on an IC call,
394 // construct call or CallFunction stub call.
395 Address target = rinfo()->target_address();
396 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
397 // All the following stuff is needed only for assertion checks so the code
398 // is wrapped in ifdef.
399 Handle<Code> maybe_call_function_stub = target_code;
400 if (IsDebugBreak()) {
401 Address original_target = original_rinfo()->target_address();
402 maybe_call_function_stub =
403 Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
405 bool is_call_function_stub =
406 (maybe_call_function_stub->kind() == Code::STUB &&
407 maybe_call_function_stub->major_key() == CodeStub::CallFunction);
409 // Step in through construct call requires no changes to the running code.
410 // Step in through getters/setters should already be prepared as well
411 // because caller of this function (Debug::PrepareStep) is expected to
412 // flood the top frame's function with one shot breakpoints.
413 // Step in through CallFunction stub should also be prepared by caller of
414 // this function (Debug::PrepareStep) which should flood target function
416 ASSERT(RelocInfo::IsConstructCall(rmode()) ||
417 target_code->is_inline_cache_stub() ||
418 is_call_function_stub);
423 // Check whether the break point is at a position which will exit the function.
424 bool BreakLocationIterator::IsExit() const {
425 return (RelocInfo::IsJSReturn(rmode()));
429 bool BreakLocationIterator::HasBreakPoint() {
430 return debug_info_->HasBreakPoint(code_position());
434 // Check whether there is a debug break at the current position.
435 bool BreakLocationIterator::IsDebugBreak() {
436 if (RelocInfo::IsJSReturn(rmode())) {
437 return IsDebugBreakAtReturn();
438 } else if (IsDebugBreakSlot()) {
439 return IsDebugBreakAtSlot();
441 return Debug::IsDebugBreak(rinfo()->target_address());
446 void BreakLocationIterator::SetDebugBreakAtIC() {
447 // Patch the original code with the current address as the current address
448 // might have changed by the inline caching since the code was copied.
449 original_rinfo()->set_target_address(rinfo()->target_address());
451 RelocInfo::Mode mode = rmode();
452 if (RelocInfo::IsCodeTarget(mode)) {
453 Address target = rinfo()->target_address();
454 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
456 // Patch the code to invoke the builtin debug break function matching the
457 // calling convention used by the call site.
458 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode));
459 rinfo()->set_target_address(dbgbrk_code->entry());
464 void BreakLocationIterator::ClearDebugBreakAtIC() {
465 // Patch the code to the original invoke.
466 rinfo()->set_target_address(original_rinfo()->target_address());
470 bool BreakLocationIterator::IsDebuggerStatement() {
471 return RelocInfo::DEBUG_BREAK == rmode();
475 bool BreakLocationIterator::IsDebugBreakSlot() {
476 return RelocInfo::DEBUG_BREAK_SLOT == rmode();
480 Object* BreakLocationIterator::BreakPointObjects() {
481 return debug_info_->GetBreakPointObjects(code_position());
485 // Clear out all the debug break code. This is ONLY supposed to be used when
486 // shutting down the debugger as it will leave the break point information in
487 // DebugInfo even though the code is patched back to the non break point state.
488 void BreakLocationIterator::ClearAllDebugBreak() {
496 bool BreakLocationIterator::RinfoDone() const {
497 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
498 return reloc_iterator_->done();
502 void BreakLocationIterator::RinfoNext() {
503 reloc_iterator_->next();
504 reloc_iterator_original_->next();
506 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
507 if (!reloc_iterator_->done()) {
508 ASSERT(rmode() == original_rmode());
514 // Threading support.
515 void Debug::ThreadInit() {
516 thread_local_.break_count_ = 0;
517 thread_local_.break_id_ = 0;
518 thread_local_.break_frame_id_ = StackFrame::NO_ID;
519 thread_local_.last_step_action_ = StepNone;
520 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
521 thread_local_.step_count_ = 0;
522 thread_local_.last_fp_ = 0;
523 thread_local_.queued_step_count_ = 0;
524 thread_local_.step_into_fp_ = 0;
525 thread_local_.step_out_fp_ = 0;
526 thread_local_.after_break_target_ = 0;
527 // TODO(isolates): frames_are_dropped_?
528 thread_local_.debugger_entry_ = NULL;
529 thread_local_.pending_interrupts_ = 0;
530 thread_local_.restarter_frame_function_pointer_ = NULL;
534 char* Debug::ArchiveDebug(char* storage) {
536 OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
537 to += sizeof(ThreadLocal);
538 OS::MemCopy(to, reinterpret_cast<char*>(®isters_), sizeof(registers_));
540 ASSERT(to <= storage + ArchiveSpacePerThread());
541 return storage + ArchiveSpacePerThread();
545 char* Debug::RestoreDebug(char* storage) {
546 char* from = storage;
548 reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
549 from += sizeof(ThreadLocal);
550 OS::MemCopy(reinterpret_cast<char*>(®isters_), from, sizeof(registers_));
551 ASSERT(from <= storage + ArchiveSpacePerThread());
552 return storage + ArchiveSpacePerThread();
556 int Debug::ArchiveSpacePerThread() {
557 return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer);
561 // Frame structure (conforms InternalFrame structure):
564 // -- function (slot is called "context")
566 Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
568 ASSERT(bottom_js_frame->is_java_script());
570 Address fp = bottom_js_frame->fp();
572 // Move function pointer into "context" slot.
573 Memory::Object_at(fp + StandardFrameConstants::kContextOffset) =
574 Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset);
576 Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code;
577 Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) =
578 Smi::FromInt(StackFrame::INTERNAL);
580 return reinterpret_cast<Object**>(&Memory::Object_at(
581 fp + StandardFrameConstants::kContextOffset));
584 const int Debug::kFrameDropperFrameSize = 4;
587 void ScriptCache::Add(Handle<Script> script) {
588 GlobalHandles* global_handles = isolate_->global_handles();
589 // Create an entry in the hash map for the script.
590 int id = script->id()->value();
591 HashMap::Entry* entry =
592 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
593 if (entry->value != NULL) {
594 ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
597 // Globalize the script object, make it weak and use the location of the
598 // global handle as the value in the hash map.
599 Handle<Script> script_ =
600 Handle<Script>::cast(global_handles->Create(*script));
601 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
603 ScriptCache::HandleWeakScript);
604 entry->value = script_.location();
608 Handle<FixedArray> ScriptCache::GetScripts() {
609 Factory* factory = isolate_->factory();
610 Handle<FixedArray> instances = factory->NewFixedArray(occupancy());
612 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
613 ASSERT(entry->value != NULL);
614 if (entry->value != NULL) {
615 instances->set(count, *reinterpret_cast<Script**>(entry->value));
623 void ScriptCache::ProcessCollectedScripts() {
624 Debugger* debugger = isolate_->debugger();
625 for (int i = 0; i < collected_scripts_.length(); i++) {
626 debugger->OnScriptCollected(collected_scripts_[i]);
628 collected_scripts_.Clear();
632 void ScriptCache::Clear() {
633 // Iterate the script cache to get rid of all the weak handles.
634 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
635 ASSERT(entry != NULL);
636 Object** location = reinterpret_cast<Object**>(entry->value);
637 ASSERT((*location)->IsScript());
638 GlobalHandles::ClearWeakness(location);
639 GlobalHandles::Destroy(location);
641 // Clear the content of the hash map.
646 void ScriptCache::HandleWeakScript(
647 const v8::WeakCallbackData<v8::Value, void>& data) {
648 // Retrieve the script identifier.
649 Handle<Object> object = Utils::OpenHandle(*data.GetValue());
650 int id = Handle<Script>::cast(object)->id()->value();
651 void* key = reinterpret_cast<void*>(id);
652 uint32_t hash = Hash(id);
654 // Remove the corresponding entry from the cache.
655 ScriptCache* script_cache =
656 reinterpret_cast<ScriptCache*>(data.GetParameter());
657 HashMap::Entry* entry = script_cache->Lookup(key, hash, false);
658 Object** location = reinterpret_cast<Object**>(entry->value);
659 script_cache->Remove(key, hash);
660 script_cache->collected_scripts_.Add(id);
662 // Clear the weak handle.
663 GlobalHandles::Destroy(location);
667 void Debug::HandleWeakDebugInfo(
668 const v8::WeakCallbackData<v8::Value, void>& data) {
669 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug();
670 DebugInfoListNode* node =
671 reinterpret_cast<DebugInfoListNode*>(data.GetParameter());
672 // We need to clear all breakpoints associated with the function to restore
673 // original code and avoid patching the code twice later because
674 // the function will live in the heap until next gc, and can be found by
675 // Debug::FindSharedFunctionInfoInScript.
676 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
677 it.ClearAllDebugBreak();
678 debug->RemoveDebugInfo(node->debug_info());
680 for (DebugInfoListNode* n = debug->debug_info_list_;
689 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
690 // Globalize the request debug info object and make it weak.
691 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
692 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info));
693 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
695 Debug::HandleWeakDebugInfo);
699 DebugInfoListNode::~DebugInfoListNode() {
700 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
704 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
705 Factory* factory = isolate->factory();
706 HandleScope scope(isolate);
708 // Bail out if the index is invalid.
713 // Find source and name for the requested script.
714 Handle<String> source_code =
715 isolate->bootstrapper()->NativesSourceLookup(index);
716 Vector<const char> name = Natives::GetScriptName(index);
717 Handle<String> script_name =
718 factory->NewStringFromAscii(name).ToHandleChecked();
719 Handle<Context> context = isolate->native_context();
721 // Compile the script.
722 Handle<SharedFunctionInfo> function_info;
723 function_info = Compiler::CompileScript(source_code,
727 NULL, NULL, NO_CACHED_DATA,
730 // Silently ignore stack overflows during compilation.
731 if (function_info.is_null()) {
732 ASSERT(isolate->has_pending_exception());
733 isolate->clear_pending_exception();
737 // Execute the shared function in the debugger context.
738 Handle<JSFunction> function =
739 factory->NewFunctionFromSharedFunctionInfo(function_info, context);
741 Handle<Object> exception;
742 MaybeHandle<Object> result =
743 Execution::TryCall(function,
744 Handle<Object>(context->global_object(), isolate),
749 // Check for caught exceptions.
750 if (result.is_null()) {
751 ASSERT(!isolate->has_pending_exception());
752 MessageLocation computed_location;
753 isolate->ComputeLocation(&computed_location);
754 Handle<Object> message = MessageHandler::MakeMessageObject(
755 isolate, "error_loading_debugger", &computed_location,
756 Vector<Handle<Object> >::empty(), Handle<JSArray>());
757 ASSERT(!isolate->has_pending_exception());
758 if (!exception.is_null()) {
759 isolate->set_pending_exception(*exception);
760 MessageHandler::ReportMessage(isolate, NULL, message);
761 isolate->clear_pending_exception();
766 // Mark this script as native and return successfully.
767 Handle<Script> script(Script::cast(function->shared()->script()));
768 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
774 // Return if debugger is already loaded.
775 if (IsLoaded()) return true;
777 Debugger* debugger = isolate_->debugger();
779 // Bail out if we're already in the process of compiling the native
780 // JavaScript source code for the debugger.
781 if (debugger->compiling_natives() ||
782 debugger->is_loading_debugger())
784 debugger->set_loading_debugger(true);
786 // Disable breakpoints and interrupts while compiling and running the
787 // debugger scripts including the context creation code.
788 DisableBreak disable(isolate_, true);
789 PostponeInterruptsScope postpone(isolate_);
791 // Create the debugger context.
792 HandleScope scope(isolate_);
793 ExtensionConfiguration no_extensions;
794 Handle<Context> context =
795 isolate_->bootstrapper()->CreateEnvironment(
796 Handle<Object>::null(),
797 v8::Handle<ObjectTemplate>(),
800 // Fail if no context could be created.
801 if (context.is_null()) return false;
803 // Use the debugger context.
804 SaveContext save(isolate_);
805 isolate_->set_context(*context);
807 // Expose the builtins object in the debugger context.
808 Handle<String> key = isolate_->factory()->InternalizeOneByteString(
809 STATIC_ASCII_VECTOR("builtins"));
810 Handle<GlobalObject> global = Handle<GlobalObject>(context->global_object());
811 RETURN_ON_EXCEPTION_VALUE(
813 JSReceiver::SetProperty(global,
815 Handle<Object>(global->builtins(), isolate_),
820 // Compile the JavaScript for the debugger in the debugger context.
821 debugger->set_compiling_natives(true);
822 bool caught_exception =
823 !CompileDebuggerScript(isolate_, Natives::GetIndex("mirror")) ||
824 !CompileDebuggerScript(isolate_, Natives::GetIndex("debug"));
826 if (FLAG_enable_liveedit) {
827 caught_exception = caught_exception ||
828 !CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit"));
831 debugger->set_compiling_natives(false);
833 // Make sure we mark the debugger as not loading before we might
835 debugger->set_loading_debugger(false);
837 // Check for caught exceptions.
838 if (caught_exception) return false;
840 // Debugger loaded, create debugger context global handle.
841 debug_context_ = Handle<Context>::cast(
842 isolate_->global_handles()->Create(*context));
848 void Debug::Unload() {
849 // Return debugger is not loaded.
854 // Clear the script cache.
855 DestroyScriptCache();
857 // Clear debugger context global handle.
858 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
859 debug_context_ = Handle<Context>();
863 // Set the flag indicating that preemption happened during debugging.
864 void Debug::PreemptionWhileInDebugger() {
865 ASSERT(InDebugger());
866 Debug::set_interrupts_pending(PREEMPT);
870 Object* Debug::Break(Arguments args) {
871 Heap* heap = isolate_->heap();
872 HandleScope scope(isolate_);
873 ASSERT(args.length() == 0);
875 thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED;
877 // Get the top-most JavaScript frame.
878 JavaScriptFrameIterator it(isolate_);
879 JavaScriptFrame* frame = it.frame();
881 // Just continue if breaks are disabled or debugger cannot be loaded.
882 if (disable_break() || !Load()) {
883 SetAfterBreakTarget(frame);
884 return heap->undefined_value();
887 // Enter the debugger.
888 EnterDebugger debugger(isolate_);
889 if (debugger.FailedToEnter()) {
890 return heap->undefined_value();
893 // Postpone interrupt during breakpoint processing.
894 PostponeInterruptsScope postpone(isolate_);
896 // Get the debug info (create it if it does not exist).
897 Handle<SharedFunctionInfo> shared =
898 Handle<SharedFunctionInfo>(frame->function()->shared());
899 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
901 // Find the break point where execution has stopped.
902 BreakLocationIterator break_location_iterator(debug_info,
903 ALL_BREAK_LOCATIONS);
904 // pc points to the instruction after the current one, possibly a break
905 // location as well. So the "- 1" to exclude it from the search.
906 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
908 // Check whether step next reached a new statement.
909 if (!StepNextContinue(&break_location_iterator, frame)) {
910 // Decrease steps left if performing multiple steps.
911 if (thread_local_.step_count_ > 0) {
912 thread_local_.step_count_--;
916 // If there is one or more real break points check whether any of these are
918 Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
919 if (break_location_iterator.HasBreakPoint()) {
920 Handle<Object> break_point_objects =
921 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_);
922 break_points_hit = CheckBreakPoints(break_point_objects);
925 // If step out is active skip everything until the frame where we need to step
926 // out to is reached, unless real breakpoint is hit.
927 if (StepOutActive() && frame->fp() != step_out_fp() &&
928 break_points_hit->IsUndefined() ) {
929 // Step count should always be 0 for StepOut.
930 ASSERT(thread_local_.step_count_ == 0);
931 } else if (!break_points_hit->IsUndefined() ||
932 (thread_local_.last_step_action_ != StepNone &&
933 thread_local_.step_count_ == 0)) {
934 // Notify debugger if a real break point is triggered or if performing
935 // single stepping with no more steps to perform. Otherwise do another step.
937 // Clear all current stepping setup.
940 if (thread_local_.queued_step_count_ > 0) {
941 // Perform queued steps
942 int step_count = thread_local_.queued_step_count_;
945 thread_local_.queued_step_count_ = 0;
947 PrepareStep(StepNext, step_count, StackFrame::NO_ID);
949 // Notify the debug event listeners.
950 isolate_->debugger()->OnDebugBreak(break_points_hit, false);
952 } else if (thread_local_.last_step_action_ != StepNone) {
953 // Hold on to last step action as it is cleared by the call to
955 StepAction step_action = thread_local_.last_step_action_;
956 int step_count = thread_local_.step_count_;
958 // If StepNext goes deeper in code, StepOut until original frame
959 // and keep step count queued up in the meantime.
960 if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
961 // Count frames until target frame
963 JavaScriptFrameIterator it(isolate_);
964 while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
969 // Check that we indeed found the frame we are looking for.
970 CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
971 if (step_count > 1) {
972 // Save old count and action to continue stepping after StepOut.
973 thread_local_.queued_step_count_ = step_count - 1;
976 // Set up for StepOut to reach target frame.
977 step_action = StepOut;
981 // Clear all current stepping setup.
984 // Set up for the remaining steps.
985 PrepareStep(step_action, step_count, StackFrame::NO_ID);
988 if (thread_local_.frame_drop_mode_ == FRAMES_UNTOUCHED) {
989 SetAfterBreakTarget(frame);
990 } else if (thread_local_.frame_drop_mode_ ==
991 FRAME_DROPPED_IN_IC_CALL) {
992 // We must have been calling IC stub. Do not go there anymore.
993 Code* plain_return = isolate_->builtins()->builtin(
994 Builtins::kPlainReturn_LiveEdit);
995 thread_local_.after_break_target_ = plain_return->entry();
996 } else if (thread_local_.frame_drop_mode_ ==
997 FRAME_DROPPED_IN_DEBUG_SLOT_CALL) {
998 // Debug break slot stub does not return normally, instead it manually
999 // cleans the stack and jumps. We should patch the jump address.
1000 Code* plain_return = isolate_->builtins()->builtin(
1001 Builtins::kFrameDropper_LiveEdit);
1002 thread_local_.after_break_target_ = plain_return->entry();
1003 } else if (thread_local_.frame_drop_mode_ ==
1004 FRAME_DROPPED_IN_DIRECT_CALL) {
1005 // Nothing to do, after_break_target is not used here.
1006 } else if (thread_local_.frame_drop_mode_ ==
1007 FRAME_DROPPED_IN_RETURN_CALL) {
1008 Code* plain_return = isolate_->builtins()->builtin(
1009 Builtins::kFrameDropper_LiveEdit);
1010 thread_local_.after_break_target_ = plain_return->entry();
1015 return heap->undefined_value();
1019 RUNTIME_FUNCTION(Debug_Break) {
1020 return isolate->debug()->Break(args);
1024 // Check the break point objects for whether one or more are actually
1025 // triggered. This function returns a JSArray with the break point objects
1026 // which is triggered.
1027 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
1028 Factory* factory = isolate_->factory();
1030 // Count the number of break points hit. If there are multiple break points
1031 // they are in a FixedArray.
1032 Handle<FixedArray> break_points_hit;
1033 int break_points_hit_count = 0;
1034 ASSERT(!break_point_objects->IsUndefined());
1035 if (break_point_objects->IsFixedArray()) {
1036 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
1037 break_points_hit = factory->NewFixedArray(array->length());
1038 for (int i = 0; i < array->length(); i++) {
1039 Handle<Object> o(array->get(i), isolate_);
1040 if (CheckBreakPoint(o)) {
1041 break_points_hit->set(break_points_hit_count++, *o);
1045 break_points_hit = factory->NewFixedArray(1);
1046 if (CheckBreakPoint(break_point_objects)) {
1047 break_points_hit->set(break_points_hit_count++, *break_point_objects);
1051 // Return undefined if no break points were triggered.
1052 if (break_points_hit_count == 0) {
1053 return factory->undefined_value();
1055 // Return break points hit as a JSArray.
1056 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
1057 result->set_length(Smi::FromInt(break_points_hit_count));
1062 // Check whether a single break point object is triggered.
1063 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
1064 Factory* factory = isolate_->factory();
1065 HandleScope scope(isolate_);
1067 // Ignore check if break point object is not a JSObject.
1068 if (!break_point_object->IsJSObject()) return true;
1070 // Get the function IsBreakPointTriggered (defined in debug-debugger.js).
1071 Handle<String> is_break_point_triggered_string =
1072 factory->InternalizeOneByteString(
1073 STATIC_ASCII_VECTOR("IsBreakPointTriggered"));
1074 Handle<GlobalObject> debug_global(debug_context()->global_object());
1075 Handle<JSFunction> check_break_point =
1076 Handle<JSFunction>::cast(Object::GetProperty(
1077 debug_global, is_break_point_triggered_string).ToHandleChecked());
1079 // Get the break id as an object.
1080 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
1082 // Call HandleBreakPointx.
1083 Handle<Object> argv[] = { break_id, break_point_object };
1084 Handle<Object> result;
1085 if (!Execution::TryCall(check_break_point,
1086 isolate_->js_builtins_object(),
1088 argv).ToHandle(&result)) {
1092 // Return whether the break point is triggered.
1093 return result->IsTrue();
1097 // Check whether the function has debug information.
1098 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
1099 return !shared->debug_info()->IsUndefined();
1103 // Return the debug info for this function. EnsureDebugInfo must be called
1104 // prior to ensure the debug info has been generated for shared.
1105 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
1106 ASSERT(HasDebugInfo(shared));
1107 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
1111 void Debug::SetBreakPoint(Handle<JSFunction> function,
1112 Handle<Object> break_point_object,
1113 int* source_position) {
1114 HandleScope scope(isolate_);
1116 PrepareForBreakPoints();
1118 // Make sure the function is compiled and has set up the debug info.
1119 Handle<SharedFunctionInfo> shared(function->shared());
1120 if (!EnsureDebugInfo(shared, function)) {
1121 // Return if retrieving debug info failed.
1125 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1126 // Source positions starts with zero.
1127 ASSERT(*source_position >= 0);
1129 // Find the break point and change it.
1130 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1131 it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED);
1132 it.SetBreakPoint(break_point_object);
1134 *source_position = it.position();
1136 // At least one active break point now.
1137 ASSERT(debug_info->GetBreakPointCount() > 0);
1141 bool Debug::SetBreakPointForScript(Handle<Script> script,
1142 Handle<Object> break_point_object,
1143 int* source_position,
1144 BreakPositionAlignment alignment) {
1145 HandleScope scope(isolate_);
1147 PrepareForBreakPoints();
1149 // Obtain shared function info for the function.
1150 Object* result = FindSharedFunctionInfoInScript(script, *source_position);
1151 if (result->IsUndefined()) return false;
1153 // Make sure the function has set up the debug info.
1154 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
1155 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1156 // Return if retrieving debug info failed.
1160 // Find position within function. The script position might be before the
1161 // source position of the first function.
1163 if (shared->start_position() > *source_position) {
1166 position = *source_position - shared->start_position();
1169 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1170 // Source positions starts with zero.
1171 ASSERT(position >= 0);
1173 // Find the break point and change it.
1174 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1175 it.FindBreakLocationFromPosition(position, alignment);
1176 it.SetBreakPoint(break_point_object);
1178 *source_position = it.position() + shared->start_position();
1180 // At least one active break point now.
1181 ASSERT(debug_info->GetBreakPointCount() > 0);
1186 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1187 HandleScope scope(isolate_);
1189 DebugInfoListNode* node = debug_info_list_;
1190 while (node != NULL) {
1191 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
1192 break_point_object);
1193 if (!result->IsUndefined()) {
1194 // Get information in the break point.
1195 BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
1196 Handle<DebugInfo> debug_info = node->debug_info();
1198 // Find the break point and clear it.
1199 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1200 it.FindBreakLocationFromAddress(debug_info->code()->entry() +
1201 break_point_info->code_position()->value());
1202 it.ClearBreakPoint(break_point_object);
1204 // If there are no more break points left remove the debug info for this
1206 if (debug_info->GetBreakPointCount() == 0) {
1207 RemoveDebugInfo(debug_info);
1212 node = node->next();
1217 void Debug::ClearAllBreakPoints() {
1218 DebugInfoListNode* node = debug_info_list_;
1219 while (node != NULL) {
1220 // Remove all debug break code.
1221 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1222 it.ClearAllDebugBreak();
1223 node = node->next();
1226 // Remove all debug info.
1227 while (debug_info_list_ != NULL) {
1228 RemoveDebugInfo(debug_info_list_->debug_info());
1233 void Debug::FloodWithOneShot(Handle<JSFunction> function) {
1234 PrepareForBreakPoints();
1236 // Make sure the function is compiled and has set up the debug info.
1237 Handle<SharedFunctionInfo> shared(function->shared());
1238 if (!EnsureDebugInfo(shared, function)) {
1239 // Return if we failed to retrieve the debug info.
1243 // Flood the function with break points.
1244 BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
1245 while (!it.Done()) {
1252 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
1253 Handle<FixedArray> new_bindings(function->function_bindings());
1254 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
1257 if (!bindee.is_null() && bindee->IsJSFunction() &&
1258 !JSFunction::cast(*bindee)->IsBuiltin()) {
1259 Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
1260 Debug::FloodWithOneShot(bindee_function);
1265 void Debug::FloodHandlerWithOneShot() {
1266 // Iterate through the JavaScript stack looking for handlers.
1267 StackFrame::Id id = break_frame_id();
1268 if (id == StackFrame::NO_ID) {
1269 // If there is no JavaScript stack don't do anything.
1272 for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
1273 JavaScriptFrame* frame = it.frame();
1274 if (frame->HasHandler()) {
1275 // Flood the function with the catch block with break points
1276 FloodWithOneShot(Handle<JSFunction>(frame->function()));
1283 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
1284 if (type == BreakUncaughtException) {
1285 break_on_uncaught_exception_ = enable;
1287 break_on_exception_ = enable;
1292 bool Debug::IsBreakOnException(ExceptionBreakType type) {
1293 if (type == BreakUncaughtException) {
1294 return break_on_uncaught_exception_;
1296 return break_on_exception_;
1301 void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) {
1302 Handle<JSFunction> promise_getter_global = Handle<JSFunction>::cast(
1303 isolate_->global_handles()->Create(*promise_getter));
1304 StackHandler* handler =
1305 StackHandler::FromAddress(Isolate::handler(isolate_->thread_local_top()));
1306 promise_getters_.Add(promise_getter_global);
1307 promise_catch_handlers_.Add(handler);
1311 void Debug::PromiseHandleEpilogue() {
1312 if (promise_catch_handlers_.length() == 0) return;
1313 promise_catch_handlers_.RemoveLast();
1314 Handle<Object> promise_getter = promise_getters_.RemoveLast();
1315 isolate_->global_handles()->Destroy(promise_getter.location());
1319 Handle<Object> Debug::GetPromiseForUncaughtException() {
1320 Handle<Object> undefined = isolate_->factory()->undefined_value();
1321 if (promise_getters_.length() == 0) return undefined;
1322 Handle<JSFunction> promise_getter = promise_getters_.last();
1323 StackHandler* promise_catch = promise_catch_handlers_.last();
1324 // Find the top-most try-catch handler.
1325 StackHandler* handler = StackHandler::FromAddress(
1326 Isolate::handler(isolate_->thread_local_top()));
1327 while (handler != NULL && !handler->is_catch()) {
1328 handler = handler->next();
1331 // Make sure that our promise catch handler is in the list of handlers,
1332 // even if it's not the top-most try-catch handler.
1333 StackHandler* temp = handler;
1334 while (temp != promise_catch && !temp->is_catch()) {
1335 temp = temp->next();
1336 CHECK(temp != NULL);
1340 if (handler == promise_catch) {
1341 return Execution::Call(
1342 isolate_, promise_getter, undefined, 0, NULL).ToHandleChecked();
1348 void Debug::PrepareStep(StepAction step_action,
1350 StackFrame::Id frame_id) {
1351 HandleScope scope(isolate_);
1353 PrepareForBreakPoints();
1355 ASSERT(Debug::InDebugger());
1357 // Remember this step action and count.
1358 thread_local_.last_step_action_ = step_action;
1359 if (step_action == StepOut) {
1360 // For step out target frame will be found on the stack so there is no need
1361 // to set step counter for it. It's expected to always be 0 for StepOut.
1362 thread_local_.step_count_ = 0;
1364 thread_local_.step_count_ = step_count;
1367 // Get the frame where the execution has stopped and skip the debug frame if
1368 // any. The debug frame will only be present if execution was stopped due to
1369 // hitting a break point. In other situations (e.g. unhandled exception) the
1370 // debug frame is not present.
1371 StackFrame::Id id = break_frame_id();
1372 if (id == StackFrame::NO_ID) {
1373 // If there is no JavaScript stack don't do anything.
1376 if (frame_id != StackFrame::NO_ID) {
1379 JavaScriptFrameIterator frames_it(isolate_, id);
1380 JavaScriptFrame* frame = frames_it.frame();
1382 // First of all ensure there is one-shot break points in the top handler
1384 FloodHandlerWithOneShot();
1386 // If the function on the top frame is unresolved perform step out. This will
1387 // be the case when calling unknown functions and having the debugger stopped
1388 // in an unhandled exception.
1389 if (!frame->function()->IsJSFunction()) {
1390 // Step out: Find the calling JavaScript frame and flood it with
1392 frames_it.Advance();
1393 // Fill the function to return to with one-shot break points.
1394 JSFunction* function = frames_it.frame()->function();
1395 FloodWithOneShot(Handle<JSFunction>(function));
1399 // Get the debug info (create it if it does not exist).
1400 Handle<JSFunction> function(frame->function());
1401 Handle<SharedFunctionInfo> shared(function->shared());
1402 if (!EnsureDebugInfo(shared, function)) {
1403 // Return if ensuring debug info failed.
1406 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1408 // Find the break location where execution has stopped.
1409 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1410 // pc points to the instruction after the current one, possibly a break
1411 // location as well. So the "- 1" to exclude it from the search.
1412 it.FindBreakLocationFromAddress(frame->pc() - 1);
1414 // Compute whether or not the target is a call target.
1415 bool is_load_or_store = false;
1416 bool is_inline_cache_stub = false;
1417 bool is_at_restarted_function = false;
1418 Handle<Code> call_function_stub;
1420 if (thread_local_.restarter_frame_function_pointer_ == NULL) {
1421 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1422 bool is_call_target = false;
1423 Address target = it.rinfo()->target_address();
1424 Code* code = Code::GetCodeFromTargetAddress(target);
1425 if (code->is_call_stub()) {
1426 is_call_target = true;
1428 if (code->is_inline_cache_stub()) {
1429 is_inline_cache_stub = true;
1430 is_load_or_store = !is_call_target;
1433 // Check if target code is CallFunction stub.
1434 Code* maybe_call_function_stub = code;
1435 // If there is a breakpoint at this line look at the original code to
1436 // check if it is a CallFunction stub.
1437 if (it.IsDebugBreak()) {
1438 Address original_target = it.original_rinfo()->target_address();
1439 maybe_call_function_stub =
1440 Code::GetCodeFromTargetAddress(original_target);
1442 if ((maybe_call_function_stub->kind() == Code::STUB &&
1443 maybe_call_function_stub->major_key() == CodeStub::CallFunction) ||
1444 maybe_call_function_stub->kind() == Code::CALL_IC) {
1445 // Save reference to the code as we may need it to find out arguments
1446 // count for 'step in' later.
1447 call_function_stub = Handle<Code>(maybe_call_function_stub);
1451 is_at_restarted_function = true;
1454 // If this is the last break code target step out is the only possibility.
1455 if (it.IsExit() || step_action == StepOut) {
1456 if (step_action == StepOut) {
1457 // Skip step_count frames starting with the current one.
1458 while (step_count-- > 0 && !frames_it.done()) {
1459 frames_it.Advance();
1462 ASSERT(it.IsExit());
1463 frames_it.Advance();
1465 // Skip builtin functions on the stack.
1466 while (!frames_it.done() && frames_it.frame()->function()->IsBuiltin()) {
1467 frames_it.Advance();
1469 // Step out: If there is a JavaScript caller frame, we need to
1470 // flood it with breakpoints.
1471 if (!frames_it.done()) {
1472 // Fill the function to return to with one-shot break points.
1473 JSFunction* function = frames_it.frame()->function();
1474 FloodWithOneShot(Handle<JSFunction>(function));
1475 // Set target frame pointer.
1476 ActivateStepOut(frames_it.frame());
1478 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
1479 !call_function_stub.is_null() || is_at_restarted_function)
1480 || step_action == StepNext || step_action == StepMin) {
1481 // Step next or step min.
1483 // Fill the current function with one-shot break points.
1484 FloodWithOneShot(function);
1486 // Remember source position and frame to handle step next.
1487 thread_local_.last_statement_position_ =
1488 debug_info->code()->SourceStatementPosition(frame->pc());
1489 thread_local_.last_fp_ = frame->UnpaddedFP();
1491 // If there's restarter frame on top of the stack, just get the pointer
1492 // to function which is going to be restarted.
1493 if (is_at_restarted_function) {
1494 Handle<JSFunction> restarted_function(
1495 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
1496 FloodWithOneShot(restarted_function);
1497 } else if (!call_function_stub.is_null()) {
1498 // If it's CallFunction stub ensure target function is compiled and flood
1499 // it with one shot breakpoints.
1500 bool is_call_ic = call_function_stub->kind() == Code::CALL_IC;
1502 // Find out number of arguments from the stub minor key.
1503 // Reverse lookup required as the minor key cannot be retrieved
1504 // from the code object.
1506 isolate_->heap()->code_stubs()->SlowReverseLookup(
1507 *call_function_stub),
1509 ASSERT(!obj.is_null());
1510 ASSERT(!(*obj)->IsUndefined());
1511 ASSERT(obj->IsSmi());
1512 // Get the STUB key and extract major and minor key.
1513 uint32_t key = Smi::cast(*obj)->value();
1514 // Argc in the stub is the number of arguments passed - not the
1515 // expected arguments of the called function.
1516 int call_function_arg_count = is_call_ic
1517 ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key))
1518 : CallFunctionStub::ExtractArgcFromMinorKey(
1519 CodeStub::MinorKeyFromKey(key));
1521 ASSERT(is_call_ic ||
1522 call_function_stub->major_key() == CodeStub::MajorKeyFromKey(key));
1524 // Find target function on the expression stack.
1525 // Expression stack looks like this (top to bottom):
1531 int expressions_count = frame->ComputeExpressionsCount();
1532 ASSERT(expressions_count - 2 - call_function_arg_count >= 0);
1533 Object* fun = frame->GetExpression(
1534 expressions_count - 2 - call_function_arg_count);
1536 // Flood the actual target of call/apply.
1537 if (fun->IsJSFunction()) {
1538 Isolate* isolate = JSFunction::cast(fun)->GetIsolate();
1539 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply);
1540 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall);
1541 while (fun->IsJSFunction()) {
1542 Code* code = JSFunction::cast(fun)->shared()->code();
1543 if (code != apply && code != call) break;
1544 fun = frame->GetExpression(
1545 expressions_count - 1 - call_function_arg_count);
1549 if (fun->IsJSFunction()) {
1550 Handle<JSFunction> js_function(JSFunction::cast(fun));
1551 if (js_function->shared()->bound()) {
1552 Debug::FloodBoundFunctionWithOneShot(js_function);
1553 } else if (!js_function->IsBuiltin()) {
1554 // Don't step into builtins.
1555 // It will also compile target function if it's not compiled yet.
1556 FloodWithOneShot(js_function);
1561 // Fill the current function with one-shot break points even for step in on
1562 // a call target as the function called might be a native function for
1563 // which step in will not stop. It also prepares for stepping in
1565 FloodWithOneShot(function);
1567 if (is_load_or_store) {
1568 // Remember source position and frame to handle step in getter/setter. If
1569 // there is a custom getter/setter it will be handled in
1570 // Object::Get/SetPropertyWithCallback, otherwise the step action will be
1571 // propagated on the next Debug::Break.
1572 thread_local_.last_statement_position_ =
1573 debug_info->code()->SourceStatementPosition(frame->pc());
1574 thread_local_.last_fp_ = frame->UnpaddedFP();
1577 // Step in or Step in min
1578 it.PrepareStepIn(isolate_);
1579 ActivateStepIn(frame);
1584 // Check whether the current debug break should be reported to the debugger. It
1585 // is used to have step next and step in only report break back to the debugger
1586 // if on a different frame or in a different statement. In some situations
1587 // there will be several break points in the same statement when the code is
1588 // flooded with one-shot break points. This function helps to perform several
1589 // steps before reporting break back to the debugger.
1590 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1591 JavaScriptFrame* frame) {
1592 // StepNext and StepOut shouldn't bring us deeper in code, so last frame
1593 // shouldn't be a parent of current frame.
1594 if (thread_local_.last_step_action_ == StepNext ||
1595 thread_local_.last_step_action_ == StepOut) {
1596 if (frame->fp() < thread_local_.last_fp_) return true;
1599 // If the step last action was step next or step in make sure that a new
1600 // statement is hit.
1601 if (thread_local_.last_step_action_ == StepNext ||
1602 thread_local_.last_step_action_ == StepIn) {
1603 // Never continue if returning from function.
1604 if (break_location_iterator->IsExit()) return false;
1606 // Continue if we are still on the same frame and in the same statement.
1607 int current_statement_position =
1608 break_location_iterator->code()->SourceStatementPosition(frame->pc());
1609 return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1610 thread_local_.last_statement_position_ == current_statement_position;
1613 // No step next action - don't continue.
1618 // Check whether the code object at the specified address is a debug break code
1620 bool Debug::IsDebugBreak(Address addr) {
1621 Code* code = Code::GetCodeFromTargetAddress(addr);
1622 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK;
1626 // Check whether a code stub with the specified major key is a possible break
1627 // point location when looking for source break locations.
1628 bool Debug::IsSourceBreakStub(Code* code) {
1629 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1630 return major_key == CodeStub::CallFunction;
1634 // Check whether a code stub with the specified major key is a possible break
1636 bool Debug::IsBreakStub(Code* code) {
1637 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1638 return major_key == CodeStub::CallFunction;
1642 // Find the builtin to use for invoking the debug break
1643 Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
1644 Isolate* isolate = code->GetIsolate();
1646 // Find the builtin debug break function matching the calling convention
1647 // used by the call site.
1648 if (code->is_inline_cache_stub()) {
1649 switch (code->kind()) {
1651 return isolate->builtins()->CallICStub_DebugBreak();
1654 return isolate->builtins()->LoadIC_DebugBreak();
1656 case Code::STORE_IC:
1657 return isolate->builtins()->StoreIC_DebugBreak();
1659 case Code::KEYED_LOAD_IC:
1660 return isolate->builtins()->KeyedLoadIC_DebugBreak();
1662 case Code::KEYED_STORE_IC:
1663 return isolate->builtins()->KeyedStoreIC_DebugBreak();
1665 case Code::COMPARE_NIL_IC:
1666 return isolate->builtins()->CompareNilIC_DebugBreak();
1672 if (RelocInfo::IsConstructCall(mode)) {
1673 if (code->has_function_cache()) {
1674 return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
1676 return isolate->builtins()->CallConstructStub_DebugBreak();
1679 if (code->kind() == Code::STUB) {
1680 ASSERT(code->major_key() == CodeStub::CallFunction);
1681 return isolate->builtins()->CallFunctionStub_DebugBreak();
1685 return Handle<Code>::null();
1689 // Simple function for returning the source positions for active break points.
1690 Handle<Object> Debug::GetSourceBreakLocations(
1691 Handle<SharedFunctionInfo> shared,
1692 BreakPositionAlignment position_alignment) {
1693 Isolate* isolate = shared->GetIsolate();
1694 Heap* heap = isolate->heap();
1695 if (!HasDebugInfo(shared)) {
1696 return Handle<Object>(heap->undefined_value(), isolate);
1698 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1699 if (debug_info->GetBreakPointCount() == 0) {
1700 return Handle<Object>(heap->undefined_value(), isolate);
1702 Handle<FixedArray> locations =
1703 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1705 for (int i = 0; i < debug_info->break_points()->length(); i++) {
1706 if (!debug_info->break_points()->get(i)->IsUndefined()) {
1707 BreakPointInfo* break_point_info =
1708 BreakPointInfo::cast(debug_info->break_points()->get(i));
1709 if (break_point_info->GetBreakPointCount() > 0) {
1711 switch (position_alignment) {
1712 case STATEMENT_ALIGNED:
1713 position = break_point_info->statement_position();
1715 case BREAK_POSITION_ALIGNED:
1716 position = break_point_info->source_position();
1720 position = break_point_info->statement_position();
1723 locations->set(count++, position);
1731 void Debug::NewBreak(StackFrame::Id break_frame_id) {
1732 thread_local_.break_frame_id_ = break_frame_id;
1733 thread_local_.break_id_ = ++thread_local_.break_count_;
1737 void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) {
1738 thread_local_.break_frame_id_ = break_frame_id;
1739 thread_local_.break_id_ = break_id;
1743 // Handle stepping into a function.
1744 void Debug::HandleStepIn(Handle<JSFunction> function,
1745 Handle<Object> holder,
1747 bool is_constructor) {
1748 Isolate* isolate = function->GetIsolate();
1749 // If the frame pointer is not supplied by the caller find it.
1751 StackFrameIterator it(isolate);
1753 // For constructor functions skip another frame.
1754 if (is_constructor) {
1755 ASSERT(it.frame()->is_construct());
1758 fp = it.frame()->fp();
1761 // Flood the function with one-shot break points if it is called from where
1762 // step into was requested.
1763 if (fp == step_in_fp()) {
1764 if (function->shared()->bound()) {
1765 // Handle Function.prototype.bind
1766 Debug::FloodBoundFunctionWithOneShot(function);
1767 } else if (!function->IsBuiltin()) {
1768 // Don't allow step into functions in the native context.
1769 if (function->shared()->code() ==
1770 isolate->builtins()->builtin(Builtins::kFunctionApply) ||
1771 function->shared()->code() ==
1772 isolate->builtins()->builtin(Builtins::kFunctionCall)) {
1773 // Handle function.apply and function.call separately to flood the
1774 // function to be called and not the code for Builtins::FunctionApply or
1775 // Builtins::FunctionCall. The receiver of call/apply is the target
1777 if (!holder.is_null() && holder->IsJSFunction()) {
1778 Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
1779 if (!js_function->IsBuiltin()) {
1780 Debug::FloodWithOneShot(js_function);
1781 } else if (js_function->shared()->bound()) {
1782 // Handle Function.prototype.bind
1783 Debug::FloodBoundFunctionWithOneShot(js_function);
1787 Debug::FloodWithOneShot(function);
1794 void Debug::ClearStepping() {
1795 // Clear the various stepping setup.
1801 // Clear multiple step counter.
1802 thread_local_.step_count_ = 0;
1806 // Clears all the one-shot break points that are currently set. Normally this
1807 // function is called each time a break point is hit as one shot break points
1808 // are used to support stepping.
1809 void Debug::ClearOneShot() {
1810 // The current implementation just runs through all the breakpoints. When the
1811 // last break point for a function is removed that function is automatically
1812 // removed from the list.
1814 DebugInfoListNode* node = debug_info_list_;
1815 while (node != NULL) {
1816 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1817 while (!it.Done()) {
1821 node = node->next();
1826 void Debug::ActivateStepIn(StackFrame* frame) {
1827 ASSERT(!StepOutActive());
1828 thread_local_.step_into_fp_ = frame->UnpaddedFP();
1832 void Debug::ClearStepIn() {
1833 thread_local_.step_into_fp_ = 0;
1837 void Debug::ActivateStepOut(StackFrame* frame) {
1838 ASSERT(!StepInActive());
1839 thread_local_.step_out_fp_ = frame->UnpaddedFP();
1843 void Debug::ClearStepOut() {
1844 thread_local_.step_out_fp_ = 0;
1848 void Debug::ClearStepNext() {
1849 thread_local_.last_step_action_ = StepNone;
1850 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1851 thread_local_.last_fp_ = 0;
1855 static void CollectActiveFunctionsFromThread(
1857 ThreadLocalTop* top,
1858 List<Handle<JSFunction> >* active_functions,
1859 Object* active_code_marker) {
1860 // Find all non-optimized code functions with activation frames
1861 // on the stack. This includes functions which have optimized
1862 // activations (including inlined functions) on the stack as the
1863 // non-optimized code is needed for the lazy deoptimization.
1864 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1865 JavaScriptFrame* frame = it.frame();
1866 if (frame->is_optimized()) {
1867 List<JSFunction*> functions(FLAG_max_inlining_levels + 1);
1868 frame->GetFunctions(&functions);
1869 for (int i = 0; i < functions.length(); i++) {
1870 JSFunction* function = functions[i];
1871 active_functions->Add(Handle<JSFunction>(function));
1872 function->shared()->code()->set_gc_metadata(active_code_marker);
1874 } else if (frame->function()->IsJSFunction()) {
1875 JSFunction* function = frame->function();
1876 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1877 active_functions->Add(Handle<JSFunction>(function));
1878 function->shared()->code()->set_gc_metadata(active_code_marker);
1884 // Figure out how many bytes of "pc_offset" correspond to actual code by
1885 // subtracting off the bytes that correspond to constant/veneer pools. See
1886 // Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this
1887 // is only useful for architectures using constant pools or veneer pools.
1888 static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) {
1889 ASSERT_EQ(code->kind(), Code::FUNCTION);
1890 ASSERT(!code->has_debug_break_slots());
1891 ASSERT_LE(0, pc_offset);
1892 ASSERT_LT(pc_offset, code->instruction_end() - code->instruction_start());
1894 int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1895 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1896 byte *pc = code->instruction_start() + pc_offset;
1897 int code_offset = pc_offset;
1898 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1899 RelocInfo* info = it.rinfo();
1900 if (info->pc() >= pc) break;
1901 ASSERT(RelocInfo::IsConstPool(info->rmode()));
1902 code_offset -= static_cast<int>(info->data());
1903 ASSERT_LE(0, code_offset);
1910 // The inverse of ComputeCodeOffsetFromPcOffset.
1911 static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) {
1912 ASSERT_EQ(code->kind(), Code::FUNCTION);
1914 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
1915 RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1916 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1918 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1919 RelocInfo* info = it.rinfo();
1920 if (info->pc() - code->instruction_start() - reloc >= code_offset) break;
1921 if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
1922 reloc += Assembler::kDebugBreakSlotLength;
1924 ASSERT(RelocInfo::IsConstPool(info->rmode()));
1925 reloc += static_cast<int>(info->data());
1929 int pc_offset = code_offset + reloc;
1931 ASSERT_LT(code->instruction_start() + pc_offset, code->instruction_end());
1937 static void RedirectActivationsToRecompiledCodeOnThread(
1939 ThreadLocalTop* top) {
1940 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1941 JavaScriptFrame* frame = it.frame();
1943 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue;
1945 JSFunction* function = frame->function();
1947 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1949 Handle<Code> frame_code(frame->LookupCode());
1950 if (frame_code->has_debug_break_slots()) continue;
1952 Handle<Code> new_code(function->shared()->code());
1953 if (new_code->kind() != Code::FUNCTION ||
1954 !new_code->has_debug_break_slots()) {
1959 static_cast<int>(frame->pc() - frame_code->instruction_start());
1960 int code_offset = ComputeCodeOffsetFromPcOffset(*frame_code, old_pc_offset);
1961 int new_pc_offset = ComputePcOffsetFromCodeOffset(*new_code, code_offset);
1963 // Compute the equivalent pc in the new code.
1964 byte* new_pc = new_code->instruction_start() + new_pc_offset;
1966 if (FLAG_trace_deopt) {
1967 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1968 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1970 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
1971 reinterpret_cast<intptr_t>(
1972 frame_code->instruction_start()),
1973 reinterpret_cast<intptr_t>(
1974 frame_code->instruction_start()) +
1975 frame_code->instruction_size(),
1976 frame_code->instruction_size(),
1977 reinterpret_cast<intptr_t>(new_code->instruction_start()),
1978 reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1979 new_code->instruction_size(),
1980 new_code->instruction_size(),
1981 reinterpret_cast<intptr_t>(frame->pc()),
1982 reinterpret_cast<intptr_t>(new_pc));
1985 // Patch the return address to return into the code with
1986 // debug break slots.
1987 frame->set_pc(new_pc);
1992 class ActiveFunctionsCollector : public ThreadVisitor {
1994 explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
1995 Object* active_code_marker)
1996 : active_functions_(active_functions),
1997 active_code_marker_(active_code_marker) { }
1999 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
2000 CollectActiveFunctionsFromThread(isolate,
2003 active_code_marker_);
2007 List<Handle<JSFunction> >* active_functions_;
2008 Object* active_code_marker_;
2012 class ActiveFunctionsRedirector : public ThreadVisitor {
2014 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
2015 RedirectActivationsToRecompiledCodeOnThread(isolate, top);
2020 class ForceDebuggerActive {
2022 explicit ForceDebuggerActive(Isolate *isolate) {
2024 old_state_ = isolate->debugger()->force_debugger_active();
2025 isolate_->debugger()->set_force_debugger_active(true);
2028 ~ForceDebuggerActive() {
2029 isolate_->debugger()->set_force_debugger_active(old_state_);
2036 DISALLOW_COPY_AND_ASSIGN(ForceDebuggerActive);
2040 void Debug::MaybeRecompileFunctionForDebugging(Handle<JSFunction> function) {
2041 ASSERT_EQ(Code::FUNCTION, function->code()->kind());
2042 ASSERT_EQ(function->code(), function->shared()->code());
2044 if (function->code()->has_debug_break_slots()) return;
2046 ForceDebuggerActive force_debugger_active(isolate_);
2047 MaybeHandle<Code> code = Compiler::GetCodeForDebugging(function);
2048 // Recompilation can fail. In that case leave the code as it was.
2049 if (!code.is_null())
2050 function->ReplaceCode(*code.ToHandleChecked());
2051 ASSERT_EQ(function->code(), function->shared()->code());
2055 void Debug::RecompileAndRelocateSuspendedGenerators(
2056 const List<Handle<JSGeneratorObject> > &generators) {
2057 for (int i = 0; i < generators.length(); i++) {
2058 Handle<JSFunction> fun(generators[i]->function());
2060 MaybeRecompileFunctionForDebugging(fun);
2062 int code_offset = generators[i]->continuation();
2063 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset);
2064 generators[i]->set_continuation(pc_offset);
2069 void Debug::PrepareForBreakPoints() {
2070 // If preparing for the first break point make sure to deoptimize all
2071 // functions as debugging does not work with optimized code.
2072 if (!has_break_points_) {
2073 if (isolate_->concurrent_recompilation_enabled()) {
2074 isolate_->optimizing_compiler_thread()->Flush();
2077 Deoptimizer::DeoptimizeAll(isolate_);
2079 Handle<Code> lazy_compile = isolate_->builtins()->CompileUnoptimized();
2081 // There will be at least one break point when we are done.
2082 has_break_points_ = true;
2084 // Keep the list of activated functions in a handlified list as it
2085 // is used both in GC and non-GC code.
2086 List<Handle<JSFunction> > active_functions(100);
2088 // A list of all suspended generators.
2089 List<Handle<JSGeneratorObject> > suspended_generators;
2091 // A list of all generator functions. We need to recompile all functions,
2092 // but we don't know until after visiting the whole heap which generator
2093 // functions have suspended activations and which do not. As in the case of
2094 // functions with activations on the stack, we need to be careful with
2095 // generator functions with suspended activations because although they
2096 // should be recompiled, recompilation can fail, and we need to avoid
2097 // leaving the heap in an inconsistent state.
2099 // We could perhaps avoid this list and instead re-use the GC metadata
2101 List<Handle<JSFunction> > generator_functions;
2104 // We are going to iterate heap to find all functions without
2105 // debug break slots.
2106 Heap* heap = isolate_->heap();
2107 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
2108 "preparing for breakpoints");
2110 // Ensure no GC in this scope as we are going to use gc_metadata
2111 // field in the Code object to mark active functions.
2112 DisallowHeapAllocation no_allocation;
2114 Object* active_code_marker = heap->the_hole_value();
2116 CollectActiveFunctionsFromThread(isolate_,
2117 isolate_->thread_local_top(),
2119 active_code_marker);
2120 ActiveFunctionsCollector active_functions_collector(&active_functions,
2121 active_code_marker);
2122 isolate_->thread_manager()->IterateArchivedThreads(
2123 &active_functions_collector);
2125 // Scan the heap for all non-optimized functions which have no
2126 // debug break slots and are not active or inlined into an active
2127 // function and mark them for lazy compilation.
2128 HeapIterator iterator(heap);
2129 HeapObject* obj = NULL;
2130 while (((obj = iterator.next()) != NULL)) {
2131 if (obj->IsJSFunction()) {
2132 JSFunction* function = JSFunction::cast(obj);
2133 SharedFunctionInfo* shared = function->shared();
2135 if (!shared->allows_lazy_compilation()) continue;
2136 if (!shared->script()->IsScript()) continue;
2137 if (function->IsBuiltin()) continue;
2138 if (shared->code()->gc_metadata() == active_code_marker) continue;
2140 if (shared->is_generator()) {
2141 generator_functions.Add(Handle<JSFunction>(function, isolate_));
2145 Code::Kind kind = function->code()->kind();
2146 if (kind == Code::FUNCTION &&
2147 !function->code()->has_debug_break_slots()) {
2148 function->set_code(*lazy_compile);
2149 function->shared()->set_code(*lazy_compile);
2150 } else if (kind == Code::BUILTIN &&
2151 (function->IsInOptimizationQueue() ||
2152 function->IsMarkedForOptimization() ||
2153 function->IsMarkedForConcurrentOptimization())) {
2154 // Abort in-flight compilation.
2155 Code* shared_code = function->shared()->code();
2156 if (shared_code->kind() == Code::FUNCTION &&
2157 shared_code->has_debug_break_slots()) {
2158 function->set_code(shared_code);
2160 function->set_code(*lazy_compile);
2161 function->shared()->set_code(*lazy_compile);
2164 } else if (obj->IsJSGeneratorObject()) {
2165 JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
2166 if (!gen->is_suspended()) continue;
2168 JSFunction* fun = gen->function();
2169 ASSERT_EQ(fun->code()->kind(), Code::FUNCTION);
2170 if (fun->code()->has_debug_break_slots()) continue;
2172 int pc_offset = gen->continuation();
2173 ASSERT_LT(0, pc_offset);
2176 ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset);
2178 // This will be fixed after we recompile the functions.
2179 gen->set_continuation(code_offset);
2181 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_));
2185 // Clear gc_metadata field.
2186 for (int i = 0; i < active_functions.length(); i++) {
2187 Handle<JSFunction> function = active_functions[i];
2188 function->shared()->code()->set_gc_metadata(Smi::FromInt(0));
2192 // Recompile generator functions that have suspended activations, and
2193 // relocate those activations.
2194 RecompileAndRelocateSuspendedGenerators(suspended_generators);
2196 // Mark generator functions that didn't have suspended activations for lazy
2197 // recompilation. Note that this set does not include any active functions.
2198 for (int i = 0; i < generator_functions.length(); i++) {
2199 Handle<JSFunction> &function = generator_functions[i];
2200 if (function->code()->kind() != Code::FUNCTION) continue;
2201 if (function->code()->has_debug_break_slots()) continue;
2202 function->set_code(*lazy_compile);
2203 function->shared()->set_code(*lazy_compile);
2206 // Now recompile all functions with activation frames and and
2207 // patch the return address to run in the new compiled code. It could be
2208 // that some active functions were recompiled already by the suspended
2209 // generator recompilation pass above; a generator with suspended
2210 // activations could also have active activations. That's fine.
2211 for (int i = 0; i < active_functions.length(); i++) {
2212 Handle<JSFunction> function = active_functions[i];
2213 Handle<SharedFunctionInfo> shared(function->shared());
2215 // If recompilation is not possible just skip it.
2216 if (shared->is_toplevel()) continue;
2217 if (!shared->allows_lazy_compilation()) continue;
2218 if (shared->code()->kind() == Code::BUILTIN) continue;
2220 MaybeRecompileFunctionForDebugging(function);
2223 RedirectActivationsToRecompiledCodeOnThread(isolate_,
2224 isolate_->thread_local_top());
2226 ActiveFunctionsRedirector active_functions_redirector;
2227 isolate_->thread_manager()->IterateArchivedThreads(
2228 &active_functions_redirector);
2233 Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2235 // Iterate the heap looking for SharedFunctionInfo generated from the
2236 // script. The inner most SharedFunctionInfo containing the source position
2237 // for the requested break point is found.
2238 // NOTE: This might require several heap iterations. If the SharedFunctionInfo
2239 // which is found is not compiled it is compiled and the heap is iterated
2240 // again as the compilation might create inner functions from the newly
2241 // compiled function and the actual requested break point might be in one of
2243 // NOTE: The below fix-point iteration depends on all functions that cannot be
2244 // compiled lazily without a context to not be compiled at all. Compilation
2245 // will be triggered at points where we do not need a context.
2247 // The current candidate for the source position:
2248 int target_start_position = RelocInfo::kNoPosition;
2249 Handle<JSFunction> target_function;
2250 Handle<SharedFunctionInfo> target;
2251 Heap* heap = isolate_->heap();
2253 { // Extra scope for iterator and no-allocation.
2254 heap->EnsureHeapIsIterable();
2255 DisallowHeapAllocation no_alloc_during_heap_iteration;
2256 HeapIterator iterator(heap);
2257 for (HeapObject* obj = iterator.next();
2258 obj != NULL; obj = iterator.next()) {
2259 bool found_next_candidate = false;
2260 Handle<JSFunction> function;
2261 Handle<SharedFunctionInfo> shared;
2262 if (obj->IsJSFunction()) {
2263 function = Handle<JSFunction>(JSFunction::cast(obj));
2264 shared = Handle<SharedFunctionInfo>(function->shared());
2265 ASSERT(shared->allows_lazy_compilation() || shared->is_compiled());
2266 found_next_candidate = true;
2267 } else if (obj->IsSharedFunctionInfo()) {
2268 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj));
2269 // Skip functions that we cannot compile lazily without a context,
2270 // which is not available here, because there is no closure.
2271 found_next_candidate = shared->is_compiled() ||
2272 shared->allows_lazy_compilation_without_context();
2274 if (!found_next_candidate) continue;
2275 if (shared->script() == *script) {
2276 // If the SharedFunctionInfo found has the requested script data and
2277 // contains the source position it is a candidate.
2278 int start_position = shared->function_token_position();
2279 if (start_position == RelocInfo::kNoPosition) {
2280 start_position = shared->start_position();
2282 if (start_position <= position &&
2283 position <= shared->end_position()) {
2284 // If there is no candidate or this function is within the current
2285 // candidate this is the new candidate.
2286 if (target.is_null()) {
2287 target_start_position = start_position;
2288 target_function = function;
2291 if (target_start_position == start_position &&
2292 shared->end_position() == target->end_position()) {
2293 // If a top-level function contains only one function
2294 // declaration the source for the top-level and the function
2295 // is the same. In that case prefer the non top-level function.
2296 if (!shared->is_toplevel()) {
2297 target_start_position = start_position;
2298 target_function = function;
2301 } else if (target_start_position <= start_position &&
2302 shared->end_position() <= target->end_position()) {
2303 // This containment check includes equality as a function
2304 // inside a top-level function can share either start or end
2305 // position with the top-level function.
2306 target_start_position = start_position;
2307 target_function = function;
2314 } // End no-allocation scope.
2316 if (target.is_null()) return heap->undefined_value();
2318 // There will be at least one break point when we are done.
2319 has_break_points_ = true;
2321 // If the candidate found is compiled we are done.
2322 done = target->is_compiled();
2324 // If the candidate is not compiled, compile it to reveal any inner
2325 // functions which might contain the requested source position. This
2326 // will compile all inner functions that cannot be compiled without a
2327 // context, because Compiler::BuildFunctionInfo checks whether the
2328 // debugger is active.
2329 MaybeHandle<Code> maybe_result = target_function.is_null()
2330 ? Compiler::GetUnoptimizedCode(target)
2331 : Compiler::GetUnoptimizedCode(target_function);
2332 if (maybe_result.is_null()) return isolate_->heap()->undefined_value();
2334 } // End while loop.
2340 // Ensures the debug information is present for shared.
2341 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2342 Handle<JSFunction> function) {
2343 Isolate* isolate = shared->GetIsolate();
2345 // Return if we already have the debug info for shared.
2346 if (HasDebugInfo(shared)) {
2347 ASSERT(shared->is_compiled());
2351 // There will be at least one break point when we are done.
2352 has_break_points_ = true;
2354 // Ensure function is compiled. Return false if this failed.
2355 if (!function.is_null() &&
2356 !Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) {
2360 // Create the debug info object.
2361 Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared);
2363 // Add debug info to the list.
2364 DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
2365 node->set_next(debug_info_list_);
2366 debug_info_list_ = node;
2372 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
2373 ASSERT(debug_info_list_ != NULL);
2374 // Run through the debug info objects to find this one and remove it.
2375 DebugInfoListNode* prev = NULL;
2376 DebugInfoListNode* current = debug_info_list_;
2377 while (current != NULL) {
2378 if (*current->debug_info() == *debug_info) {
2379 // Unlink from list. If prev is NULL we are looking at the first element.
2381 debug_info_list_ = current->next();
2383 prev->set_next(current->next());
2385 current->debug_info()->shared()->set_debug_info(
2386 isolate_->heap()->undefined_value());
2389 // If there are no more debug info objects there are not more break
2391 has_break_points_ = debug_info_list_ != NULL;
2395 // Move to next in list.
2397 current = current->next();
2403 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
2404 HandleScope scope(isolate_);
2406 PrepareForBreakPoints();
2408 // Get the executing function in which the debug break occurred.
2409 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2410 Handle<SharedFunctionInfo> shared(function->shared());
2411 if (!EnsureDebugInfo(shared, function)) {
2412 // Return if we failed to retrieve the debug info.
2415 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2416 Handle<Code> code(debug_info->code());
2417 Handle<Code> original_code(debug_info->original_code());
2419 // Get the code which is actually executing.
2420 Handle<Code> frame_code(frame->LookupCode());
2421 ASSERT(frame_code.is_identical_to(code));
2424 // Find the call address in the running code. This address holds the call to
2425 // either a DebugBreakXXX or to the debug break return entry code if the
2426 // break point is still active after processing the break point.
2427 Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset;
2429 // Check if the location is at JS exit or debug break slot.
2430 bool at_js_return = false;
2431 bool break_at_js_return_active = false;
2432 bool at_debug_break_slot = false;
2433 RelocIterator it(debug_info->code());
2434 while (!it.done() && !at_js_return && !at_debug_break_slot) {
2435 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2436 at_js_return = (it.rinfo()->pc() ==
2437 addr - Assembler::kPatchReturnSequenceAddressOffset);
2438 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
2440 if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2441 at_debug_break_slot = (it.rinfo()->pc() ==
2442 addr - Assembler::kPatchDebugBreakSlotAddressOffset);
2447 // Handle the jump to continue execution after break point depending on the
2450 // If the break point as return is still active jump to the corresponding
2451 // place in the original code. If not the break point was removed during
2452 // break point processing.
2453 if (break_at_js_return_active) {
2454 addr += original_code->instruction_start() - code->instruction_start();
2457 // Move back to where the call instruction sequence started.
2458 thread_local_.after_break_target_ =
2459 addr - Assembler::kPatchReturnSequenceAddressOffset;
2460 } else if (at_debug_break_slot) {
2461 // Address of where the debug break slot starts.
2462 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
2464 // Continue just after the slot.
2465 thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
2466 } else if (IsDebugBreak(Assembler::target_address_at(addr, *code))) {
2467 // We now know that there is still a debug break call at the target address,
2468 // so the break point is still there and the original code will hold the
2469 // address to jump to in order to complete the call which is replaced by a
2470 // call to DebugBreakXXX.
2472 // Find the corresponding address in the original code.
2473 addr += original_code->instruction_start() - code->instruction_start();
2475 // Install jump to the call address in the original code. This will be the
2476 // call which was overwritten by the call to DebugBreakXXX.
2477 thread_local_.after_break_target_ =
2478 Assembler::target_address_at(addr, *original_code);
2480 // There is no longer a break point present. Don't try to look in the
2481 // original code as the running code will have the right address. This takes
2482 // care of the case where the last break point is removed from the function
2483 // and therefore no "original code" is available.
2484 thread_local_.after_break_target_ =
2485 Assembler::target_address_at(addr, *code);
2490 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
2491 HandleScope scope(isolate_);
2493 // If there are no break points this cannot be break at return, as
2494 // the debugger statement and stack guard bebug break cannot be at
2496 if (!has_break_points_) {
2500 PrepareForBreakPoints();
2502 // Get the executing function in which the debug break occurred.
2503 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2504 Handle<SharedFunctionInfo> shared(function->shared());
2505 if (!EnsureDebugInfo(shared, function)) {
2506 // Return if we failed to retrieve the debug info.
2509 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2510 Handle<Code> code(debug_info->code());
2512 // Get the code which is actually executing.
2513 Handle<Code> frame_code(frame->LookupCode());
2514 ASSERT(frame_code.is_identical_to(code));
2517 // Find the call address in the running code.
2518 Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset;
2520 // Check if the location is at JS return.
2521 RelocIterator it(debug_info->code());
2522 while (!it.done()) {
2523 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2524 return (it.rinfo()->pc() ==
2525 addr - Assembler::kPatchReturnSequenceAddressOffset);
2533 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
2535 Object** restarter_frame_function_pointer) {
2536 if (mode != CURRENTLY_SET_MODE) {
2537 thread_local_.frame_drop_mode_ = mode;
2539 thread_local_.break_frame_id_ = new_break_frame_id;
2540 thread_local_.restarter_frame_function_pointer_ =
2541 restarter_frame_function_pointer;
2545 const int Debug::FramePaddingLayout::kInitialSize = 1;
2548 // Any even value bigger than kInitialSize as needed for stack scanning.
2549 const int Debug::FramePaddingLayout::kPaddingValue = kInitialSize + 1;
2552 bool Debug::IsDebugGlobal(GlobalObject* global) {
2553 return IsLoaded() && global == debug_context()->global_object();
2557 void Debug::ClearMirrorCache() {
2558 PostponeInterruptsScope postpone(isolate_);
2559 HandleScope scope(isolate_);
2560 ASSERT(isolate_->context() == *Debug::debug_context());
2562 // Clear the mirror cache.
2563 Handle<String> function_name = isolate_->factory()->InternalizeOneByteString(
2564 STATIC_ASCII_VECTOR("ClearMirrorCache"));
2565 Handle<Object> fun = Object::GetProperty(
2566 isolate_->global_object(), function_name).ToHandleChecked();
2567 ASSERT(fun->IsJSFunction());
2569 Handle<JSFunction>::cast(fun),
2570 Handle<JSObject>(Debug::debug_context()->global_object()),
2576 void Debug::CreateScriptCache() {
2577 Heap* heap = isolate_->heap();
2578 HandleScope scope(isolate_);
2580 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
2581 // rid of all the cached script wrappers and the second gets rid of the
2582 // scripts which are no longer referenced. The second also sweeps precisely,
2583 // which saves us doing yet another GC to make the heap iterable.
2584 heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache");
2585 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
2586 "Debug::CreateScriptCache");
2588 ASSERT(script_cache_ == NULL);
2589 script_cache_ = new ScriptCache(isolate_);
2591 // Scan heap for Script objects.
2593 HeapIterator iterator(heap);
2594 DisallowHeapAllocation no_allocation;
2596 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
2597 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
2598 script_cache_->Add(Handle<Script>(Script::cast(obj)));
2605 void Debug::DestroyScriptCache() {
2606 // Get rid of the script cache if it was created.
2607 if (script_cache_ != NULL) {
2608 delete script_cache_;
2609 script_cache_ = NULL;
2614 void Debug::AddScriptToScriptCache(Handle<Script> script) {
2615 if (script_cache_ != NULL) {
2616 script_cache_->Add(script);
2621 Handle<FixedArray> Debug::GetLoadedScripts() {
2622 // Create and fill the script cache when the loaded scripts is requested for
2624 if (script_cache_ == NULL) {
2625 CreateScriptCache();
2628 // If the script cache is not active just return an empty array.
2629 ASSERT(script_cache_ != NULL);
2630 if (script_cache_ == NULL) {
2631 isolate_->factory()->NewFixedArray(0);
2634 // Perform GC to get unreferenced scripts evicted from the cache before
2635 // returning the content.
2636 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
2637 "Debug::GetLoadedScripts");
2639 // Get the scripts from the cache.
2640 return script_cache_->GetScripts();
2644 void Debug::RecordEvalCaller(Handle<Script> script) {
2645 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
2646 // For eval scripts add information on the function from which eval was
2648 StackTraceFrameIterator it(script->GetIsolate());
2650 script->set_eval_from_shared(it.frame()->function()->shared());
2651 Code* code = it.frame()->LookupCode();
2652 int offset = static_cast<int>(
2653 it.frame()->pc() - code->instruction_start());
2654 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
2659 void Debug::AfterGarbageCollection() {
2660 // Generate events for collected scripts.
2661 if (script_cache_ != NULL) {
2662 script_cache_->ProcessCollectedScripts();
2667 Debugger::Debugger(Isolate* isolate)
2668 : debugger_access_(isolate->debugger_access()),
2669 event_listener_(Handle<Object>()),
2670 event_listener_data_(Handle<Object>()),
2671 compiling_natives_(false),
2672 is_loading_debugger_(false),
2673 live_edit_enabled_(true),
2674 never_unload_debugger_(false),
2675 force_debugger_active_(false),
2676 message_handler_(NULL),
2677 debugger_unload_pending_(false),
2678 host_dispatch_handler_(NULL),
2679 debug_message_dispatch_handler_(NULL),
2680 message_dispatch_helper_thread_(NULL),
2681 host_dispatch_period_(TimeDelta::FromMilliseconds(100)),
2683 command_queue_(isolate->logger(), kQueueInitialSize),
2684 command_received_(0),
2685 event_command_queue_(isolate->logger(), kQueueInitialSize),
2690 Debugger::~Debugger() {}
2693 MaybeHandle<Object> Debugger::MakeJSObject(
2694 Vector<const char> constructor_name,
2696 Handle<Object> argv[]) {
2697 ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2699 // Create the execution state object.
2700 Handle<String> constructor_str =
2701 isolate_->factory()->InternalizeUtf8String(constructor_name);
2702 ASSERT(!constructor_str.is_null());
2703 Handle<Object> constructor = Object::GetProperty(
2704 isolate_->global_object(), constructor_str).ToHandleChecked();
2705 ASSERT(constructor->IsJSFunction());
2706 if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
2707 return Execution::TryCall(
2708 Handle<JSFunction>::cast(constructor),
2709 Handle<JSObject>(isolate_->debug()->debug_context()->global_object()),
2715 MaybeHandle<Object> Debugger::MakeExecutionState() {
2716 // Create the execution state object.
2717 Handle<Object> break_id = isolate_->factory()->NewNumberFromInt(
2718 isolate_->debug()->break_id());
2719 Handle<Object> argv[] = { break_id };
2720 return MakeJSObject(CStrVector("MakeExecutionState"), ARRAY_SIZE(argv), argv);
2724 MaybeHandle<Object> Debugger::MakeBreakEvent(Handle<Object> break_points_hit) {
2725 Handle<Object> exec_state;
2726 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
2727 // Create the new break event object.
2728 Handle<Object> argv[] = { exec_state, break_points_hit };
2729 return MakeJSObject(CStrVector("MakeBreakEvent"), ARRAY_SIZE(argv), argv);
2733 MaybeHandle<Object> Debugger::MakeExceptionEvent(Handle<Object> exception,
2735 Handle<Object> promise) {
2736 Handle<Object> exec_state;
2737 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
2738 // Create the new exception event object.
2739 Handle<Object> argv[] = { exec_state,
2741 isolate_->factory()->ToBoolean(uncaught),
2743 return MakeJSObject(CStrVector("MakeExceptionEvent"), ARRAY_SIZE(argv), argv);
2747 MaybeHandle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
2749 Handle<Object> exec_state;
2750 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
2751 // Create the compile event object.
2752 Handle<Object> script_wrapper = Script::GetWrapper(script);
2753 Handle<Object> argv[] = { exec_state,
2755 isolate_->factory()->ToBoolean(before) };
2756 return MakeJSObject(CStrVector("MakeCompileEvent"), ARRAY_SIZE(argv), argv);
2760 MaybeHandle<Object> Debugger::MakeScriptCollectedEvent(int id) {
2761 Handle<Object> exec_state;
2762 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
2763 // Create the script collected event object.
2764 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_);
2765 Handle<Object> argv[] = { exec_state, id_object };
2767 return MakeJSObject(
2768 CStrVector("MakeScriptCollectedEvent"), ARRAY_SIZE(argv), argv);
2772 void Debugger::OnException(Handle<Object> exception, bool uncaught) {
2773 HandleScope scope(isolate_);
2774 Debug* debug = isolate_->debug();
2776 // Bail out based on state or if there is no listener for this event
2777 if (debug->InDebugger()) return;
2778 if (!Debugger::EventActive(v8::Exception)) return;
2780 Handle<Object> promise = debug->GetPromiseForUncaughtException();
2781 uncaught |= !promise->IsUndefined();
2783 // Bail out if exception breaks are not active
2785 // Uncaught exceptions are reported by either flags.
2786 if (!(debug->break_on_uncaught_exception() ||
2787 debug->break_on_exception())) return;
2789 // Caught exceptions are reported is activated.
2790 if (!debug->break_on_exception()) return;
2793 // Enter the debugger.
2794 EnterDebugger debugger(isolate_);
2795 if (debugger.FailedToEnter()) return;
2797 // Clear all current stepping setup.
2798 debug->ClearStepping();
2800 // Create the event data object.
2801 Handle<Object> event_data;
2802 // Bail out and don't call debugger if exception.
2803 if (!MakeExceptionEvent(
2804 exception, uncaught, promise).ToHandle(&event_data)) {
2808 // Process debug event.
2809 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
2810 // Return to continue execution from where the exception was thrown.
2814 void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
2815 bool auto_continue) {
2816 HandleScope scope(isolate_);
2818 // Debugger has already been entered by caller.
2819 ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2821 // Bail out if there is no listener for this event
2822 if (!Debugger::EventActive(v8::Break)) return;
2824 // Debugger must be entered in advance.
2825 ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2827 // Create the event data object.
2828 Handle<Object> event_data;
2829 // Bail out and don't call debugger if exception.
2830 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
2832 // Process debug event.
2833 ProcessDebugEvent(v8::Break,
2834 Handle<JSObject>::cast(event_data),
2839 void Debugger::OnBeforeCompile(Handle<Script> script) {
2840 HandleScope scope(isolate_);
2842 // Bail out based on state or if there is no listener for this event
2843 if (isolate_->debug()->InDebugger()) return;
2844 if (compiling_natives()) return;
2845 if (!EventActive(v8::BeforeCompile)) return;
2847 // Enter the debugger.
2848 EnterDebugger debugger(isolate_);
2849 if (debugger.FailedToEnter()) return;
2851 // Create the event data object.
2852 Handle<Object> event_data;
2853 // Bail out and don't call debugger if exception.
2854 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return;
2856 // Process debug event.
2857 ProcessDebugEvent(v8::BeforeCompile,
2858 Handle<JSObject>::cast(event_data),
2863 // Handle debugger actions when a new script is compiled.
2864 void Debugger::OnAfterCompile(Handle<Script> script,
2865 AfterCompileFlags after_compile_flags) {
2866 HandleScope scope(isolate_);
2867 Debug* debug = isolate_->debug();
2869 // Add the newly compiled script to the script cache.
2870 debug->AddScriptToScriptCache(script);
2872 // No more to do if not debugging.
2873 if (!IsDebuggerActive()) return;
2875 // No compile events while compiling natives.
2876 if (compiling_natives()) return;
2878 // Store whether in debugger before entering debugger.
2879 bool in_debugger = debug->InDebugger();
2881 // Enter the debugger.
2882 EnterDebugger debugger(isolate_);
2883 if (debugger.FailedToEnter()) return;
2885 // If debugging there might be script break points registered for this
2886 // script. Make sure that these break points are set.
2888 // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js).
2889 Handle<String> update_script_break_points_string =
2890 isolate_->factory()->InternalizeOneByteString(
2891 STATIC_ASCII_VECTOR("UpdateScriptBreakPoints"));
2892 Handle<GlobalObject> debug_global(debug->debug_context()->global_object());
2893 Handle<Object> update_script_break_points =
2894 Object::GetProperty(
2895 debug_global, update_script_break_points_string).ToHandleChecked();
2896 if (!update_script_break_points->IsJSFunction()) {
2899 ASSERT(update_script_break_points->IsJSFunction());
2901 // Wrap the script object in a proper JS object before passing it
2903 Handle<Object> wrapper = Script::GetWrapper(script);
2905 // Call UpdateScriptBreakPoints expect no exceptions.
2906 Handle<Object> argv[] = { wrapper };
2907 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
2908 isolate_->js_builtins_object(),
2913 // Bail out based on state or if there is no listener for this event
2914 if (in_debugger && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return;
2915 if (!Debugger::EventActive(v8::AfterCompile)) return;
2917 // Create the compile state object.
2918 Handle<Object> event_data;
2919 // Bail out and don't call debugger if exception.
2920 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return;
2922 // Process debug event.
2923 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
2927 void Debugger::OnScriptCollected(int id) {
2928 HandleScope scope(isolate_);
2930 // No more to do if not debugging.
2931 if (isolate_->debug()->InDebugger()) return;
2932 if (!IsDebuggerActive()) return;
2933 if (!Debugger::EventActive(v8::ScriptCollected)) return;
2935 // Enter the debugger.
2936 EnterDebugger debugger(isolate_);
2937 if (debugger.FailedToEnter()) return;
2939 // Create the script collected state object.
2940 Handle<Object> event_data;
2941 // Bail out and don't call debugger if exception.
2942 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return;
2944 // Process debug event.
2945 ProcessDebugEvent(v8::ScriptCollected,
2946 Handle<JSObject>::cast(event_data),
2951 void Debugger::ProcessDebugEvent(v8::DebugEvent event,
2952 Handle<JSObject> event_data,
2953 bool auto_continue) {
2954 HandleScope scope(isolate_);
2956 // Clear any pending debug break if this is a real break.
2957 if (!auto_continue) {
2958 isolate_->debug()->clear_interrupt_pending(DEBUGBREAK);
2961 // Create the execution state.
2962 Handle<Object> exec_state;
2963 // Bail out and don't call debugger if exception.
2964 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2966 // First notify the message handler if any.
2967 if (message_handler_ != NULL) {
2968 NotifyMessageHandler(event,
2969 Handle<JSObject>::cast(exec_state),
2973 // Notify registered debug event listener. This can be either a C or
2974 // a JavaScript function. Don't call event listener for v8::Break
2975 // here, if it's only a debug command -- they will be processed later.
2976 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
2977 CallEventCallback(event, exec_state, event_data, NULL);
2979 // Process pending debug commands.
2980 if (event == v8::Break) {
2981 while (!event_command_queue_.IsEmpty()) {
2982 CommandMessage command = event_command_queue_.Get();
2983 if (!event_listener_.is_null()) {
2984 CallEventCallback(v8::BreakForCommand,
2987 command.client_data());
2995 void Debugger::CallEventCallback(v8::DebugEvent event,
2996 Handle<Object> exec_state,
2997 Handle<Object> event_data,
2998 v8::Debug::ClientData* client_data) {
2999 if (event_listener_->IsForeign()) {
3000 CallCEventCallback(event, exec_state, event_data, client_data);
3002 CallJSEventCallback(event, exec_state, event_data);
3007 void Debugger::CallCEventCallback(v8::DebugEvent event,
3008 Handle<Object> exec_state,
3009 Handle<Object> event_data,
3010 v8::Debug::ClientData* client_data) {
3011 Handle<Foreign> callback_obj(Handle<Foreign>::cast(event_listener_));
3012 v8::Debug::EventCallback2 callback =
3013 FUNCTION_CAST<v8::Debug::EventCallback2>(
3014 callback_obj->foreign_address());
3015 EventDetailsImpl event_details(
3017 Handle<JSObject>::cast(exec_state),
3018 Handle<JSObject>::cast(event_data),
3019 event_listener_data_,
3021 callback(event_details);
3025 void Debugger::CallJSEventCallback(v8::DebugEvent event,
3026 Handle<Object> exec_state,
3027 Handle<Object> event_data) {
3028 ASSERT(event_listener_->IsJSFunction());
3029 Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
3031 // Invoke the JavaScript debug event listener.
3032 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
3035 event_listener_data_ };
3036 Execution::TryCall(fun,
3037 isolate_->global_object(),
3040 // Silently ignore exceptions from debug event listeners.
3044 Handle<Context> Debugger::GetDebugContext() {
3045 never_unload_debugger_ = true;
3046 EnterDebugger debugger(isolate_);
3047 return isolate_->debug()->debug_context();
3051 void Debugger::UnloadDebugger() {
3052 Debug* debug = isolate_->debug();
3054 // Make sure that there are no breakpoints left.
3055 debug->ClearAllBreakPoints();
3057 // Unload the debugger if feasible.
3058 if (!never_unload_debugger_) {
3062 // Clear the flag indicating that the debugger should be unloaded.
3063 debugger_unload_pending_ = false;
3067 void Debugger::NotifyMessageHandler(v8::DebugEvent event,
3068 Handle<JSObject> exec_state,
3069 Handle<JSObject> event_data,
3070 bool auto_continue) {
3071 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_);
3072 HandleScope scope(isolate_);
3074 if (!isolate_->debug()->Load()) return;
3076 // Process the individual events.
3077 bool sendEventMessage = false;
3080 case v8::BreakForCommand:
3081 sendEventMessage = !auto_continue;
3084 sendEventMessage = true;
3086 case v8::BeforeCompile:
3088 case v8::AfterCompile:
3089 sendEventMessage = true;
3091 case v8::ScriptCollected:
3092 sendEventMessage = true;
3094 case v8::NewFunction:
3100 // The debug command interrupt flag might have been set when the command was
3101 // added. It should be enough to clear the flag only once while we are in the
3103 ASSERT(isolate_->debug()->InDebugger());
3104 isolate_->stack_guard()->Continue(DEBUGCOMMAND);
3106 // Notify the debugger that a debug event has occurred unless auto continue is
3107 // active in which case no event is send.
3108 if (sendEventMessage) {
3109 MessageImpl message = MessageImpl::NewEvent(
3112 Handle<JSObject>::cast(exec_state),
3113 Handle<JSObject>::cast(event_data));
3114 InvokeMessageHandler(message);
3117 // If auto continue don't make the event cause a break, but process messages
3118 // in the queue if any. For script collected events don't even process
3119 // messages in the queue as the execution state might not be what is expected
3121 if ((auto_continue && !HasCommands()) || event == v8::ScriptCollected) {
3125 v8::TryCatch try_catch;
3127 // DebugCommandProcessor goes here.
3128 v8::Local<v8::Object> cmd_processor;
3130 v8::Local<v8::Object> api_exec_state =
3131 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
3132 v8::Local<v8::String> fun_name = v8::String::NewFromUtf8(
3133 isolate, "debugCommandProcessor");
3134 v8::Local<v8::Function> fun =
3135 v8::Local<v8::Function>::Cast(api_exec_state->Get(fun_name));
3137 v8::Handle<v8::Boolean> running = v8::Boolean::New(isolate, auto_continue);
3138 static const int kArgc = 1;
3139 v8::Handle<Value> argv[kArgc] = { running };
3140 cmd_processor = v8::Local<v8::Object>::Cast(
3141 fun->Call(api_exec_state, kArgc, argv));
3142 if (try_catch.HasCaught()) {
3143 PrintLn(try_catch.Exception());
3148 bool running = auto_continue;
3150 // Process requests from the debugger.
3152 // Wait for new command in the queue.
3153 if (Debugger::host_dispatch_handler_) {
3154 // In case there is a host dispatch - do periodic dispatches.
3155 if (!command_received_.WaitFor(host_dispatch_period_)) {
3156 // Timout expired, do the dispatch.
3157 Debugger::host_dispatch_handler_();
3161 // In case there is no host dispatch - just wait.
3162 command_received_.Wait();
3165 // Get the command from the queue.
3166 CommandMessage command = command_queue_.Get();
3167 isolate_->logger()->DebugTag(
3168 "Got request from command queue, in interactive loop.");
3169 if (!Debugger::IsDebuggerActive()) {
3170 // Delete command text and user data.
3175 // Invoke JavaScript to process the debug request.
3176 v8::Local<v8::String> fun_name;
3177 v8::Local<v8::Function> fun;
3178 v8::Local<v8::Value> request;
3179 v8::TryCatch try_catch;
3180 fun_name = v8::String::NewFromUtf8(isolate, "processDebugRequest");
3181 fun = v8::Local<v8::Function>::Cast(cmd_processor->Get(fun_name));
3183 request = v8::String::NewFromTwoByte(isolate, command.text().start(),
3184 v8::String::kNormalString,
3185 command.text().length());
3186 static const int kArgc = 1;
3187 v8::Handle<Value> argv[kArgc] = { request };
3188 v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
3190 // Get the response.
3191 v8::Local<v8::String> response;
3192 if (!try_catch.HasCaught()) {
3193 // Get response string.
3194 if (!response_val->IsUndefined()) {
3195 response = v8::Local<v8::String>::Cast(response_val);
3197 response = v8::String::NewFromUtf8(isolate, "");
3200 // Log the JSON request/response.
3201 if (FLAG_trace_debug_json) {
3206 // Get the running state.
3207 fun_name = v8::String::NewFromUtf8(isolate, "isRunning");
3208 fun = v8::Local<v8::Function>::Cast(cmd_processor->Get(fun_name));
3209 static const int kArgc = 1;
3210 v8::Handle<Value> argv[kArgc] = { response };
3211 v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv);
3212 if (!try_catch.HasCaught()) {
3213 running = running_val->ToBoolean()->Value();
3216 // In case of failure the result text is the exception text.
3217 response = try_catch.Exception()->ToString();
3220 // Return the result.
3221 MessageImpl message = MessageImpl::NewResponse(
3224 Handle<JSObject>::cast(exec_state),
3225 Handle<JSObject>::cast(event_data),
3226 Handle<String>(Utils::OpenHandle(*response)),
3227 command.client_data());
3228 InvokeMessageHandler(message);
3231 // Return from debug event processing if either the VM is put into the
3232 // running state (through a continue command) or auto continue is active
3233 // and there are no more commands queued.
3234 if (running && !HasCommands()) {
3241 void Debugger::SetEventListener(Handle<Object> callback,
3242 Handle<Object> data) {
3243 HandleScope scope(isolate_);
3244 GlobalHandles* global_handles = isolate_->global_handles();
3246 // Clear the global handles for the event listener and the event listener data
3248 if (!event_listener_.is_null()) {
3249 GlobalHandles::Destroy(
3250 reinterpret_cast<Object**>(event_listener_.location()));
3251 event_listener_ = Handle<Object>();
3253 if (!event_listener_data_.is_null()) {
3254 GlobalHandles::Destroy(
3255 reinterpret_cast<Object**>(event_listener_data_.location()));
3256 event_listener_data_ = Handle<Object>();
3259 // If there is a new debug event listener register it together with its data
3261 if (!callback->IsUndefined() && !callback->IsNull()) {
3262 event_listener_ = Handle<Object>::cast(
3263 global_handles->Create(*callback));
3264 if (data.is_null()) {
3265 data = isolate_->factory()->undefined_value();
3267 event_listener_data_ = Handle<Object>::cast(
3268 global_handles->Create(*data));
3275 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
3276 LockGuard<RecursiveMutex> with(debugger_access_);
3278 message_handler_ = handler;
3280 if (handler == NULL) {
3281 // Send an empty command to the debugger if in a break to make JavaScript
3282 // run again if the debugger is closed.
3283 if (isolate_->debug()->InDebugger()) {
3284 ProcessCommand(Vector<const uint16_t>::empty());
3290 void Debugger::ListenersChanged() {
3291 bool active = IsDebuggerActive();
3293 // Disable the compilation cache when the debugger is active.
3294 isolate_->compilation_cache()->Disable();
3295 debugger_unload_pending_ = false;
3297 isolate_->compilation_cache()->Enable();
3298 // Unload the debugger if event listener and message handler cleared.
3299 // Schedule this for later, because we may be in non-V8 thread.
3300 debugger_unload_pending_ = true;
3305 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
3307 host_dispatch_handler_ = handler;
3308 host_dispatch_period_ = period;
3312 void Debugger::SetDebugMessageDispatchHandler(
3313 v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) {
3314 LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3315 debug_message_dispatch_handler_ = handler;
3317 if (provide_locker && message_dispatch_helper_thread_ == NULL) {
3318 message_dispatch_helper_thread_ = new MessageDispatchHelperThread(isolate_);
3319 message_dispatch_helper_thread_->Start();
3324 // Calls the registered debug message handler. This callback is part of the
3326 void Debugger::InvokeMessageHandler(MessageImpl message) {
3327 LockGuard<RecursiveMutex> with(debugger_access_);
3329 if (message_handler_ != NULL) {
3330 message_handler_(message);
3335 // Puts a command coming from the public API on the queue. Creates
3336 // a copy of the command string managed by the debugger. Up to this
3337 // point, the command data was managed by the API client. Called
3338 // by the API client thread.
3339 void Debugger::ProcessCommand(Vector<const uint16_t> command,
3340 v8::Debug::ClientData* client_data) {
3341 // Need to cast away const.
3342 CommandMessage message = CommandMessage::New(
3343 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
3346 isolate_->logger()->DebugTag("Put command on command_queue.");
3347 command_queue_.Put(message);
3348 command_received_.Signal();
3350 // Set the debug command break flag to have the command processed.
3351 if (!isolate_->debug()->InDebugger()) {
3352 isolate_->stack_guard()->DebugCommand();
3355 MessageDispatchHelperThread* dispatch_thread;
3357 LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3358 dispatch_thread = message_dispatch_helper_thread_;
3361 if (dispatch_thread == NULL) {
3362 CallMessageDispatchHandler();
3364 dispatch_thread->Schedule();
3369 bool Debugger::HasCommands() {
3370 return !command_queue_.IsEmpty();
3374 void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
3375 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
3376 event_command_queue_.Put(message);
3378 // Set the debug command break flag to have the command processed.
3379 if (!isolate_->debug()->InDebugger()) {
3380 isolate_->stack_guard()->DebugCommand();
3385 bool Debugger::IsDebuggerActive() {
3386 LockGuard<RecursiveMutex> with(debugger_access_);
3388 return message_handler_ != NULL ||
3389 !event_listener_.is_null() ||
3390 force_debugger_active_;
3394 MaybeHandle<Object> Debugger::Call(Handle<JSFunction> fun,
3395 Handle<Object> data) {
3396 // When calling functions in the debugger prevent it from beeing unloaded.
3397 Debugger::never_unload_debugger_ = true;
3399 // Enter the debugger.
3400 EnterDebugger debugger(isolate_);
3401 if (debugger.FailedToEnter()) {
3402 return isolate_->factory()->undefined_value();
3405 // Create the execution state.
3406 Handle<Object> exec_state;
3407 if (!MakeExecutionState().ToHandle(&exec_state)) {
3408 return isolate_->factory()->undefined_value();
3411 Handle<Object> argv[] = { exec_state, data };
3412 return Execution::Call(
3415 Handle<Object>(isolate_->debug()->debug_context_->global_proxy(),
3422 static void StubMessageHandler2(const v8::Debug::Message& message) {
3423 // Simply ignore message.
3427 bool Debugger::StartAgent(const char* name, int port,
3428 bool wait_for_connection) {
3429 if (wait_for_connection) {
3430 // Suspend V8 if it is already running or set V8 to suspend whenever
3432 // Provide stub message handler; V8 auto-continues each suspend
3433 // when there is no message handler; we doesn't need it.
3434 // Once become suspended, V8 will stay so indefinitely long, until remote
3435 // debugger connects and issues "continue" command.
3436 Debugger::message_handler_ = StubMessageHandler2;
3437 v8::Debug::DebugBreak(reinterpret_cast<v8::Isolate*>(isolate_));
3440 if (agent_ == NULL) {
3441 agent_ = new DebuggerAgent(isolate_, name, port);
3448 void Debugger::StopAgent() {
3449 if (agent_ != NULL) {
3458 void Debugger::WaitForAgent() {
3460 agent_->WaitUntilListening();
3464 void Debugger::CallMessageDispatchHandler() {
3465 v8::Debug::DebugMessageDispatchHandler handler;
3467 LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3468 handler = Debugger::debug_message_dispatch_handler_;
3470 if (handler != NULL) {
3476 EnterDebugger::EnterDebugger(Isolate* isolate)
3477 : isolate_(isolate),
3478 prev_(isolate_->debug()->debugger_entry()),
3480 has_js_frames_(!it_.done()),
3482 Debug* debug = isolate_->debug();
3483 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT));
3484 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK));
3486 // Link recursive debugger entry.
3487 debug->set_debugger_entry(this);
3489 // Store the previous break id and frame id.
3490 break_id_ = debug->break_id();
3491 break_frame_id_ = debug->break_frame_id();
3493 // Create the new break info. If there is no JavaScript frames there is no
3495 if (has_js_frames_) {
3496 debug->NewBreak(it_.frame()->id());
3498 debug->NewBreak(StackFrame::NO_ID);
3501 // Make sure that debugger is loaded and enter the debugger context.
3502 load_failed_ = !debug->Load();
3503 if (!load_failed_) {
3504 // NOTE the member variable save which saves the previous context before
3506 isolate_->set_context(*debug->debug_context());
3511 EnterDebugger::~EnterDebugger() {
3512 Debug* debug = isolate_->debug();
3514 // Restore to the previous break state.
3515 debug->SetBreak(break_frame_id_, break_id_);
3517 // Check for leaving the debugger.
3518 if (!load_failed_ && prev_ == NULL) {
3519 // Clear mirror cache when leaving the debugger. Skip this if there is a
3520 // pending exception as clearing the mirror cache calls back into
3521 // JavaScript. This can happen if the v8::Debug::Call is used in which
3522 // case the exception should end up in the calling code.
3523 if (!isolate_->has_pending_exception()) {
3524 // Try to avoid any pending debug break breaking in the clear mirror
3525 // cache JavaScript code.
3526 if (isolate_->stack_guard()->IsDebugBreak()) {
3527 debug->set_interrupts_pending(DEBUGBREAK);
3528 isolate_->stack_guard()->Continue(DEBUGBREAK);
3530 debug->ClearMirrorCache();
3533 // Request preemption and debug break when leaving the last debugger entry
3534 // if any of these where recorded while debugging.
3535 if (debug->is_interrupt_pending(PREEMPT)) {
3536 // This re-scheduling of preemption is to avoid starvation in some
3537 // debugging scenarios.
3538 debug->clear_interrupt_pending(PREEMPT);
3539 isolate_->stack_guard()->Preempt();
3541 if (debug->is_interrupt_pending(DEBUGBREAK)) {
3542 debug->clear_interrupt_pending(DEBUGBREAK);
3543 isolate_->stack_guard()->DebugBreak();
3546 // If there are commands in the queue when leaving the debugger request
3547 // that these commands are processed.
3548 if (isolate_->debugger()->HasCommands()) {
3549 isolate_->stack_guard()->DebugCommand();
3552 // If leaving the debugger with the debugger no longer active unload it.
3553 if (!isolate_->debugger()->IsDebuggerActive()) {
3554 isolate_->debugger()->UnloadDebugger();
3558 // Leaving this debugger entry.
3559 debug->set_debugger_entry(prev_);
3563 MessageImpl MessageImpl::NewEvent(DebugEvent event,
3565 Handle<JSObject> exec_state,
3566 Handle<JSObject> event_data) {
3567 MessageImpl message(true, event, running,
3568 exec_state, event_data, Handle<String>(), NULL);
3573 MessageImpl MessageImpl::NewResponse(DebugEvent event,
3575 Handle<JSObject> exec_state,
3576 Handle<JSObject> event_data,
3577 Handle<String> response_json,
3578 v8::Debug::ClientData* client_data) {
3579 MessageImpl message(false, event, running,
3580 exec_state, event_data, response_json, client_data);
3585 MessageImpl::MessageImpl(bool is_event,
3588 Handle<JSObject> exec_state,
3589 Handle<JSObject> event_data,
3590 Handle<String> response_json,
3591 v8::Debug::ClientData* client_data)
3592 : is_event_(is_event),
3595 exec_state_(exec_state),
3596 event_data_(event_data),
3597 response_json_(response_json),
3598 client_data_(client_data) {}
3601 bool MessageImpl::IsEvent() const {
3606 bool MessageImpl::IsResponse() const {
3611 DebugEvent MessageImpl::GetEvent() const {
3616 bool MessageImpl::WillStartRunning() const {
3621 v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
3622 return v8::Utils::ToLocal(exec_state_);
3626 v8::Isolate* MessageImpl::GetIsolate() const {
3627 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
3631 v8::Handle<v8::Object> MessageImpl::GetEventData() const {
3632 return v8::Utils::ToLocal(event_data_);
3636 v8::Handle<v8::String> MessageImpl::GetJSON() const {
3637 Isolate* isolate = event_data_->GetIsolate();
3638 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
3641 // Call toJSONProtocol on the debug event object.
3642 Handle<Object> fun = Object::GetProperty(
3643 isolate, event_data_, "toJSONProtocol").ToHandleChecked();
3644 if (!fun->IsJSFunction()) {
3645 return v8::Handle<v8::String>();
3648 MaybeHandle<Object> maybe_json =
3649 Execution::TryCall(Handle<JSFunction>::cast(fun), event_data_, 0, NULL);
3650 Handle<Object> json;
3651 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
3652 return v8::Handle<v8::String>();
3654 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
3656 return v8::Utils::ToLocal(response_json_);
3661 v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
3662 Isolate* isolate = event_data_->GetIsolate();
3663 v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
3664 // Isolate::context() may be NULL when "script collected" event occures.
3665 ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected);
3670 v8::Debug::ClientData* MessageImpl::GetClientData() const {
3671 return client_data_;
3675 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
3676 Handle<JSObject> exec_state,
3677 Handle<JSObject> event_data,
3678 Handle<Object> callback_data,
3679 v8::Debug::ClientData* client_data)
3681 exec_state_(exec_state),
3682 event_data_(event_data),
3683 callback_data_(callback_data),
3684 client_data_(client_data) {}
3687 DebugEvent EventDetailsImpl::GetEvent() const {
3692 v8::Handle<v8::Object> EventDetailsImpl::GetExecutionState() const {
3693 return v8::Utils::ToLocal(exec_state_);
3697 v8::Handle<v8::Object> EventDetailsImpl::GetEventData() const {
3698 return v8::Utils::ToLocal(event_data_);
3702 v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const {
3703 return GetDebugEventContext(exec_state_->GetIsolate());
3707 v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const {
3708 return v8::Utils::ToLocal(callback_data_);
3712 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
3713 return client_data_;
3717 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
3718 client_data_(NULL) {
3722 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
3723 v8::Debug::ClientData* data)
3725 client_data_(data) {
3729 CommandMessage::~CommandMessage() {
3733 void CommandMessage::Dispose() {
3735 delete client_data_;
3736 client_data_ = NULL;
3740 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
3741 v8::Debug::ClientData* data) {
3742 return CommandMessage(command.Clone(), data);
3746 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
3748 messages_ = NewArray<CommandMessage>(size);
3752 CommandMessageQueue::~CommandMessageQueue() {
3753 while (!IsEmpty()) {
3754 CommandMessage m = Get();
3757 DeleteArray(messages_);
3761 CommandMessage CommandMessageQueue::Get() {
3763 int result = start_;
3764 start_ = (start_ + 1) % size_;
3765 return messages_[result];
3769 void CommandMessageQueue::Put(const CommandMessage& message) {
3770 if ((end_ + 1) % size_ == start_) {
3773 messages_[end_] = message;
3774 end_ = (end_ + 1) % size_;
3778 void CommandMessageQueue::Expand() {
3779 CommandMessageQueue new_queue(size_ * 2);
3780 while (!IsEmpty()) {
3781 new_queue.Put(Get());
3783 CommandMessage* array_to_free = messages_;
3785 new_queue.messages_ = array_to_free;
3786 // Make the new_queue empty so that it doesn't call Dispose on any messages.
3787 new_queue.start_ = new_queue.end_;
3788 // Automatic destructor called on new_queue, freeing array_to_free.
3792 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
3793 : logger_(logger), queue_(size) {}
3796 bool LockingCommandMessageQueue::IsEmpty() const {
3797 LockGuard<Mutex> lock_guard(&mutex_);
3798 return queue_.IsEmpty();
3802 CommandMessage LockingCommandMessageQueue::Get() {
3803 LockGuard<Mutex> lock_guard(&mutex_);
3804 CommandMessage result = queue_.Get();
3805 logger_->DebugEvent("Get", result.text());
3810 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
3811 LockGuard<Mutex> lock_guard(&mutex_);
3812 queue_.Put(message);
3813 logger_->DebugEvent("Put", message.text());
3817 void LockingCommandMessageQueue::Clear() {
3818 LockGuard<Mutex> lock_guard(&mutex_);
3823 MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
3824 : Thread("v8:MsgDispHelpr"),
3825 isolate_(isolate), sem_(0),
3826 already_signalled_(false) {
3830 void MessageDispatchHelperThread::Schedule() {
3832 LockGuard<Mutex> lock_guard(&mutex_);
3833 if (already_signalled_) {
3836 already_signalled_ = true;
3842 void MessageDispatchHelperThread::Run() {
3846 LockGuard<Mutex> lock_guard(&mutex_);
3847 already_signalled_ = false;
3850 Locker locker(reinterpret_cast<v8::Isolate*>(isolate_));
3851 isolate_->debugger()->CallMessageDispatchHandler();
3856 } } // namespace v8::internal