• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "api.h"
31 #include "arguments.h"
32 #include "bootstrapper.h"
33 #include "code-stubs.h"
34 #include "compilation-cache.h"
35 #include "compiler.h"
36 #include "debug.h"
37 #include "execution.h"
38 #include "global-handles.h"
39 #include "ic.h"
40 #include "ic-inl.h"
41 #include "natives.h"
42 #include "stub-cache.h"
43 #include "log.h"
44 
45 #include "../include/v8-debug.h"
46 
47 namespace v8 {
48 namespace internal {
49 
50 #ifdef ENABLE_DEBUGGER_SUPPORT
PrintLn(v8::Local<v8::Value> value)51 static void PrintLn(v8::Local<v8::Value> value) {
52   v8::Local<v8::String> s = value->ToString();
53   char* data = NewArray<char>(s->Length() + 1);
54   if (data == NULL) {
55     V8::FatalProcessOutOfMemory("PrintLn");
56     return;
57   }
58   s->WriteAscii(data);
59   PrintF("%s\n", data);
60   DeleteArray(data);
61 }
62 
63 
ComputeCallDebugBreak(int argc)64 static Handle<Code> ComputeCallDebugBreak(int argc) {
65   CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugBreak(argc), Code);
66 }
67 
68 
ComputeCallDebugPrepareStepIn(int argc)69 static Handle<Code> ComputeCallDebugPrepareStepIn(int argc) {
70   CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugPrepareStepIn(argc), Code);
71 }
72 
73 
BreakLocationIterator(Handle<DebugInfo> debug_info,BreakLocatorType type)74 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
75                                              BreakLocatorType type) {
76   debug_info_ = debug_info;
77   type_ = type;
78   // Get the stub early to avoid possible GC during iterations. We may need
79   // this stub to detect debugger calls generated from debugger statements.
80   debug_break_stub_ = RuntimeStub(Runtime::kDebugBreak, 0).GetCode();
81   reloc_iterator_ = NULL;
82   reloc_iterator_original_ = NULL;
83   Reset();  // Initialize the rest of the member variables.
84 }
85 
86 
~BreakLocationIterator()87 BreakLocationIterator::~BreakLocationIterator() {
88   ASSERT(reloc_iterator_ != NULL);
89   ASSERT(reloc_iterator_original_ != NULL);
90   delete reloc_iterator_;
91   delete reloc_iterator_original_;
92 }
93 
94 
Next()95 void BreakLocationIterator::Next() {
96   AssertNoAllocation nogc;
97   ASSERT(!RinfoDone());
98 
99   // Iterate through reloc info for code and original code stopping at each
100   // breakable code target.
101   bool first = break_point_ == -1;
102   while (!RinfoDone()) {
103     if (!first) RinfoNext();
104     first = false;
105     if (RinfoDone()) return;
106 
107     // Whenever a statement position or (plain) position is passed update the
108     // current value of these.
109     if (RelocInfo::IsPosition(rmode())) {
110       if (RelocInfo::IsStatementPosition(rmode())) {
111         statement_position_ =
112             rinfo()->data() - debug_info_->shared()->start_position();
113       }
114       // Always update the position as we don't want that to be before the
115       // statement position.
116       position_ = rinfo()->data() - debug_info_->shared()->start_position();
117       ASSERT(position_ >= 0);
118       ASSERT(statement_position_ >= 0);
119     }
120 
121     // Check for breakable code target. Look in the original code as setting
122     // break points can cause the code targets in the running (debugged) code to
123     // be of a different kind than in the original code.
124     if (RelocInfo::IsCodeTarget(rmode())) {
125       Address target = original_rinfo()->target_address();
126       Code* code = Code::GetCodeFromTargetAddress(target);
127       if (code->is_inline_cache_stub() || RelocInfo::IsConstructCall(rmode())) {
128         break_point_++;
129         return;
130       }
131       if (code->kind() == Code::STUB) {
132         if (IsDebuggerStatement()) {
133           break_point_++;
134           return;
135         }
136         if (type_ == ALL_BREAK_LOCATIONS) {
137           if (Debug::IsBreakStub(code)) {
138             break_point_++;
139             return;
140           }
141         } else {
142           ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
143           if (Debug::IsSourceBreakStub(code)) {
144             break_point_++;
145             return;
146           }
147         }
148       }
149     }
150 
151     // Check for break at return.
152     if (RelocInfo::IsJSReturn(rmode())) {
153       // Set the positions to the end of the function.
154       if (debug_info_->shared()->HasSourceCode()) {
155         position_ = debug_info_->shared()->end_position() -
156                     debug_info_->shared()->start_position();
157       } else {
158         position_ = 0;
159       }
160       statement_position_ = position_;
161       break_point_++;
162       return;
163     }
164   }
165 }
166 
167 
Next(int count)168 void BreakLocationIterator::Next(int count) {
169   while (count > 0) {
170     Next();
171     count--;
172   }
173 }
174 
175 
176 // Find the break point closest to the supplied address.
FindBreakLocationFromAddress(Address pc)177 void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
178   // Run through all break points to locate the one closest to the address.
179   int closest_break_point = 0;
180   int distance = kMaxInt;
181   while (!Done()) {
182     // Check if this break point is closer that what was previously found.
183     if (this->pc() < pc && pc - this->pc() < distance) {
184       closest_break_point = break_point();
185       distance = pc - this->pc();
186       // Check whether we can't get any closer.
187       if (distance == 0) break;
188     }
189     Next();
190   }
191 
192   // Move to the break point found.
193   Reset();
194   Next(closest_break_point);
195 }
196 
197 
198 // Find the break point closest to the supplied source position.
FindBreakLocationFromPosition(int position)199 void BreakLocationIterator::FindBreakLocationFromPosition(int position) {
200   // Run through all break points to locate the one closest to the source
201   // position.
202   int closest_break_point = 0;
203   int distance = kMaxInt;
204   while (!Done()) {
205     // Check if this break point is closer that what was previously found.
206     if (position <= statement_position() &&
207         statement_position() - position < distance) {
208       closest_break_point = break_point();
209       distance = statement_position() - position;
210       // Check whether we can't get any closer.
211       if (distance == 0) break;
212     }
213     Next();
214   }
215 
216   // Move to the break point found.
217   Reset();
218   Next(closest_break_point);
219 }
220 
221 
Reset()222 void BreakLocationIterator::Reset() {
223   // Create relocation iterators for the two code objects.
224   if (reloc_iterator_ != NULL) delete reloc_iterator_;
225   if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
226   reloc_iterator_ = new RelocIterator(debug_info_->code());
227   reloc_iterator_original_ = new RelocIterator(debug_info_->original_code());
228 
229   // Position at the first break point.
230   break_point_ = -1;
231   position_ = 1;
232   statement_position_ = 1;
233   Next();
234 }
235 
236 
Done() const237 bool BreakLocationIterator::Done() const {
238   return RinfoDone();
239 }
240 
241 
SetBreakPoint(Handle<Object> break_point_object)242 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
243   // If there is not already a real break point here patch code with debug
244   // break.
245   if (!HasBreakPoint()) {
246     SetDebugBreak();
247   }
248   ASSERT(IsDebugBreak() || IsDebuggerStatement());
249   // Set the break point information.
250   DebugInfo::SetBreakPoint(debug_info_, code_position(),
251                            position(), statement_position(),
252                            break_point_object);
253 }
254 
255 
ClearBreakPoint(Handle<Object> break_point_object)256 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
257   // Clear the break point information.
258   DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
259   // If there are no more break points here remove the debug break.
260   if (!HasBreakPoint()) {
261     ClearDebugBreak();
262     ASSERT(!IsDebugBreak());
263   }
264 }
265 
266 
SetOneShot()267 void BreakLocationIterator::SetOneShot() {
268   // Debugger statement always calls debugger. No need to modify it.
269   if (IsDebuggerStatement()) {
270     return;
271   }
272 
273   // If there is a real break point here no more to do.
274   if (HasBreakPoint()) {
275     ASSERT(IsDebugBreak());
276     return;
277   }
278 
279   // Patch code with debug break.
280   SetDebugBreak();
281 }
282 
283 
ClearOneShot()284 void BreakLocationIterator::ClearOneShot() {
285   // Debugger statement always calls debugger. No need to modify it.
286   if (IsDebuggerStatement()) {
287     return;
288   }
289 
290   // If there is a real break point here no more to do.
291   if (HasBreakPoint()) {
292     ASSERT(IsDebugBreak());
293     return;
294   }
295 
296   // Patch code removing debug break.
297   ClearDebugBreak();
298   ASSERT(!IsDebugBreak());
299 }
300 
301 
SetDebugBreak()302 void BreakLocationIterator::SetDebugBreak() {
303   // Debugger statement always calls debugger. No need to modify it.
304   if (IsDebuggerStatement()) {
305     return;
306   }
307 
308   // If there is already a break point here just return. This might happen if
309   // the same code is flooded with break points twice. Flooding the same
310   // function twice might happen when stepping in a function with an exception
311   // handler as the handler and the function is the same.
312   if (IsDebugBreak()) {
313     return;
314   }
315 
316   if (RelocInfo::IsJSReturn(rmode())) {
317     // Patch the frame exit code with a break point.
318     SetDebugBreakAtReturn();
319   } else {
320     // Patch the IC call.
321     SetDebugBreakAtIC();
322   }
323   ASSERT(IsDebugBreak());
324 }
325 
326 
ClearDebugBreak()327 void BreakLocationIterator::ClearDebugBreak() {
328   // Debugger statement always calls debugger. No need to modify it.
329   if (IsDebuggerStatement()) {
330     return;
331   }
332 
333   if (RelocInfo::IsJSReturn(rmode())) {
334     // Restore the frame exit code.
335     ClearDebugBreakAtReturn();
336   } else {
337     // Patch the IC call.
338     ClearDebugBreakAtIC();
339   }
340   ASSERT(!IsDebugBreak());
341 }
342 
343 
PrepareStepIn()344 void BreakLocationIterator::PrepareStepIn() {
345   HandleScope scope;
346 
347   // Step in can only be prepared if currently positioned on an IC call,
348   // construct call or CallFunction stub call.
349   Address target = rinfo()->target_address();
350   Handle<Code> code(Code::GetCodeFromTargetAddress(target));
351   if (code->is_call_stub()) {
352     // Step in through IC call is handled by the runtime system. Therefore make
353     // sure that the any current IC is cleared and the runtime system is
354     // called. If the executing code has a debug break at the location change
355     // the call in the original code as it is the code there that will be
356     // executed in place of the debug break call.
357     Handle<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count());
358     if (IsDebugBreak()) {
359       original_rinfo()->set_target_address(stub->entry());
360     } else {
361       rinfo()->set_target_address(stub->entry());
362     }
363   } else {
364 #ifdef DEBUG
365     // All the following stuff is needed only for assertion checks so the code
366     // is wrapped in ifdef.
367     Handle<Code> maybe_call_function_stub = code;
368     if (IsDebugBreak()) {
369       Address original_target = original_rinfo()->target_address();
370       maybe_call_function_stub =
371           Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
372     }
373     bool is_call_function_stub =
374         (maybe_call_function_stub->kind() == Code::STUB &&
375          maybe_call_function_stub->major_key() == CodeStub::CallFunction);
376 
377     // Step in through construct call requires no changes to the running code.
378     // Step in through getters/setters should already be prepared as well
379     // because caller of this function (Debug::PrepareStep) is expected to
380     // flood the top frame's function with one shot breakpoints.
381     // Step in through CallFunction stub should also be prepared by caller of
382     // this function (Debug::PrepareStep) which should flood target function
383     // with breakpoints.
384     ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub()
385            || is_call_function_stub);
386 #endif
387   }
388 }
389 
390 
391 // Check whether the break point is at a position which will exit the function.
IsExit() const392 bool BreakLocationIterator::IsExit() const {
393   return (RelocInfo::IsJSReturn(rmode()));
394 }
395 
396 
HasBreakPoint()397 bool BreakLocationIterator::HasBreakPoint() {
398   return debug_info_->HasBreakPoint(code_position());
399 }
400 
401 
402 // Check whether there is a debug break at the current position.
IsDebugBreak()403 bool BreakLocationIterator::IsDebugBreak() {
404   if (RelocInfo::IsJSReturn(rmode())) {
405     return IsDebugBreakAtReturn();
406   } else {
407     return Debug::IsDebugBreak(rinfo()->target_address());
408   }
409 }
410 
411 
SetDebugBreakAtIC()412 void BreakLocationIterator::SetDebugBreakAtIC() {
413   // Patch the original code with the current address as the current address
414   // might have changed by the inline caching since the code was copied.
415   original_rinfo()->set_target_address(rinfo()->target_address());
416 
417   RelocInfo::Mode mode = rmode();
418   if (RelocInfo::IsCodeTarget(mode)) {
419     Address target = rinfo()->target_address();
420     Handle<Code> code(Code::GetCodeFromTargetAddress(target));
421 
422     // Patch the code to invoke the builtin debug break function matching the
423     // calling convention used by the call site.
424     Handle<Code> dbgbrk_code(Debug::FindDebugBreak(code, mode));
425     rinfo()->set_target_address(dbgbrk_code->entry());
426 
427     // For stubs that refer back to an inlined version clear the cached map for
428     // the inlined case to always go through the IC. As long as the break point
429     // is set the patching performed by the runtime system will take place in
430     // the code copy and will therefore have no effect on the running code
431     // keeping it from using the inlined code.
432     if (code->is_keyed_load_stub()) KeyedLoadIC::ClearInlinedVersion(pc());
433     if (code->is_keyed_store_stub()) KeyedStoreIC::ClearInlinedVersion(pc());
434   }
435 }
436 
437 
ClearDebugBreakAtIC()438 void BreakLocationIterator::ClearDebugBreakAtIC() {
439   // Patch the code to the original invoke.
440   rinfo()->set_target_address(original_rinfo()->target_address());
441 
442   RelocInfo::Mode mode = rmode();
443   if (RelocInfo::IsCodeTarget(mode)) {
444     Address target = original_rinfo()->target_address();
445     Handle<Code> code(Code::GetCodeFromTargetAddress(target));
446 
447     // Restore the inlined version of keyed stores to get back to the
448     // fast case.  We need to patch back the keyed store because no
449     // patching happens when running normally.  For keyed loads, the
450     // map check will get patched back when running normally after ICs
451     // have been cleared at GC.
452     if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc());
453   }
454 }
455 
456 
IsDebuggerStatement()457 bool BreakLocationIterator::IsDebuggerStatement() {
458   if (RelocInfo::IsCodeTarget(rmode())) {
459     Address target = original_rinfo()->target_address();
460     Code* code = Code::GetCodeFromTargetAddress(target);
461     if (code->kind() == Code::STUB) {
462       CodeStub::Major major_key = code->major_key();
463       if (major_key == CodeStub::Runtime) {
464         return (*debug_break_stub_ == code);
465       }
466     }
467   }
468   return false;
469 }
470 
471 
BreakPointObjects()472 Object* BreakLocationIterator::BreakPointObjects() {
473   return debug_info_->GetBreakPointObjects(code_position());
474 }
475 
476 
477 // Clear out all the debug break code. This is ONLY supposed to be used when
478 // shutting down the debugger as it will leave the break point information in
479 // DebugInfo even though the code is patched back to the non break point state.
ClearAllDebugBreak()480 void BreakLocationIterator::ClearAllDebugBreak() {
481   while (!Done()) {
482     ClearDebugBreak();
483     Next();
484   }
485 }
486 
487 
RinfoDone() const488 bool BreakLocationIterator::RinfoDone() const {
489   ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
490   return reloc_iterator_->done();
491 }
492 
493 
RinfoNext()494 void BreakLocationIterator::RinfoNext() {
495   reloc_iterator_->next();
496   reloc_iterator_original_->next();
497 #ifdef DEBUG
498   ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
499   if (!reloc_iterator_->done()) {
500     ASSERT(rmode() == original_rmode());
501   }
502 #endif
503 }
504 
505 
506 bool Debug::has_break_points_ = false;
507 ScriptCache* Debug::script_cache_ = NULL;
508 DebugInfoListNode* Debug::debug_info_list_ = NULL;
509 
510 
511 // Threading support.
ThreadInit()512 void Debug::ThreadInit() {
513   thread_local_.break_count_ = 0;
514   thread_local_.break_id_ = 0;
515   thread_local_.break_frame_id_ = StackFrame::NO_ID;
516   thread_local_.last_step_action_ = StepNone;
517   thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
518   thread_local_.step_count_ = 0;
519   thread_local_.last_fp_ = 0;
520   thread_local_.step_into_fp_ = 0;
521   thread_local_.after_break_target_ = 0;
522   thread_local_.debugger_entry_ = NULL;
523   thread_local_.pending_interrupts_ = 0;
524 }
525 
526 
527 JSCallerSavedBuffer Debug::registers_;
528 Debug::ThreadLocal Debug::thread_local_;
529 
530 
ArchiveDebug(char * storage)531 char* Debug::ArchiveDebug(char* storage) {
532   char* to = storage;
533   memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
534   to += sizeof(ThreadLocal);
535   memcpy(to, reinterpret_cast<char*>(&registers_), sizeof(registers_));
536   ThreadInit();
537   ASSERT(to <= storage + ArchiveSpacePerThread());
538   return storage + ArchiveSpacePerThread();
539 }
540 
541 
RestoreDebug(char * storage)542 char* Debug::RestoreDebug(char* storage) {
543   char* from = storage;
544   memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
545   from += sizeof(ThreadLocal);
546   memcpy(reinterpret_cast<char*>(&registers_), from, sizeof(registers_));
547   ASSERT(from <= storage + ArchiveSpacePerThread());
548   return storage + ArchiveSpacePerThread();
549 }
550 
551 
ArchiveSpacePerThread()552 int Debug::ArchiveSpacePerThread() {
553   return sizeof(ThreadLocal) + sizeof(registers_);
554 }
555 
556 
557 // Default break enabled.
558 bool Debug::disable_break_ = false;
559 
560 // Default call debugger on uncaught exception.
561 bool Debug::break_on_exception_ = false;
562 bool Debug::break_on_uncaught_exception_ = true;
563 
564 Handle<Context> Debug::debug_context_ = Handle<Context>();
565 Code* Debug::debug_break_return_entry_ = NULL;
566 Code* Debug::debug_break_return_ = NULL;
567 
568 
Add(Handle<Script> script)569 void ScriptCache::Add(Handle<Script> script) {
570   // Create an entry in the hash map for the script.
571   int id = Smi::cast(script->id())->value();
572   HashMap::Entry* entry =
573       HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
574   if (entry->value != NULL) {
575     ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
576     return;
577   }
578 
579   // Globalize the script object, make it weak and use the location of the
580   // global handle as the value in the hash map.
581   Handle<Script> script_ =
582       Handle<Script>::cast((GlobalHandles::Create(*script)));
583   GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
584                           this, ScriptCache::HandleWeakScript);
585   entry->value = script_.location();
586 }
587 
588 
GetScripts()589 Handle<FixedArray> ScriptCache::GetScripts() {
590   Handle<FixedArray> instances = Factory::NewFixedArray(occupancy());
591   int count = 0;
592   for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
593     ASSERT(entry->value != NULL);
594     if (entry->value != NULL) {
595       instances->set(count, *reinterpret_cast<Script**>(entry->value));
596       count++;
597     }
598   }
599   return instances;
600 }
601 
602 
ProcessCollectedScripts()603 void ScriptCache::ProcessCollectedScripts() {
604   for (int i = 0; i < collected_scripts_.length(); i++) {
605     Debugger::OnScriptCollected(collected_scripts_[i]);
606   }
607   collected_scripts_.Clear();
608 }
609 
610 
Clear()611 void ScriptCache::Clear() {
612   // Iterate the script cache to get rid of all the weak handles.
613   for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
614     ASSERT(entry != NULL);
615     Object** location = reinterpret_cast<Object**>(entry->value);
616     ASSERT((*location)->IsScript());
617     GlobalHandles::ClearWeakness(location);
618     GlobalHandles::Destroy(location);
619   }
620   // Clear the content of the hash map.
621   HashMap::Clear();
622 }
623 
624 
HandleWeakScript(v8::Persistent<v8::Value> obj,void * data)625 void ScriptCache::HandleWeakScript(v8::Persistent<v8::Value> obj, void* data) {
626   ScriptCache* script_cache = reinterpret_cast<ScriptCache*>(data);
627   // Find the location of the global handle.
628   Script** location =
629       reinterpret_cast<Script**>(Utils::OpenHandle(*obj).location());
630   ASSERT((*location)->IsScript());
631 
632   // Remove the entry from the cache.
633   int id = Smi::cast((*location)->id())->value();
634   script_cache->Remove(reinterpret_cast<void*>(id), Hash(id));
635   script_cache->collected_scripts_.Add(id);
636 
637   // Clear the weak handle.
638   obj.Dispose();
639   obj.Clear();
640 }
641 
642 
Setup(bool create_heap_objects)643 void Debug::Setup(bool create_heap_objects) {
644   ThreadInit();
645   if (create_heap_objects) {
646     // Get code to handle entry to debug break on return.
647     debug_break_return_entry_ =
648         Builtins::builtin(Builtins::Return_DebugBreakEntry);
649     ASSERT(debug_break_return_entry_->IsCode());
650 
651     // Get code to handle debug break on return.
652     debug_break_return_ =
653         Builtins::builtin(Builtins::Return_DebugBreak);
654     ASSERT(debug_break_return_->IsCode());
655   }
656 }
657 
658 
HandleWeakDebugInfo(v8::Persistent<v8::Value> obj,void * data)659 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) {
660   DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
661   RemoveDebugInfo(node->debug_info());
662 #ifdef DEBUG
663   node = Debug::debug_info_list_;
664   while (node != NULL) {
665     ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
666     node = node->next();
667   }
668 #endif
669 }
670 
671 
DebugInfoListNode(DebugInfo * debug_info)672 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
673   // Globalize the request debug info object and make it weak.
674   debug_info_ = Handle<DebugInfo>::cast((GlobalHandles::Create(debug_info)));
675   GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
676                           this, Debug::HandleWeakDebugInfo);
677 }
678 
679 
~DebugInfoListNode()680 DebugInfoListNode::~DebugInfoListNode() {
681   GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
682 }
683 
684 
CompileDebuggerScript(int index)685 bool Debug::CompileDebuggerScript(int index) {
686   HandleScope scope;
687 
688   // Bail out if the index is invalid.
689   if (index == -1) {
690     return false;
691   }
692 
693   // Find source and name for the requested script.
694   Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
695   Vector<const char> name = Natives::GetScriptName(index);
696   Handle<String> script_name = Factory::NewStringFromAscii(name);
697 
698   // Compile the script.
699   bool allow_natives_syntax = FLAG_allow_natives_syntax;
700   FLAG_allow_natives_syntax = true;
701   Handle<JSFunction> boilerplate;
702   boilerplate = Compiler::Compile(source_code, script_name, 0, 0, NULL, NULL);
703   FLAG_allow_natives_syntax = allow_natives_syntax;
704 
705   // Silently ignore stack overflows during compilation.
706   if (boilerplate.is_null()) {
707     ASSERT(Top::has_pending_exception());
708     Top::clear_pending_exception();
709     return false;
710   }
711 
712   // Execute the boilerplate function in the debugger context.
713   Handle<Context> context = Top::global_context();
714   bool caught_exception = false;
715   Handle<JSFunction> function =
716       Factory::NewFunctionFromBoilerplate(boilerplate, context);
717   Handle<Object> result =
718       Execution::TryCall(function, Handle<Object>(context->global()),
719                          0, NULL, &caught_exception);
720 
721   // Check for caught exceptions.
722   if (caught_exception) {
723     Handle<Object> message = MessageHandler::MakeMessageObject(
724         "error_loading_debugger", NULL, Vector<Handle<Object> >::empty(),
725         Handle<String>());
726     MessageHandler::ReportMessage(NULL, message);
727     return false;
728   }
729 
730   // Mark this script as native and return successfully.
731   Handle<Script> script(Script::cast(function->shared()->script()));
732   script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
733   return true;
734 }
735 
736 
Load()737 bool Debug::Load() {
738   // Return if debugger is already loaded.
739   if (IsLoaded()) return true;
740 
741   // Bail out if we're already in the process of compiling the native
742   // JavaScript source code for the debugger.
743   if (Debugger::compiling_natives() || Debugger::is_loading_debugger())
744     return false;
745   Debugger::set_loading_debugger(true);
746 
747   // Disable breakpoints and interrupts while compiling and running the
748   // debugger scripts including the context creation code.
749   DisableBreak disable(true);
750   PostponeInterruptsScope postpone;
751 
752   // Create the debugger context.
753   HandleScope scope;
754   Handle<Context> context =
755       Bootstrapper::CreateEnvironment(Handle<Object>::null(),
756                                       v8::Handle<ObjectTemplate>(),
757                                       NULL);
758 
759   // Use the debugger context.
760   SaveContext save;
761   Top::set_context(*context);
762 
763   // Expose the builtins object in the debugger context.
764   Handle<String> key = Factory::LookupAsciiSymbol("builtins");
765   Handle<GlobalObject> global = Handle<GlobalObject>(context->global());
766   SetProperty(global, key, Handle<Object>(global->builtins()), NONE);
767 
768   // Compile the JavaScript for the debugger in the debugger context.
769   Debugger::set_compiling_natives(true);
770   bool caught_exception =
771       !CompileDebuggerScript(Natives::GetIndex("mirror")) ||
772       !CompileDebuggerScript(Natives::GetIndex("debug"));
773   Debugger::set_compiling_natives(false);
774 
775   // Make sure we mark the debugger as not loading before we might
776   // return.
777   Debugger::set_loading_debugger(false);
778 
779   // Check for caught exceptions.
780   if (caught_exception) return false;
781 
782   // Debugger loaded.
783   debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
784 
785   return true;
786 }
787 
788 
Unload()789 void Debug::Unload() {
790   // Return debugger is not loaded.
791   if (!IsLoaded()) {
792     return;
793   }
794 
795   // Clear the script cache.
796   DestroyScriptCache();
797 
798   // Clear debugger context global handle.
799   GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
800   debug_context_ = Handle<Context>();
801 }
802 
803 
804 // Set the flag indicating that preemption happened during debugging.
PreemptionWhileInDebugger()805 void Debug::PreemptionWhileInDebugger() {
806   ASSERT(InDebugger());
807   Debug::set_interrupts_pending(PREEMPT);
808 }
809 
810 
Iterate(ObjectVisitor * v)811 void Debug::Iterate(ObjectVisitor* v) {
812   v->VisitPointer(bit_cast<Object**, Code**>(&(debug_break_return_entry_)));
813   v->VisitPointer(bit_cast<Object**, Code**>(&(debug_break_return_)));
814 }
815 
816 
Break(Arguments args)817 Object* Debug::Break(Arguments args) {
818   HandleScope scope;
819   ASSERT(args.length() == 0);
820 
821   // Get the top-most JavaScript frame.
822   JavaScriptFrameIterator it;
823   JavaScriptFrame* frame = it.frame();
824 
825   // Just continue if breaks are disabled or debugger cannot be loaded.
826   if (disable_break() || !Load()) {
827     SetAfterBreakTarget(frame);
828     return Heap::undefined_value();
829   }
830 
831   // Enter the debugger.
832   EnterDebugger debugger;
833   if (debugger.FailedToEnter()) {
834     return Heap::undefined_value();
835   }
836 
837   // Postpone interrupt during breakpoint processing.
838   PostponeInterruptsScope postpone;
839 
840   // Get the debug info (create it if it does not exist).
841   Handle<SharedFunctionInfo> shared =
842       Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
843   Handle<DebugInfo> debug_info = GetDebugInfo(shared);
844 
845   // Find the break point where execution has stopped.
846   BreakLocationIterator break_location_iterator(debug_info,
847                                                 ALL_BREAK_LOCATIONS);
848   break_location_iterator.FindBreakLocationFromAddress(frame->pc());
849 
850   // Check whether step next reached a new statement.
851   if (!StepNextContinue(&break_location_iterator, frame)) {
852     // Decrease steps left if performing multiple steps.
853     if (thread_local_.step_count_ > 0) {
854       thread_local_.step_count_--;
855     }
856   }
857 
858   // If there is one or more real break points check whether any of these are
859   // triggered.
860   Handle<Object> break_points_hit(Heap::undefined_value());
861   if (break_location_iterator.HasBreakPoint()) {
862     Handle<Object> break_point_objects =
863         Handle<Object>(break_location_iterator.BreakPointObjects());
864     break_points_hit = CheckBreakPoints(break_point_objects);
865   }
866 
867   // Notify debugger if a real break point is triggered or if performing single
868   // stepping with no more steps to perform. Otherwise do another step.
869   if (!break_points_hit->IsUndefined() ||
870     (thread_local_.last_step_action_ != StepNone &&
871      thread_local_.step_count_ == 0)) {
872     // Clear all current stepping setup.
873     ClearStepping();
874 
875     // Notify the debug event listeners.
876     Debugger::OnDebugBreak(break_points_hit, false);
877   } else if (thread_local_.last_step_action_ != StepNone) {
878     // Hold on to last step action as it is cleared by the call to
879     // ClearStepping.
880     StepAction step_action = thread_local_.last_step_action_;
881     int step_count = thread_local_.step_count_;
882 
883     // Clear all current stepping setup.
884     ClearStepping();
885 
886     // Set up for the remaining steps.
887     PrepareStep(step_action, step_count);
888   }
889 
890   // Install jump to the call address which was overwritten.
891   SetAfterBreakTarget(frame);
892 
893   return Heap::undefined_value();
894 }
895 
896 
897 // Check the break point objects for whether one or more are actually
898 // triggered. This function returns a JSArray with the break point objects
899 // which is triggered.
CheckBreakPoints(Handle<Object> break_point_objects)900 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
901   int break_points_hit_count = 0;
902   Handle<JSArray> break_points_hit = Factory::NewJSArray(1);
903 
904   // If there are multiple break points they are in a FixedArray.
905   ASSERT(!break_point_objects->IsUndefined());
906   if (break_point_objects->IsFixedArray()) {
907     Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
908     for (int i = 0; i < array->length(); i++) {
909       Handle<Object> o(array->get(i));
910       if (CheckBreakPoint(o)) {
911         break_points_hit->SetElement(break_points_hit_count++, *o);
912       }
913     }
914   } else {
915     if (CheckBreakPoint(break_point_objects)) {
916       break_points_hit->SetElement(break_points_hit_count++,
917                                    *break_point_objects);
918     }
919   }
920 
921   // Return undefined if no break points where triggered.
922   if (break_points_hit_count == 0) {
923     return Factory::undefined_value();
924   }
925   return break_points_hit;
926 }
927 
928 
929 // Check whether a single break point object is triggered.
CheckBreakPoint(Handle<Object> break_point_object)930 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
931   HandleScope scope;
932 
933   // Ignore check if break point object is not a JSObject.
934   if (!break_point_object->IsJSObject()) return true;
935 
936   // Get the function CheckBreakPoint (defined in debug.js).
937   Handle<JSFunction> check_break_point =
938     Handle<JSFunction>(JSFunction::cast(
939       debug_context()->global()->GetProperty(
940           *Factory::LookupAsciiSymbol("IsBreakPointTriggered"))));
941 
942   // Get the break id as an object.
943   Handle<Object> break_id = Factory::NewNumberFromInt(Debug::break_id());
944 
945   // Call HandleBreakPointx.
946   bool caught_exception = false;
947   const int argc = 2;
948   Object** argv[argc] = {
949     break_id.location(),
950     reinterpret_cast<Object**>(break_point_object.location())
951   };
952   Handle<Object> result = Execution::TryCall(check_break_point,
953                                              Top::builtins(), argc, argv,
954                                              &caught_exception);
955 
956   // If exception or non boolean result handle as not triggered
957   if (caught_exception || !result->IsBoolean()) {
958     return false;
959   }
960 
961   // Return whether the break point is triggered.
962   return *result == Heap::true_value();
963 }
964 
965 
966 // Check whether the function has debug information.
HasDebugInfo(Handle<SharedFunctionInfo> shared)967 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
968   return !shared->debug_info()->IsUndefined();
969 }
970 
971 
972 // Return the debug info for this function. EnsureDebugInfo must be called
973 // prior to ensure the debug info has been generated for shared.
GetDebugInfo(Handle<SharedFunctionInfo> shared)974 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
975   ASSERT(HasDebugInfo(shared));
976   return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
977 }
978 
979 
SetBreakPoint(Handle<SharedFunctionInfo> shared,int source_position,Handle<Object> break_point_object)980 void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
981                           int source_position,
982                           Handle<Object> break_point_object) {
983   HandleScope scope;
984 
985   if (!EnsureDebugInfo(shared)) {
986     // Return if retrieving debug info failed.
987     return;
988   }
989 
990   Handle<DebugInfo> debug_info = GetDebugInfo(shared);
991   // Source positions starts with zero.
992   ASSERT(source_position >= 0);
993 
994   // Find the break point and change it.
995   BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
996   it.FindBreakLocationFromPosition(source_position);
997   it.SetBreakPoint(break_point_object);
998 
999   // At least one active break point now.
1000   ASSERT(debug_info->GetBreakPointCount() > 0);
1001 }
1002 
1003 
ClearBreakPoint(Handle<Object> break_point_object)1004 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1005   HandleScope scope;
1006 
1007   DebugInfoListNode* node = debug_info_list_;
1008   while (node != NULL) {
1009     Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
1010                                                    break_point_object);
1011     if (!result->IsUndefined()) {
1012       // Get information in the break point.
1013       BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
1014       Handle<DebugInfo> debug_info = node->debug_info();
1015       Handle<SharedFunctionInfo> shared(debug_info->shared());
1016       int source_position =  break_point_info->statement_position()->value();
1017 
1018       // Source positions starts with zero.
1019       ASSERT(source_position >= 0);
1020 
1021       // Find the break point and clear it.
1022       BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1023       it.FindBreakLocationFromPosition(source_position);
1024       it.ClearBreakPoint(break_point_object);
1025 
1026       // If there are no more break points left remove the debug info for this
1027       // function.
1028       if (debug_info->GetBreakPointCount() == 0) {
1029         RemoveDebugInfo(debug_info);
1030       }
1031 
1032       return;
1033     }
1034     node = node->next();
1035   }
1036 }
1037 
1038 
ClearAllBreakPoints()1039 void Debug::ClearAllBreakPoints() {
1040   DebugInfoListNode* node = debug_info_list_;
1041   while (node != NULL) {
1042     // Remove all debug break code.
1043     BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1044     it.ClearAllDebugBreak();
1045     node = node->next();
1046   }
1047 
1048   // Remove all debug info.
1049   while (debug_info_list_ != NULL) {
1050     RemoveDebugInfo(debug_info_list_->debug_info());
1051   }
1052 }
1053 
1054 
FloodWithOneShot(Handle<SharedFunctionInfo> shared)1055 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) {
1056   // Make sure the function has setup the debug info.
1057   if (!EnsureDebugInfo(shared)) {
1058     // Return if we failed to retrieve the debug info.
1059     return;
1060   }
1061 
1062   // Flood the function with break points.
1063   BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
1064   while (!it.Done()) {
1065     it.SetOneShot();
1066     it.Next();
1067   }
1068 }
1069 
1070 
FloodHandlerWithOneShot()1071 void Debug::FloodHandlerWithOneShot() {
1072   // Iterate through the JavaScript stack looking for handlers.
1073   StackFrame::Id id = break_frame_id();
1074   if (id == StackFrame::NO_ID) {
1075     // If there is no JavaScript stack don't do anything.
1076     return;
1077   }
1078   for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) {
1079     JavaScriptFrame* frame = it.frame();
1080     if (frame->HasHandler()) {
1081       Handle<SharedFunctionInfo> shared =
1082           Handle<SharedFunctionInfo>(
1083               JSFunction::cast(frame->function())->shared());
1084       // Flood the function with the catch block with break points
1085       FloodWithOneShot(shared);
1086       return;
1087     }
1088   }
1089 }
1090 
1091 
ChangeBreakOnException(ExceptionBreakType type,bool enable)1092 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
1093   if (type == BreakUncaughtException) {
1094     break_on_uncaught_exception_ = enable;
1095   } else {
1096     break_on_exception_ = enable;
1097   }
1098 }
1099 
1100 
PrepareStep(StepAction step_action,int step_count)1101 void Debug::PrepareStep(StepAction step_action, int step_count) {
1102   HandleScope scope;
1103   ASSERT(Debug::InDebugger());
1104 
1105   // Remember this step action and count.
1106   thread_local_.last_step_action_ = step_action;
1107   thread_local_.step_count_ = step_count;
1108 
1109   // Get the frame where the execution has stopped and skip the debug frame if
1110   // any. The debug frame will only be present if execution was stopped due to
1111   // hitting a break point. In other situations (e.g. unhandled exception) the
1112   // debug frame is not present.
1113   StackFrame::Id id = break_frame_id();
1114   if (id == StackFrame::NO_ID) {
1115     // If there is no JavaScript stack don't do anything.
1116     return;
1117   }
1118   JavaScriptFrameIterator frames_it(id);
1119   JavaScriptFrame* frame = frames_it.frame();
1120 
1121   // First of all ensure there is one-shot break points in the top handler
1122   // if any.
1123   FloodHandlerWithOneShot();
1124 
1125   // If the function on the top frame is unresolved perform step out. This will
1126   // be the case when calling unknown functions and having the debugger stopped
1127   // in an unhandled exception.
1128   if (!frame->function()->IsJSFunction()) {
1129     // Step out: Find the calling JavaScript frame and flood it with
1130     // breakpoints.
1131     frames_it.Advance();
1132     // Fill the function to return to with one-shot break points.
1133     JSFunction* function = JSFunction::cast(frames_it.frame()->function());
1134     FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
1135     return;
1136   }
1137 
1138   // Get the debug info (create it if it does not exist).
1139   Handle<SharedFunctionInfo> shared =
1140       Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
1141   if (!EnsureDebugInfo(shared)) {
1142     // Return if ensuring debug info failed.
1143     return;
1144   }
1145   Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1146 
1147   // Find the break location where execution has stopped.
1148   BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1149   it.FindBreakLocationFromAddress(frame->pc());
1150 
1151   // Compute whether or not the target is a call target.
1152   bool is_call_target = false;
1153   bool is_load_or_store = false;
1154   bool is_inline_cache_stub = false;
1155   Handle<Code> call_function_stub;
1156   if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1157     Address target = it.rinfo()->target_address();
1158     Code* code = Code::GetCodeFromTargetAddress(target);
1159     if (code->is_call_stub()) {
1160       is_call_target = true;
1161     }
1162     if (code->is_inline_cache_stub()) {
1163       is_inline_cache_stub = true;
1164       is_load_or_store = !is_call_target;
1165     }
1166 
1167     // Check if target code is CallFunction stub.
1168     Code* maybe_call_function_stub = code;
1169     // If there is a breakpoint at this line look at the original code to
1170     // check if it is a CallFunction stub.
1171     if (it.IsDebugBreak()) {
1172       Address original_target = it.original_rinfo()->target_address();
1173       maybe_call_function_stub =
1174           Code::GetCodeFromTargetAddress(original_target);
1175     }
1176     if (maybe_call_function_stub->kind() == Code::STUB &&
1177         maybe_call_function_stub->major_key() == CodeStub::CallFunction) {
1178       // Save reference to the code as we may need it to find out arguments
1179       // count for 'step in' later.
1180       call_function_stub = Handle<Code>(maybe_call_function_stub);
1181     }
1182   }
1183 
1184   // If this is the last break code target step out is the only possibility.
1185   if (it.IsExit() || step_action == StepOut) {
1186     // Step out: If there is a JavaScript caller frame, we need to
1187     // flood it with breakpoints.
1188     frames_it.Advance();
1189     if (!frames_it.done()) {
1190       // Fill the function to return to with one-shot break points.
1191       JSFunction* function = JSFunction::cast(frames_it.frame()->function());
1192       FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
1193     }
1194   } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
1195                !call_function_stub.is_null())
1196              || step_action == StepNext || step_action == StepMin) {
1197     // Step next or step min.
1198 
1199     // Fill the current function with one-shot break points.
1200     FloodWithOneShot(shared);
1201 
1202     // Remember source position and frame to handle step next.
1203     thread_local_.last_statement_position_ =
1204         debug_info->code()->SourceStatementPosition(frame->pc());
1205     thread_local_.last_fp_ = frame->fp();
1206   } else {
1207     // If it's CallFunction stub ensure target function is compiled and flood
1208     // it with one shot breakpoints.
1209     if (!call_function_stub.is_null()) {
1210       // Find out number of arguments from the stub minor key.
1211       // Reverse lookup required as the minor key cannot be retrieved
1212       // from the code object.
1213       Handle<Object> obj(
1214           Heap::code_stubs()->SlowReverseLookup(*call_function_stub));
1215       ASSERT(*obj != Heap::undefined_value());
1216       ASSERT(obj->IsSmi());
1217       // Get the STUB key and extract major and minor key.
1218       uint32_t key = Smi::cast(*obj)->value();
1219       // Argc in the stub is the number of arguments passed - not the
1220       // expected arguments of the called function.
1221       int call_function_arg_count = CodeStub::MinorKeyFromKey(key);
1222       ASSERT(call_function_stub->major_key() ==
1223              CodeStub::MajorKeyFromKey(key));
1224 
1225       // Find target function on the expression stack.
1226       // Expression stack lools like this (top to bottom):
1227       // argN
1228       // ...
1229       // arg0
1230       // Receiver
1231       // Function to call
1232       int expressions_count = frame->ComputeExpressionsCount();
1233       ASSERT(expressions_count - 2 - call_function_arg_count >= 0);
1234       Object* fun = frame->GetExpression(
1235           expressions_count - 2 - call_function_arg_count);
1236       if (fun->IsJSFunction()) {
1237         Handle<JSFunction> js_function(JSFunction::cast(fun));
1238         // Don't step into builtins.
1239         if (!js_function->IsBuiltin()) {
1240           // It will also compile target function if it's not compiled yet.
1241           FloodWithOneShot(Handle<SharedFunctionInfo>(js_function->shared()));
1242         }
1243       }
1244     }
1245 
1246     // Fill the current function with one-shot break points even for step in on
1247     // a call target as the function called might be a native function for
1248     // which step in will not stop. It also prepares for stepping in
1249     // getters/setters.
1250     FloodWithOneShot(shared);
1251 
1252     if (is_load_or_store) {
1253       // Remember source position and frame to handle step in getter/setter. If
1254       // there is a custom getter/setter it will be handled in
1255       // Object::Get/SetPropertyWithCallback, otherwise the step action will be
1256       // propagated on the next Debug::Break.
1257       thread_local_.last_statement_position_ =
1258           debug_info->code()->SourceStatementPosition(frame->pc());
1259       thread_local_.last_fp_ = frame->fp();
1260     }
1261 
1262     // Step in or Step in min
1263     it.PrepareStepIn();
1264     ActivateStepIn(frame);
1265   }
1266 }
1267 
1268 
1269 // Check whether the current debug break should be reported to the debugger. It
1270 // is used to have step next and step in only report break back to the debugger
1271 // if on a different frame or in a different statement. In some situations
1272 // there will be several break points in the same statement when the code is
1273 // flooded with one-shot break points. This function helps to perform several
1274 // steps before reporting break back to the debugger.
StepNextContinue(BreakLocationIterator * break_location_iterator,JavaScriptFrame * frame)1275 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1276                              JavaScriptFrame* frame) {
1277   // If the step last action was step next or step in make sure that a new
1278   // statement is hit.
1279   if (thread_local_.last_step_action_ == StepNext ||
1280       thread_local_.last_step_action_ == StepIn) {
1281     // Never continue if returning from function.
1282     if (break_location_iterator->IsExit()) return false;
1283 
1284     // Continue if we are still on the same frame and in the same statement.
1285     int current_statement_position =
1286         break_location_iterator->code()->SourceStatementPosition(frame->pc());
1287     return thread_local_.last_fp_ == frame->fp() &&
1288         thread_local_.last_statement_position_ == current_statement_position;
1289   }
1290 
1291   // No step next action - don't continue.
1292   return false;
1293 }
1294 
1295 
1296 // Check whether the code object at the specified address is a debug break code
1297 // object.
IsDebugBreak(Address addr)1298 bool Debug::IsDebugBreak(Address addr) {
1299   Code* code = Code::GetCodeFromTargetAddress(addr);
1300   return code->ic_state() == DEBUG_BREAK;
1301 }
1302 
1303 
1304 // Check whether a code stub with the specified major key is a possible break
1305 // point location when looking for source break locations.
IsSourceBreakStub(Code * code)1306 bool Debug::IsSourceBreakStub(Code* code) {
1307   CodeStub::Major major_key = code->major_key();
1308   return major_key == CodeStub::CallFunction;
1309 }
1310 
1311 
1312 // Check whether a code stub with the specified major key is a possible break
1313 // location.
IsBreakStub(Code * code)1314 bool Debug::IsBreakStub(Code* code) {
1315   CodeStub::Major major_key = code->major_key();
1316   return major_key == CodeStub::CallFunction ||
1317          major_key == CodeStub::StackCheck;
1318 }
1319 
1320 
1321 // Find the builtin to use for invoking the debug break
FindDebugBreak(Handle<Code> code,RelocInfo::Mode mode)1322 Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
1323   // Find the builtin debug break function matching the calling convention
1324   // used by the call site.
1325   if (code->is_inline_cache_stub()) {
1326     if (code->is_call_stub()) {
1327       return ComputeCallDebugBreak(code->arguments_count());
1328     }
1329     if (code->is_load_stub()) {
1330       return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak));
1331     }
1332     if (code->is_store_stub()) {
1333       return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak));
1334     }
1335     if (code->is_keyed_load_stub()) {
1336       Handle<Code> result =
1337           Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
1338       return result;
1339     }
1340     if (code->is_keyed_store_stub()) {
1341       Handle<Code> result =
1342           Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
1343       return result;
1344     }
1345   }
1346   if (RelocInfo::IsConstructCall(mode)) {
1347     Handle<Code> result =
1348         Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak));
1349     return result;
1350   }
1351   if (code->kind() == Code::STUB) {
1352     ASSERT(code->major_key() == CodeStub::CallFunction ||
1353            code->major_key() == CodeStub::StackCheck);
1354     Handle<Code> result =
1355         Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
1356     return result;
1357   }
1358 
1359   UNREACHABLE();
1360   return Handle<Code>::null();
1361 }
1362 
1363 
1364 // Simple function for returning the source positions for active break points.
GetSourceBreakLocations(Handle<SharedFunctionInfo> shared)1365 Handle<Object> Debug::GetSourceBreakLocations(
1366     Handle<SharedFunctionInfo> shared) {
1367   if (!HasDebugInfo(shared)) return Handle<Object>(Heap::undefined_value());
1368   Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1369   if (debug_info->GetBreakPointCount() == 0) {
1370     return Handle<Object>(Heap::undefined_value());
1371   }
1372   Handle<FixedArray> locations =
1373       Factory::NewFixedArray(debug_info->GetBreakPointCount());
1374   int count = 0;
1375   for (int i = 0; i < debug_info->break_points()->length(); i++) {
1376     if (!debug_info->break_points()->get(i)->IsUndefined()) {
1377       BreakPointInfo* break_point_info =
1378           BreakPointInfo::cast(debug_info->break_points()->get(i));
1379       if (break_point_info->GetBreakPointCount() > 0) {
1380         locations->set(count++, break_point_info->statement_position());
1381       }
1382     }
1383   }
1384   return locations;
1385 }
1386 
1387 
NewBreak(StackFrame::Id break_frame_id)1388 void Debug::NewBreak(StackFrame::Id break_frame_id) {
1389   thread_local_.break_frame_id_ = break_frame_id;
1390   thread_local_.break_id_ = ++thread_local_.break_count_;
1391 }
1392 
1393 
SetBreak(StackFrame::Id break_frame_id,int break_id)1394 void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) {
1395   thread_local_.break_frame_id_ = break_frame_id;
1396   thread_local_.break_id_ = break_id;
1397 }
1398 
1399 
1400 // Handle stepping into a function.
HandleStepIn(Handle<JSFunction> function,Handle<Object> holder,Address fp,bool is_constructor)1401 void Debug::HandleStepIn(Handle<JSFunction> function,
1402                          Handle<Object> holder,
1403                          Address fp,
1404                          bool is_constructor) {
1405   // If the frame pointer is not supplied by the caller find it.
1406   if (fp == 0) {
1407     StackFrameIterator it;
1408     it.Advance();
1409     // For constructor functions skip another frame.
1410     if (is_constructor) {
1411       ASSERT(it.frame()->is_construct());
1412       it.Advance();
1413     }
1414     fp = it.frame()->fp();
1415   }
1416 
1417   // Flood the function with one-shot break points if it is called from where
1418   // step into was requested.
1419   if (fp == Debug::step_in_fp()) {
1420     // Don't allow step into functions in the native context.
1421     if (!function->IsBuiltin()) {
1422       if (function->shared()->code() ==
1423           Builtins::builtin(Builtins::FunctionApply) ||
1424           function->shared()->code() ==
1425           Builtins::builtin(Builtins::FunctionCall)) {
1426         // Handle function.apply and function.call separately to flood the
1427         // function to be called and not the code for Builtins::FunctionApply or
1428         // Builtins::FunctionCall. The receiver of call/apply is the target
1429         // function.
1430         if (!holder.is_null() && holder->IsJSFunction() &&
1431             !JSFunction::cast(*holder)->IsBuiltin()) {
1432           Handle<SharedFunctionInfo> shared_info(
1433               JSFunction::cast(*holder)->shared());
1434           Debug::FloodWithOneShot(shared_info);
1435         }
1436       } else {
1437         Debug::FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
1438       }
1439     }
1440   }
1441 }
1442 
1443 
ClearStepping()1444 void Debug::ClearStepping() {
1445   // Clear the various stepping setup.
1446   ClearOneShot();
1447   ClearStepIn();
1448   ClearStepNext();
1449 
1450   // Clear multiple step counter.
1451   thread_local_.step_count_ = 0;
1452 }
1453 
1454 // Clears all the one-shot break points that are currently set. Normally this
1455 // function is called each time a break point is hit as one shot break points
1456 // are used to support stepping.
ClearOneShot()1457 void Debug::ClearOneShot() {
1458   // The current implementation just runs through all the breakpoints. When the
1459   // last break point for a function is removed that function is automatically
1460   // removed from the list.
1461 
1462   DebugInfoListNode* node = debug_info_list_;
1463   while (node != NULL) {
1464     BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1465     while (!it.Done()) {
1466       it.ClearOneShot();
1467       it.Next();
1468     }
1469     node = node->next();
1470   }
1471 }
1472 
1473 
ActivateStepIn(StackFrame * frame)1474 void Debug::ActivateStepIn(StackFrame* frame) {
1475   thread_local_.step_into_fp_ = frame->fp();
1476 }
1477 
1478 
ClearStepIn()1479 void Debug::ClearStepIn() {
1480   thread_local_.step_into_fp_ = 0;
1481 }
1482 
1483 
ClearStepNext()1484 void Debug::ClearStepNext() {
1485   thread_local_.last_step_action_ = StepNone;
1486   thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1487   thread_local_.last_fp_ = 0;
1488 }
1489 
1490 
EnsureCompiled(Handle<SharedFunctionInfo> shared)1491 bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
1492   if (shared->is_compiled()) return true;
1493   return CompileLazyShared(shared, CLEAR_EXCEPTION, 0);
1494 }
1495 
1496 
1497 // Ensures the debug information is present for shared.
EnsureDebugInfo(Handle<SharedFunctionInfo> shared)1498 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
1499   // Return if we already have the debug info for shared.
1500   if (HasDebugInfo(shared)) return true;
1501 
1502   // Ensure shared in compiled. Return false if this failed.
1503   if (!EnsureCompiled(shared)) return false;
1504 
1505   // Create the debug info object.
1506   Handle<DebugInfo> debug_info = Factory::NewDebugInfo(shared);
1507 
1508   // Add debug info to the list.
1509   DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
1510   node->set_next(debug_info_list_);
1511   debug_info_list_ = node;
1512 
1513   // Now there is at least one break point.
1514   has_break_points_ = true;
1515 
1516   return true;
1517 }
1518 
1519 
RemoveDebugInfo(Handle<DebugInfo> debug_info)1520 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
1521   ASSERT(debug_info_list_ != NULL);
1522   // Run through the debug info objects to find this one and remove it.
1523   DebugInfoListNode* prev = NULL;
1524   DebugInfoListNode* current = debug_info_list_;
1525   while (current != NULL) {
1526     if (*current->debug_info() == *debug_info) {
1527       // Unlink from list. If prev is NULL we are looking at the first element.
1528       if (prev == NULL) {
1529         debug_info_list_ = current->next();
1530       } else {
1531         prev->set_next(current->next());
1532       }
1533       current->debug_info()->shared()->set_debug_info(Heap::undefined_value());
1534       delete current;
1535 
1536       // If there are no more debug info objects there are not more break
1537       // points.
1538       has_break_points_ = debug_info_list_ != NULL;
1539 
1540       return;
1541     }
1542     // Move to next in list.
1543     prev = current;
1544     current = current->next();
1545   }
1546   UNREACHABLE();
1547 }
1548 
1549 
SetAfterBreakTarget(JavaScriptFrame * frame)1550 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
1551   HandleScope scope;
1552 
1553   // Get the executing function in which the debug break occurred.
1554   Handle<SharedFunctionInfo> shared =
1555       Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
1556   if (!EnsureDebugInfo(shared)) {
1557     // Return if we failed to retrieve the debug info.
1558     return;
1559   }
1560   Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1561   Handle<Code> code(debug_info->code());
1562   Handle<Code> original_code(debug_info->original_code());
1563 #ifdef DEBUG
1564   // Get the code which is actually executing.
1565   Handle<Code> frame_code(frame->code());
1566   ASSERT(frame_code.is_identical_to(code));
1567 #endif
1568 
1569   // Find the call address in the running code. This address holds the call to
1570   // either a DebugBreakXXX or to the debug break return entry code if the
1571   // break point is still active after processing the break point.
1572   Address addr = frame->pc() - Assembler::kPatchReturnSequenceLength;
1573 
1574   // Check if the location is at JS exit.
1575   bool at_js_exit = false;
1576   RelocIterator it(debug_info->code());
1577   while (!it.done()) {
1578     if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
1579       at_js_exit = (it.rinfo()->pc() ==
1580                         addr - Assembler::kPatchReturnSequenceAddressOffset);
1581     }
1582     it.next();
1583   }
1584 
1585   // Handle the jump to continue execution after break point depending on the
1586   // break location.
1587   if (at_js_exit) {
1588     // First check if the call in the code is still the debug break return
1589     // entry code. If it is the break point is still active. If not the break
1590     // point was removed during break point processing.
1591     if (Assembler::target_address_at(addr) ==
1592         debug_break_return_entry()->entry()) {
1593       // Break point still active. Jump to the corresponding place in the
1594       // original code.
1595       addr +=  original_code->instruction_start() - code->instruction_start();
1596     }
1597 
1598     // Move back to where the call instruction sequence started.
1599     thread_local_.after_break_target_ =
1600         addr - Assembler::kPatchReturnSequenceAddressOffset;
1601   } else {
1602     // Check if there still is a debug break call at the target address. If the
1603     // break point has been removed it will have disappeared. If it have
1604     // disappeared don't try to look in the original code as the running code
1605     // will have the right address. This takes care of the case where the last
1606     // break point is removed from the function and therefore no "original code"
1607     // is available. If the debug break call is still there find the address in
1608     // the original code.
1609     if (IsDebugBreak(Assembler::target_address_at(addr))) {
1610       // If the break point is still there find the call address which was
1611       // overwritten in the original code by the call to DebugBreakXXX.
1612 
1613       // Find the corresponding address in the original code.
1614       addr += original_code->instruction_start() - code->instruction_start();
1615     }
1616 
1617     // Install jump to the call address in the original code. This will be the
1618     // call which was overwritten by the call to DebugBreakXXX.
1619     thread_local_.after_break_target_ = Assembler::target_address_at(addr);
1620   }
1621 }
1622 
1623 
IsDebugGlobal(GlobalObject * global)1624 bool Debug::IsDebugGlobal(GlobalObject* global) {
1625   return IsLoaded() && global == Debug::debug_context()->global();
1626 }
1627 
1628 
ClearMirrorCache()1629 void Debug::ClearMirrorCache() {
1630   HandleScope scope;
1631   ASSERT(Top::context() == *Debug::debug_context());
1632 
1633   // Clear the mirror cache.
1634   Handle<String> function_name =
1635       Factory::LookupSymbol(CStrVector("ClearMirrorCache"));
1636   Handle<Object> fun(Top::global()->GetProperty(*function_name));
1637   ASSERT(fun->IsJSFunction());
1638   bool caught_exception;
1639   Handle<Object> js_object = Execution::TryCall(
1640       Handle<JSFunction>::cast(fun),
1641       Handle<JSObject>(Debug::debug_context()->global()),
1642       0, NULL, &caught_exception);
1643 }
1644 
1645 
1646 // If an object given is an external string, check that the underlying
1647 // resource is accessible. For other kinds of objects, always return true.
IsExternalStringValid(Object * str)1648 static bool IsExternalStringValid(Object* str) {
1649   if (!str->IsString() || !StringShape(String::cast(str)).IsExternal()) {
1650     return true;
1651   }
1652   if (String::cast(str)->IsAsciiRepresentation()) {
1653     return ExternalAsciiString::cast(str)->resource() != NULL;
1654   } else if (String::cast(str)->IsTwoByteRepresentation()) {
1655     return ExternalTwoByteString::cast(str)->resource() != NULL;
1656   } else {
1657     return true;
1658   }
1659 }
1660 
1661 
CreateScriptCache()1662 void Debug::CreateScriptCache() {
1663   HandleScope scope;
1664 
1665   // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
1666   // rid of all the cached script wrappers and the second gets rid of the
1667   // scripts which is no longer referenced.
1668   Heap::CollectAllGarbage(false);
1669   Heap::CollectAllGarbage(false);
1670 
1671   ASSERT(script_cache_ == NULL);
1672   script_cache_ = new ScriptCache();
1673 
1674   // Scan heap for Script objects.
1675   int count = 0;
1676   HeapIterator iterator;
1677   while (iterator.has_next()) {
1678     HeapObject* obj = iterator.next();
1679     ASSERT(obj != NULL);
1680     if (obj->IsScript() && IsExternalStringValid(Script::cast(obj)->source())) {
1681       script_cache_->Add(Handle<Script>(Script::cast(obj)));
1682       count++;
1683     }
1684   }
1685 }
1686 
1687 
DestroyScriptCache()1688 void Debug::DestroyScriptCache() {
1689   // Get rid of the script cache if it was created.
1690   if (script_cache_ != NULL) {
1691     delete script_cache_;
1692     script_cache_ = NULL;
1693   }
1694 }
1695 
1696 
AddScriptToScriptCache(Handle<Script> script)1697 void Debug::AddScriptToScriptCache(Handle<Script> script) {
1698   if (script_cache_ != NULL) {
1699     script_cache_->Add(script);
1700   }
1701 }
1702 
1703 
GetLoadedScripts()1704 Handle<FixedArray> Debug::GetLoadedScripts() {
1705   // Create and fill the script cache when the loaded scripts is requested for
1706   // the first time.
1707   if (script_cache_ == NULL) {
1708     CreateScriptCache();
1709   }
1710 
1711   // If the script cache is not active just return an empty array.
1712   ASSERT(script_cache_ != NULL);
1713   if (script_cache_ == NULL) {
1714     Factory::NewFixedArray(0);
1715   }
1716 
1717   // Perform GC to get unreferenced scripts evicted from the cache before
1718   // returning the content.
1719   Heap::CollectAllGarbage(false);
1720 
1721   // Get the scripts from the cache.
1722   return script_cache_->GetScripts();
1723 }
1724 
1725 
AfterGarbageCollection()1726 void Debug::AfterGarbageCollection() {
1727   // Generate events for collected scripts.
1728   if (script_cache_ != NULL) {
1729     script_cache_->ProcessCollectedScripts();
1730   }
1731 }
1732 
1733 
1734 Mutex* Debugger::debugger_access_ = OS::CreateMutex();
1735 Handle<Object> Debugger::event_listener_ = Handle<Object>();
1736 Handle<Object> Debugger::event_listener_data_ = Handle<Object>();
1737 bool Debugger::compiling_natives_ = false;
1738 bool Debugger::is_loading_debugger_ = false;
1739 bool Debugger::never_unload_debugger_ = false;
1740 v8::Debug::MessageHandler2 Debugger::message_handler_ = NULL;
1741 bool Debugger::debugger_unload_pending_ = false;
1742 v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
1743 int Debugger::host_dispatch_micros_ = 100 * 1000;
1744 DebuggerAgent* Debugger::agent_ = NULL;
1745 LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize);
1746 Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0);
1747 
1748 
MakeJSObject(Vector<const char> constructor_name,int argc,Object *** argv,bool * caught_exception)1749 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
1750                                       int argc, Object*** argv,
1751                                       bool* caught_exception) {
1752   ASSERT(Top::context() == *Debug::debug_context());
1753 
1754   // Create the execution state object.
1755   Handle<String> constructor_str = Factory::LookupSymbol(constructor_name);
1756   Handle<Object> constructor(Top::global()->GetProperty(*constructor_str));
1757   ASSERT(constructor->IsJSFunction());
1758   if (!constructor->IsJSFunction()) {
1759     *caught_exception = true;
1760     return Factory::undefined_value();
1761   }
1762   Handle<Object> js_object = Execution::TryCall(
1763       Handle<JSFunction>::cast(constructor),
1764       Handle<JSObject>(Debug::debug_context()->global()), argc, argv,
1765       caught_exception);
1766   return js_object;
1767 }
1768 
1769 
MakeExecutionState(bool * caught_exception)1770 Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
1771   // Create the execution state object.
1772   Handle<Object> break_id = Factory::NewNumberFromInt(Debug::break_id());
1773   const int argc = 1;
1774   Object** argv[argc] = { break_id.location() };
1775   return MakeJSObject(CStrVector("MakeExecutionState"),
1776                       argc, argv, caught_exception);
1777 }
1778 
1779 
MakeBreakEvent(Handle<Object> exec_state,Handle<Object> break_points_hit,bool * caught_exception)1780 Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
1781                                         Handle<Object> break_points_hit,
1782                                         bool* caught_exception) {
1783   // Create the new break event object.
1784   const int argc = 2;
1785   Object** argv[argc] = { exec_state.location(),
1786                           break_points_hit.location() };
1787   return MakeJSObject(CStrVector("MakeBreakEvent"),
1788                       argc,
1789                       argv,
1790                       caught_exception);
1791 }
1792 
1793 
MakeExceptionEvent(Handle<Object> exec_state,Handle<Object> exception,bool uncaught,bool * caught_exception)1794 Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
1795                                             Handle<Object> exception,
1796                                             bool uncaught,
1797                                             bool* caught_exception) {
1798   // Create the new exception event object.
1799   const int argc = 3;
1800   Object** argv[argc] = { exec_state.location(),
1801                           exception.location(),
1802                           uncaught ? Factory::true_value().location() :
1803                                      Factory::false_value().location()};
1804   return MakeJSObject(CStrVector("MakeExceptionEvent"),
1805                       argc, argv, caught_exception);
1806 }
1807 
1808 
MakeNewFunctionEvent(Handle<Object> function,bool * caught_exception)1809 Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
1810                                               bool* caught_exception) {
1811   // Create the new function event object.
1812   const int argc = 1;
1813   Object** argv[argc] = { function.location() };
1814   return MakeJSObject(CStrVector("MakeNewFunctionEvent"),
1815                       argc, argv, caught_exception);
1816 }
1817 
1818 
MakeCompileEvent(Handle<Script> script,bool before,bool * caught_exception)1819 Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
1820                                           bool before,
1821                                           bool* caught_exception) {
1822   // Create the compile event object.
1823   Handle<Object> exec_state = MakeExecutionState(caught_exception);
1824   Handle<Object> script_wrapper = GetScriptWrapper(script);
1825   const int argc = 3;
1826   Object** argv[argc] = { exec_state.location(),
1827                           script_wrapper.location(),
1828                           before ? Factory::true_value().location() :
1829                                    Factory::false_value().location() };
1830 
1831   return MakeJSObject(CStrVector("MakeCompileEvent"),
1832                       argc,
1833                       argv,
1834                       caught_exception);
1835 }
1836 
1837 
MakeScriptCollectedEvent(int id,bool * caught_exception)1838 Handle<Object> Debugger::MakeScriptCollectedEvent(int id,
1839                                                   bool* caught_exception) {
1840   // Create the script collected event object.
1841   Handle<Object> exec_state = MakeExecutionState(caught_exception);
1842   Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id));
1843   const int argc = 2;
1844   Object** argv[argc] = { exec_state.location(), id_object.location() };
1845 
1846   return MakeJSObject(CStrVector("MakeScriptCollectedEvent"),
1847                       argc,
1848                       argv,
1849                       caught_exception);
1850 }
1851 
1852 
OnException(Handle<Object> exception,bool uncaught)1853 void Debugger::OnException(Handle<Object> exception, bool uncaught) {
1854   HandleScope scope;
1855 
1856   // Bail out based on state or if there is no listener for this event
1857   if (Debug::InDebugger()) return;
1858   if (!Debugger::EventActive(v8::Exception)) return;
1859 
1860   // Bail out if exception breaks are not active
1861   if (uncaught) {
1862     // Uncaught exceptions are reported by either flags.
1863     if (!(Debug::break_on_uncaught_exception() ||
1864           Debug::break_on_exception())) return;
1865   } else {
1866     // Caught exceptions are reported is activated.
1867     if (!Debug::break_on_exception()) return;
1868   }
1869 
1870   // Enter the debugger.
1871   EnterDebugger debugger;
1872   if (debugger.FailedToEnter()) return;
1873 
1874   // Clear all current stepping setup.
1875   Debug::ClearStepping();
1876   // Create the event data object.
1877   bool caught_exception = false;
1878   Handle<Object> exec_state = MakeExecutionState(&caught_exception);
1879   Handle<Object> event_data;
1880   if (!caught_exception) {
1881     event_data = MakeExceptionEvent(exec_state, exception, uncaught,
1882                                     &caught_exception);
1883   }
1884   // Bail out and don't call debugger if exception.
1885   if (caught_exception) {
1886     return;
1887   }
1888 
1889   // Process debug event.
1890   ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
1891   // Return to continue execution from where the exception was thrown.
1892 }
1893 
1894 
OnDebugBreak(Handle<Object> break_points_hit,bool auto_continue)1895 void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
1896                             bool auto_continue) {
1897   HandleScope scope;
1898 
1899   // Debugger has already been entered by caller.
1900   ASSERT(Top::context() == *Debug::debug_context());
1901 
1902   // Bail out if there is no listener for this event
1903   if (!Debugger::EventActive(v8::Break)) return;
1904 
1905   // Debugger must be entered in advance.
1906   ASSERT(Top::context() == *Debug::debug_context());
1907 
1908   // Create the event data object.
1909   bool caught_exception = false;
1910   Handle<Object> exec_state = MakeExecutionState(&caught_exception);
1911   Handle<Object> event_data;
1912   if (!caught_exception) {
1913     event_data = MakeBreakEvent(exec_state, break_points_hit,
1914                                 &caught_exception);
1915   }
1916   // Bail out and don't call debugger if exception.
1917   if (caught_exception) {
1918     return;
1919   }
1920 
1921   // Process debug event.
1922   ProcessDebugEvent(v8::Break,
1923                     Handle<JSObject>::cast(event_data),
1924                     auto_continue);
1925 }
1926 
1927 
OnBeforeCompile(Handle<Script> script)1928 void Debugger::OnBeforeCompile(Handle<Script> script) {
1929   HandleScope scope;
1930 
1931   // Bail out based on state or if there is no listener for this event
1932   if (Debug::InDebugger()) return;
1933   if (compiling_natives()) return;
1934   if (!EventActive(v8::BeforeCompile)) return;
1935 
1936   // Enter the debugger.
1937   EnterDebugger debugger;
1938   if (debugger.FailedToEnter()) return;
1939 
1940   // Create the event data object.
1941   bool caught_exception = false;
1942   Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception);
1943   // Bail out and don't call debugger if exception.
1944   if (caught_exception) {
1945     return;
1946   }
1947 
1948   // Process debug event.
1949   ProcessDebugEvent(v8::BeforeCompile,
1950                     Handle<JSObject>::cast(event_data),
1951                     true);
1952 }
1953 
1954 
1955 // Handle debugger actions when a new script is compiled.
OnAfterCompile(Handle<Script> script,Handle<JSFunction> fun)1956 void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
1957   HandleScope scope;
1958 
1959   // Add the newly compiled script to the script cache.
1960   Debug::AddScriptToScriptCache(script);
1961 
1962   // No more to do if not debugging.
1963   if (!IsDebuggerActive()) return;
1964 
1965   // No compile events while compiling natives.
1966   if (compiling_natives()) return;
1967 
1968   // Store whether in debugger before entering debugger.
1969   bool in_debugger = Debug::InDebugger();
1970 
1971   // Enter the debugger.
1972   EnterDebugger debugger;
1973   if (debugger.FailedToEnter()) return;
1974 
1975   // If debugging there might be script break points registered for this
1976   // script. Make sure that these break points are set.
1977 
1978   // Get the function UpdateScriptBreakPoints (defined in debug-delay.js).
1979   Handle<Object> update_script_break_points =
1980       Handle<Object>(Debug::debug_context()->global()->GetProperty(
1981           *Factory::LookupAsciiSymbol("UpdateScriptBreakPoints")));
1982   if (!update_script_break_points->IsJSFunction()) {
1983     return;
1984   }
1985   ASSERT(update_script_break_points->IsJSFunction());
1986 
1987   // Wrap the script object in a proper JS object before passing it
1988   // to JavaScript.
1989   Handle<JSValue> wrapper = GetScriptWrapper(script);
1990 
1991   // Call UpdateScriptBreakPoints expect no exceptions.
1992   bool caught_exception = false;
1993   const int argc = 1;
1994   Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) };
1995   Handle<Object> result = Execution::TryCall(
1996       Handle<JSFunction>::cast(update_script_break_points),
1997       Top::builtins(), argc, argv,
1998       &caught_exception);
1999   if (caught_exception) {
2000     return;
2001   }
2002   // Bail out based on state or if there is no listener for this event
2003   if (in_debugger) return;
2004   if (!Debugger::EventActive(v8::AfterCompile)) return;
2005 
2006   // Create the compile state object.
2007   Handle<Object> event_data = MakeCompileEvent(script,
2008                                                false,
2009                                                &caught_exception);
2010   // Bail out and don't call debugger if exception.
2011   if (caught_exception) {
2012     return;
2013   }
2014   // Process debug event.
2015   ProcessDebugEvent(v8::AfterCompile,
2016                     Handle<JSObject>::cast(event_data),
2017                     true);
2018 }
2019 
2020 
OnNewFunction(Handle<JSFunction> function)2021 void Debugger::OnNewFunction(Handle<JSFunction> function) {
2022   return;
2023   HandleScope scope;
2024 
2025   // Bail out based on state or if there is no listener for this event
2026   if (Debug::InDebugger()) return;
2027   if (compiling_natives()) return;
2028   if (!Debugger::EventActive(v8::NewFunction)) return;
2029 
2030   // Enter the debugger.
2031   EnterDebugger debugger;
2032   if (debugger.FailedToEnter()) return;
2033 
2034   // Create the event object.
2035   bool caught_exception = false;
2036   Handle<Object> event_data = MakeNewFunctionEvent(function, &caught_exception);
2037   // Bail out and don't call debugger if exception.
2038   if (caught_exception) {
2039     return;
2040   }
2041   // Process debug event.
2042   ProcessDebugEvent(v8::NewFunction, Handle<JSObject>::cast(event_data), true);
2043 }
2044 
2045 
OnScriptCollected(int id)2046 void Debugger::OnScriptCollected(int id) {
2047   HandleScope scope;
2048 
2049   // No more to do if not debugging.
2050   if (!IsDebuggerActive()) return;
2051   if (!Debugger::EventActive(v8::ScriptCollected)) return;
2052 
2053   // Enter the debugger.
2054   EnterDebugger debugger;
2055   if (debugger.FailedToEnter()) return;
2056 
2057   // Create the script collected state object.
2058   bool caught_exception = false;
2059   Handle<Object> event_data = MakeScriptCollectedEvent(id,
2060                                                        &caught_exception);
2061   // Bail out and don't call debugger if exception.
2062   if (caught_exception) {
2063     return;
2064   }
2065 
2066   // Process debug event.
2067   ProcessDebugEvent(v8::ScriptCollected,
2068                     Handle<JSObject>::cast(event_data),
2069                     true);
2070 }
2071 
2072 
ProcessDebugEvent(v8::DebugEvent event,Handle<JSObject> event_data,bool auto_continue)2073 void Debugger::ProcessDebugEvent(v8::DebugEvent event,
2074                                  Handle<JSObject> event_data,
2075                                  bool auto_continue) {
2076   HandleScope scope;
2077 
2078   // Clear any pending debug break if this is a real break.
2079   if (!auto_continue) {
2080     Debug::clear_interrupt_pending(DEBUGBREAK);
2081   }
2082 
2083   // Create the execution state.
2084   bool caught_exception = false;
2085   Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2086   if (caught_exception) {
2087     return;
2088   }
2089   // First notify the message handler if any.
2090   if (message_handler_ != NULL) {
2091     NotifyMessageHandler(event,
2092                          Handle<JSObject>::cast(exec_state),
2093                          event_data,
2094                          auto_continue);
2095   }
2096   // Notify registered debug event listener. This can be either a C or a
2097   // JavaScript function.
2098   if (!event_listener_.is_null()) {
2099     if (event_listener_->IsProxy()) {
2100       // C debug event listener.
2101       Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_));
2102       v8::Debug::EventCallback callback =
2103             FUNCTION_CAST<v8::Debug::EventCallback>(callback_obj->proxy());
2104       callback(event,
2105                v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
2106                v8::Utils::ToLocal(event_data),
2107                v8::Utils::ToLocal(Handle<Object>::cast(event_listener_data_)));
2108     } else {
2109       // JavaScript debug event listener.
2110       ASSERT(event_listener_->IsJSFunction());
2111       Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
2112 
2113       // Invoke the JavaScript debug event listener.
2114       const int argc = 4;
2115       Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(),
2116                               exec_state.location(),
2117                               Handle<Object>::cast(event_data).location(),
2118                               event_listener_data_.location() };
2119       Handle<Object> result = Execution::TryCall(fun, Top::global(),
2120                                                  argc, argv, &caught_exception);
2121       // Silently ignore exceptions from debug event listeners.
2122     }
2123   }
2124 }
2125 
2126 
UnloadDebugger()2127 void Debugger::UnloadDebugger() {
2128   // Make sure that there are no breakpoints left.
2129   Debug::ClearAllBreakPoints();
2130 
2131   // Unload the debugger if feasible.
2132   if (!never_unload_debugger_) {
2133     Debug::Unload();
2134   }
2135 
2136   // Clear the flag indicating that the debugger should be unloaded.
2137   debugger_unload_pending_ = false;
2138 }
2139 
2140 
NotifyMessageHandler(v8::DebugEvent event,Handle<JSObject> exec_state,Handle<JSObject> event_data,bool auto_continue)2141 void Debugger::NotifyMessageHandler(v8::DebugEvent event,
2142                                     Handle<JSObject> exec_state,
2143                                     Handle<JSObject> event_data,
2144                                     bool auto_continue) {
2145   HandleScope scope;
2146 
2147   if (!Debug::Load()) return;
2148 
2149   // Process the individual events.
2150   bool sendEventMessage = false;
2151   switch (event) {
2152     case v8::Break:
2153       sendEventMessage = !auto_continue;
2154       break;
2155     case v8::Exception:
2156       sendEventMessage = true;
2157       break;
2158     case v8::BeforeCompile:
2159       break;
2160     case v8::AfterCompile:
2161       sendEventMessage = true;
2162       break;
2163     case v8::ScriptCollected:
2164       sendEventMessage = true;
2165       break;
2166     case v8::NewFunction:
2167       break;
2168     default:
2169       UNREACHABLE();
2170   }
2171 
2172   // The debug command interrupt flag might have been set when the command was
2173   // added. It should be enough to clear the flag only once while we are in the
2174   // debugger.
2175   ASSERT(Debug::InDebugger());
2176   StackGuard::Continue(DEBUGCOMMAND);
2177 
2178   // Notify the debugger that a debug event has occurred unless auto continue is
2179   // active in which case no event is send.
2180   if (sendEventMessage) {
2181     MessageImpl message = MessageImpl::NewEvent(
2182         event,
2183         auto_continue,
2184         Handle<JSObject>::cast(exec_state),
2185         Handle<JSObject>::cast(event_data));
2186     InvokeMessageHandler(message);
2187   }
2188 
2189   // If auto continue don't make the event cause a break, but process messages
2190   // in the queue if any. For script collected events don't even process
2191   // messages in the queue as the execution state might not be what is expected
2192   // by the client.
2193   if ((auto_continue && !HasCommands()) || event == v8::ScriptCollected) {
2194     return;
2195   }
2196 
2197   // Get the DebugCommandProcessor.
2198   v8::Local<v8::Object> api_exec_state =
2199       v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
2200   v8::Local<v8::String> fun_name =
2201       v8::String::New("debugCommandProcessor");
2202   v8::Local<v8::Function> fun =
2203       v8::Function::Cast(*api_exec_state->Get(fun_name));
2204   v8::TryCatch try_catch;
2205   v8::Local<v8::Object> cmd_processor =
2206       v8::Object::Cast(*fun->Call(api_exec_state, 0, NULL));
2207   if (try_catch.HasCaught()) {
2208     PrintLn(try_catch.Exception());
2209     return;
2210   }
2211 
2212   // Process requests from the debugger.
2213   while (true) {
2214     // Wait for new command in the queue.
2215     if (Debugger::host_dispatch_handler_) {
2216       // In case there is a host dispatch - do periodic dispatches.
2217       if (!command_received_->Wait(host_dispatch_micros_)) {
2218         // Timout expired, do the dispatch.
2219         Debugger::host_dispatch_handler_();
2220         continue;
2221       }
2222     } else {
2223       // In case there is no host dispatch - just wait.
2224       command_received_->Wait();
2225     }
2226 
2227     // Get the command from the queue.
2228     CommandMessage command = command_queue_.Get();
2229     Logger::DebugTag("Got request from command queue, in interactive loop.");
2230     if (!Debugger::IsDebuggerActive()) {
2231       // Delete command text and user data.
2232       command.Dispose();
2233       return;
2234     }
2235 
2236     // Invoke JavaScript to process the debug request.
2237     v8::Local<v8::String> fun_name;
2238     v8::Local<v8::Function> fun;
2239     v8::Local<v8::Value> request;
2240     v8::TryCatch try_catch;
2241     fun_name = v8::String::New("processDebugRequest");
2242     fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
2243 
2244     request = v8::String::New(command.text().start(),
2245                               command.text().length());
2246     static const int kArgc = 1;
2247     v8::Handle<Value> argv[kArgc] = { request };
2248     v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
2249 
2250     // Get the response.
2251     v8::Local<v8::String> response;
2252     bool running = false;
2253     if (!try_catch.HasCaught()) {
2254       // Get response string.
2255       if (!response_val->IsUndefined()) {
2256         response = v8::String::Cast(*response_val);
2257       } else {
2258         response = v8::String::New("");
2259       }
2260 
2261       // Log the JSON request/response.
2262       if (FLAG_trace_debug_json) {
2263         PrintLn(request);
2264         PrintLn(response);
2265       }
2266 
2267       // Get the running state.
2268       fun_name = v8::String::New("isRunning");
2269       fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
2270       static const int kArgc = 1;
2271       v8::Handle<Value> argv[kArgc] = { response };
2272       v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv);
2273       if (!try_catch.HasCaught()) {
2274         running = running_val->ToBoolean()->Value();
2275       }
2276     } else {
2277       // In case of failure the result text is the exception text.
2278       response = try_catch.Exception()->ToString();
2279     }
2280 
2281     // Return the result.
2282     MessageImpl message = MessageImpl::NewResponse(
2283         event,
2284         running,
2285         Handle<JSObject>::cast(exec_state),
2286         Handle<JSObject>::cast(event_data),
2287         Handle<String>(Utils::OpenHandle(*response)),
2288         command.client_data());
2289     InvokeMessageHandler(message);
2290     command.Dispose();
2291 
2292     // Return from debug event processing if either the VM is put into the
2293     // runnning state (through a continue command) or auto continue is active
2294     // and there are no more commands queued.
2295     if (running || (auto_continue && !HasCommands())) {
2296       return;
2297     }
2298   }
2299 }
2300 
2301 
SetEventListener(Handle<Object> callback,Handle<Object> data)2302 void Debugger::SetEventListener(Handle<Object> callback,
2303                                 Handle<Object> data) {
2304   HandleScope scope;
2305 
2306   // Clear the global handles for the event listener and the event listener data
2307   // object.
2308   if (!event_listener_.is_null()) {
2309     GlobalHandles::Destroy(
2310         reinterpret_cast<Object**>(event_listener_.location()));
2311     event_listener_ = Handle<Object>();
2312   }
2313   if (!event_listener_data_.is_null()) {
2314     GlobalHandles::Destroy(
2315         reinterpret_cast<Object**>(event_listener_data_.location()));
2316     event_listener_data_ = Handle<Object>();
2317   }
2318 
2319   // If there is a new debug event listener register it together with its data
2320   // object.
2321   if (!callback->IsUndefined() && !callback->IsNull()) {
2322     event_listener_ = Handle<Object>::cast(GlobalHandles::Create(*callback));
2323     if (data.is_null()) {
2324       data = Factory::undefined_value();
2325     }
2326     event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data));
2327   }
2328 
2329   ListenersChanged();
2330 }
2331 
2332 
SetMessageHandler(v8::Debug::MessageHandler2 handler)2333 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
2334   ScopedLock with(debugger_access_);
2335 
2336   message_handler_ = handler;
2337   ListenersChanged();
2338   if (handler == NULL) {
2339     // Send an empty command to the debugger if in a break to make JavaScript
2340     // run again if the debugger is closed.
2341     if (Debug::InDebugger()) {
2342       ProcessCommand(Vector<const uint16_t>::empty());
2343     }
2344   }
2345 }
2346 
2347 
ListenersChanged()2348 void Debugger::ListenersChanged() {
2349   if (IsDebuggerActive()) {
2350     // Disable the compilation cache when the debugger is active.
2351     CompilationCache::Disable();
2352   } else {
2353     CompilationCache::Enable();
2354 
2355     // Unload the debugger if event listener and message handler cleared.
2356     if (Debug::InDebugger()) {
2357       // If we are in debugger set the flag to unload the debugger when last
2358       // EnterDebugger on the current stack is destroyed.
2359       debugger_unload_pending_ = true;
2360     } else {
2361       UnloadDebugger();
2362     }
2363   }
2364 }
2365 
2366 
SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,int period)2367 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
2368                                       int period) {
2369   host_dispatch_handler_ = handler;
2370   host_dispatch_micros_ = period * 1000;
2371 }
2372 
2373 
2374 // Calls the registered debug message handler. This callback is part of the
2375 // public API.
InvokeMessageHandler(MessageImpl message)2376 void Debugger::InvokeMessageHandler(MessageImpl message) {
2377   ScopedLock with(debugger_access_);
2378 
2379   if (message_handler_ != NULL) {
2380     message_handler_(message);
2381   }
2382 }
2383 
2384 
2385 // Puts a command coming from the public API on the queue.  Creates
2386 // a copy of the command string managed by the debugger.  Up to this
2387 // point, the command data was managed by the API client.  Called
2388 // by the API client thread.
ProcessCommand(Vector<const uint16_t> command,v8::Debug::ClientData * client_data)2389 void Debugger::ProcessCommand(Vector<const uint16_t> command,
2390                               v8::Debug::ClientData* client_data) {
2391   // Need to cast away const.
2392   CommandMessage message = CommandMessage::New(
2393       Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
2394                        command.length()),
2395       client_data);
2396   Logger::DebugTag("Put command on command_queue.");
2397   command_queue_.Put(message);
2398   command_received_->Signal();
2399 
2400   // Set the debug command break flag to have the command processed.
2401   if (!Debug::InDebugger()) {
2402     StackGuard::DebugCommand();
2403   }
2404 }
2405 
2406 
HasCommands()2407 bool Debugger::HasCommands() {
2408   return !command_queue_.IsEmpty();
2409 }
2410 
2411 
IsDebuggerActive()2412 bool Debugger::IsDebuggerActive() {
2413   ScopedLock with(debugger_access_);
2414 
2415   return message_handler_ != NULL || !event_listener_.is_null();
2416 }
2417 
2418 
Call(Handle<JSFunction> fun,Handle<Object> data,bool * pending_exception)2419 Handle<Object> Debugger::Call(Handle<JSFunction> fun,
2420                               Handle<Object> data,
2421                               bool* pending_exception) {
2422   // When calling functions in the debugger prevent it from beeing unloaded.
2423   Debugger::never_unload_debugger_ = true;
2424 
2425   // Enter the debugger.
2426   EnterDebugger debugger;
2427   if (debugger.FailedToEnter() || !debugger.HasJavaScriptFrames()) {
2428     return Factory::undefined_value();
2429   }
2430 
2431   // Create the execution state.
2432   bool caught_exception = false;
2433   Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2434   if (caught_exception) {
2435     return Factory::undefined_value();
2436   }
2437 
2438   static const int kArgc = 2;
2439   Object** argv[kArgc] = { exec_state.location(), data.location() };
2440   Handle<Object> result = Execution::Call(fun, Factory::undefined_value(),
2441                                           kArgc, argv, pending_exception);
2442   return result;
2443 }
2444 
2445 
StartAgent(const char * name,int port)2446 bool Debugger::StartAgent(const char* name, int port) {
2447   if (Socket::Setup()) {
2448     agent_ = new DebuggerAgent(name, port);
2449     agent_->Start();
2450     return true;
2451   }
2452 
2453   return false;
2454 }
2455 
2456 
StopAgent()2457 void Debugger::StopAgent() {
2458   if (agent_ != NULL) {
2459     agent_->Shutdown();
2460     agent_->Join();
2461     delete agent_;
2462     agent_ = NULL;
2463   }
2464 }
2465 
2466 
NewEvent(DebugEvent event,bool running,Handle<JSObject> exec_state,Handle<JSObject> event_data)2467 MessageImpl MessageImpl::NewEvent(DebugEvent event,
2468                                   bool running,
2469                                   Handle<JSObject> exec_state,
2470                                   Handle<JSObject> event_data) {
2471   MessageImpl message(true, event, running,
2472                       exec_state, event_data, Handle<String>(), NULL);
2473   return message;
2474 }
2475 
2476 
NewResponse(DebugEvent event,bool running,Handle<JSObject> exec_state,Handle<JSObject> event_data,Handle<String> response_json,v8::Debug::ClientData * client_data)2477 MessageImpl MessageImpl::NewResponse(DebugEvent event,
2478                                      bool running,
2479                                      Handle<JSObject> exec_state,
2480                                      Handle<JSObject> event_data,
2481                                      Handle<String> response_json,
2482                                      v8::Debug::ClientData* client_data) {
2483   MessageImpl message(false, event, running,
2484                       exec_state, event_data, response_json, client_data);
2485   return message;
2486 }
2487 
2488 
MessageImpl(bool is_event,DebugEvent event,bool running,Handle<JSObject> exec_state,Handle<JSObject> event_data,Handle<String> response_json,v8::Debug::ClientData * client_data)2489 MessageImpl::MessageImpl(bool is_event,
2490                          DebugEvent event,
2491                          bool running,
2492                          Handle<JSObject> exec_state,
2493                          Handle<JSObject> event_data,
2494                          Handle<String> response_json,
2495                          v8::Debug::ClientData* client_data)
2496     : is_event_(is_event),
2497       event_(event),
2498       running_(running),
2499       exec_state_(exec_state),
2500       event_data_(event_data),
2501       response_json_(response_json),
2502       client_data_(client_data) {}
2503 
2504 
IsEvent() const2505 bool MessageImpl::IsEvent() const {
2506   return is_event_;
2507 }
2508 
2509 
IsResponse() const2510 bool MessageImpl::IsResponse() const {
2511   return !is_event_;
2512 }
2513 
2514 
GetEvent() const2515 DebugEvent MessageImpl::GetEvent() const {
2516   return event_;
2517 }
2518 
2519 
WillStartRunning() const2520 bool MessageImpl::WillStartRunning() const {
2521   return running_;
2522 }
2523 
2524 
GetExecutionState() const2525 v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
2526   return v8::Utils::ToLocal(exec_state_);
2527 }
2528 
2529 
GetEventData() const2530 v8::Handle<v8::Object> MessageImpl::GetEventData() const {
2531   return v8::Utils::ToLocal(event_data_);
2532 }
2533 
2534 
GetJSON() const2535 v8::Handle<v8::String> MessageImpl::GetJSON() const {
2536   v8::HandleScope scope;
2537 
2538   if (IsEvent()) {
2539     // Call toJSONProtocol on the debug event object.
2540     Handle<Object> fun = GetProperty(event_data_, "toJSONProtocol");
2541     if (!fun->IsJSFunction()) {
2542       return v8::Handle<v8::String>();
2543     }
2544     bool caught_exception;
2545     Handle<Object> json = Execution::TryCall(Handle<JSFunction>::cast(fun),
2546                                              event_data_,
2547                                              0, NULL, &caught_exception);
2548     if (caught_exception || !json->IsString()) {
2549       return v8::Handle<v8::String>();
2550     }
2551     return scope.Close(v8::Utils::ToLocal(Handle<String>::cast(json)));
2552   } else {
2553     return v8::Utils::ToLocal(response_json_);
2554   }
2555 }
2556 
2557 
GetEventContext() const2558 v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
2559   Handle<Context> context = Debug::debugger_entry()->GetContext();
2560   // Top::context() may have been NULL when "script collected" event occured.
2561   if (*context == NULL) {
2562     ASSERT(event_ == v8::ScriptCollected);
2563     return v8::Local<v8::Context>();
2564   }
2565   Handle<Context> global_context(context->global_context());
2566   return v8::Utils::ToLocal(global_context);
2567 }
2568 
2569 
GetClientData() const2570 v8::Debug::ClientData* MessageImpl::GetClientData() const {
2571   return client_data_;
2572 }
2573 
2574 
CommandMessage()2575 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
2576                                    client_data_(NULL) {
2577 }
2578 
2579 
CommandMessage(const Vector<uint16_t> & text,v8::Debug::ClientData * data)2580 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
2581                                v8::Debug::ClientData* data)
2582     : text_(text),
2583       client_data_(data) {
2584 }
2585 
2586 
~CommandMessage()2587 CommandMessage::~CommandMessage() {
2588 }
2589 
2590 
Dispose()2591 void CommandMessage::Dispose() {
2592   text_.Dispose();
2593   delete client_data_;
2594   client_data_ = NULL;
2595 }
2596 
2597 
New(const Vector<uint16_t> & command,v8::Debug::ClientData * data)2598 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
2599                                    v8::Debug::ClientData* data) {
2600   return CommandMessage(command.Clone(), data);
2601 }
2602 
2603 
CommandMessageQueue(int size)2604 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
2605                                                      size_(size) {
2606   messages_ = NewArray<CommandMessage>(size);
2607 }
2608 
2609 
~CommandMessageQueue()2610 CommandMessageQueue::~CommandMessageQueue() {
2611   while (!IsEmpty()) {
2612     CommandMessage m = Get();
2613     m.Dispose();
2614   }
2615   DeleteArray(messages_);
2616 }
2617 
2618 
Get()2619 CommandMessage CommandMessageQueue::Get() {
2620   ASSERT(!IsEmpty());
2621   int result = start_;
2622   start_ = (start_ + 1) % size_;
2623   return messages_[result];
2624 }
2625 
2626 
Put(const CommandMessage & message)2627 void CommandMessageQueue::Put(const CommandMessage& message) {
2628   if ((end_ + 1) % size_ == start_) {
2629     Expand();
2630   }
2631   messages_[end_] = message;
2632   end_ = (end_ + 1) % size_;
2633 }
2634 
2635 
Expand()2636 void CommandMessageQueue::Expand() {
2637   CommandMessageQueue new_queue(size_ * 2);
2638   while (!IsEmpty()) {
2639     new_queue.Put(Get());
2640   }
2641   CommandMessage* array_to_free = messages_;
2642   *this = new_queue;
2643   new_queue.messages_ = array_to_free;
2644   // Make the new_queue empty so that it doesn't call Dispose on any messages.
2645   new_queue.start_ = new_queue.end_;
2646   // Automatic destructor called on new_queue, freeing array_to_free.
2647 }
2648 
2649 
LockingCommandMessageQueue(int size)2650 LockingCommandMessageQueue::LockingCommandMessageQueue(int size)
2651     : queue_(size) {
2652   lock_ = OS::CreateMutex();
2653 }
2654 
2655 
~LockingCommandMessageQueue()2656 LockingCommandMessageQueue::~LockingCommandMessageQueue() {
2657   delete lock_;
2658 }
2659 
2660 
IsEmpty() const2661 bool LockingCommandMessageQueue::IsEmpty() const {
2662   ScopedLock sl(lock_);
2663   return queue_.IsEmpty();
2664 }
2665 
2666 
Get()2667 CommandMessage LockingCommandMessageQueue::Get() {
2668   ScopedLock sl(lock_);
2669   CommandMessage result = queue_.Get();
2670   Logger::DebugEvent("Get", result.text());
2671   return result;
2672 }
2673 
2674 
Put(const CommandMessage & message)2675 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
2676   ScopedLock sl(lock_);
2677   queue_.Put(message);
2678   Logger::DebugEvent("Put", message.text());
2679 }
2680 
2681 
Clear()2682 void LockingCommandMessageQueue::Clear() {
2683   ScopedLock sl(lock_);
2684   queue_.Clear();
2685 }
2686 
2687 #endif  // ENABLE_DEBUGGER_SUPPORT
2688 
2689 } }  // namespace v8::internal
2690