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