The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / debug.cc @ 40c0f755

History | View | Annotate | Download (71.1 KB)

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 "compiler.h"
35
#include "debug.h"
36
#include "execution.h"
37
#include "global-handles.h"
38
#include "natives.h"
39
#include "stub-cache.h"
40
#include "log.h"
41

    
42
namespace v8 { namespace internal {
43

    
44
static void PrintLn(v8::Local<v8::Value> value) {
45
  v8::Local<v8::String> s = value->ToString();
46
  char* data = NewArray<char>(s->Length() + 1);
47
  if (data == NULL) {
48
    V8::FatalProcessOutOfMemory("PrintLn");
49
    return;
50
  }
51
  s->WriteAscii(data);
52
  PrintF("%s\n", data);
53
  DeleteArray(data);
54
}
55

    
56

    
57
static Handle<Code> ComputeCallDebugBreak(int argc) {
58
  CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugBreak(argc), Code);
59
}
60

    
61

    
62
static Handle<Code> ComputeCallDebugPrepareStepIn(int argc) {
63
  CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugPrepareStepIn(argc), Code);
64
}
65

    
66

    
67
BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
68
                                             BreakLocatorType type) {
69
  debug_info_ = debug_info;
70
  type_ = type;
71
  reloc_iterator_ = NULL;
72
  reloc_iterator_original_ = NULL;
73
  Reset();  // Initialize the rest of the member variables.
74
}
75

    
76

    
77
BreakLocationIterator::~BreakLocationIterator() {
78
  ASSERT(reloc_iterator_ != NULL);
79
  ASSERT(reloc_iterator_original_ != NULL);
80
  delete reloc_iterator_;
81
  delete reloc_iterator_original_;
82
}
83

    
84

    
85
void BreakLocationIterator::Next() {
86
  AssertNoAllocation nogc;
87
  ASSERT(!RinfoDone());
88

    
89
  // Iterate through reloc info for code and original code stopping at each
90
  // breakable code target.
91
  bool first = break_point_ == -1;
92
  while (!RinfoDone()) {
93
    if (!first) RinfoNext();
94
    first = false;
95
    if (RinfoDone()) return;
96

    
97
    // Whenever a statement position or (plain) position is passed update the
98
    // current value of these.
99
    if (RelocInfo::IsPosition(rmode())) {
100
      if (RelocInfo::IsStatementPosition(rmode())) {
101
        statement_position_ =
102
            rinfo()->data() - debug_info_->shared()->start_position();
103
      }
104
      // Always update the position as we don't want that to be before the
105
      // statement position.
106
      position_ = rinfo()->data() - debug_info_->shared()->start_position();
107
      ASSERT(position_ >= 0);
108
      ASSERT(statement_position_ >= 0);
109
    }
110

    
111
    // Check for breakable code target. Look in the original code as setting
112
    // break points can cause the code targets in the running (debugged) code to
113
    // be of a different kind than in the original code.
114
    if (RelocInfo::IsCodeTarget(rmode())) {
115
      Address target = original_rinfo()->target_address();
116
      Code* code = Code::GetCodeFromTargetAddress(target);
117
      if (code->is_inline_cache_stub() || RelocInfo::IsConstructCall(rmode())) {
118
        break_point_++;
119
        return;
120
      }
121
      if (code->kind() == Code::STUB) {
122
        if (type_ == ALL_BREAK_LOCATIONS) {
123
          if (Debug::IsBreakStub(code)) {
124
            break_point_++;
125
            return;
126
          }
127
        } else {
128
          ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
129
          if (Debug::IsSourceBreakStub(code)) {
130
            break_point_++;
131
            return;
132
          }
133
        }
134
      }
135
    }
136

    
137
    // Check for break at return.
138
    if (RelocInfo::IsJSReturn(rmode())) {
139
      // Set the positions to the end of the function.
140
      if (debug_info_->shared()->HasSourceCode()) {
141
        position_ = debug_info_->shared()->end_position() -
142
                    debug_info_->shared()->start_position();
143
      } else {
144
        position_ = 0;
145
      }
146
      statement_position_ = position_;
147
      break_point_++;
148
      return;
149
    }
150
  }
151
}
152

    
153

    
154
void BreakLocationIterator::Next(int count) {
155
  while (count > 0) {
156
    Next();
157
    count--;
158
  }
159
}
160

    
161

    
162
// Find the break point closest to the supplied address.
163
void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
164
  // Run through all break points to locate the one closest to the address.
165
  int closest_break_point = 0;
166
  int distance = kMaxInt;
167
  while (!Done()) {
168
    // Check if this break point is closer that what was previously found.
169
    if (this->pc() < pc && pc - this->pc() < distance) {
170
      closest_break_point = break_point();
171
      distance = pc - this->pc();
172
      // Check whether we can't get any closer.
173
      if (distance == 0) break;
174
    }
175
    Next();
176
  }
177

    
178
  // Move to the break point found.
179
  Reset();
180
  Next(closest_break_point);
181
}
182

    
183

    
184
// Find the break point closest to the supplied source position.
185
void BreakLocationIterator::FindBreakLocationFromPosition(int position) {
186
  // Run through all break points to locate the one closest to the source
187
  // position.
188
  int closest_break_point = 0;
189
  int distance = kMaxInt;
190
  while (!Done()) {
191
    // Check if this break point is closer that what was previously found.
192
    if (position <= statement_position() &&
193
        statement_position() - position < distance) {
194
      closest_break_point = break_point();
195
      distance = statement_position() - position;
196
      // Check whether we can't get any closer.
197
      if (distance == 0) break;
198
    }
199
    Next();
200
  }
201

    
202
  // Move to the break point found.
203
  Reset();
204
  Next(closest_break_point);
205
}
206

    
207

    
208
void BreakLocationIterator::Reset() {
209
  // Create relocation iterators for the two code objects.
210
  if (reloc_iterator_ != NULL) delete reloc_iterator_;
211
  if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
212
  reloc_iterator_ = new RelocIterator(debug_info_->code());
213
  reloc_iterator_original_ = new RelocIterator(debug_info_->original_code());
214

    
215
  // Position at the first break point.
216
  break_point_ = -1;
217
  position_ = 1;
218
  statement_position_ = 1;
219
  Next();
220
}
221

    
222

    
223
bool BreakLocationIterator::Done() const {
224
  return RinfoDone();
225
}
226

    
227

    
228
void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
229
  // If there is not already a real break point here patch code with debug
230
  // break.
231
  if (!HasBreakPoint()) {
232
    SetDebugBreak();
233
  }
234
  ASSERT(IsDebugBreak());
235
  // Set the break point information.
236
  DebugInfo::SetBreakPoint(debug_info_, code_position(),
237
                           position(), statement_position(),
238
                           break_point_object);
239
}
240

    
241

    
242
void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
243
  // Clear the break point information.
244
  DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
245
  // If there are no more break points here remove the debug break.
246
  if (!HasBreakPoint()) {
247
    ClearDebugBreak();
248
    ASSERT(!IsDebugBreak());
249
  }
250
}
251

    
252

    
253
void BreakLocationIterator::SetOneShot() {
254
  // If there is a real break point here no more to do.
255
  if (HasBreakPoint()) {
256
    ASSERT(IsDebugBreak());
257
    return;
258
  }
259

    
260
  // Patch code with debug break.
261
  SetDebugBreak();
262
}
263

    
264

    
265
void BreakLocationIterator::ClearOneShot() {
266
  // If there is a real break point here no more to do.
267
  if (HasBreakPoint()) {
268
    ASSERT(IsDebugBreak());
269
    return;
270
  }
271

    
272
  // Patch code removing debug break.
273
  ClearDebugBreak();
274
  ASSERT(!IsDebugBreak());
275
}
276

    
277

    
278
void BreakLocationIterator::SetDebugBreak() {
279
  // If there is already a break point here just return. This might happen if
280
  // the same code is flooded with break points twice. Flooding the same
281
  // function twice might happen when stepping in a function with an exception
282
  // handler as the handler and the function is the same.
283
  if (IsDebugBreak()) {
284
    return;
285
  }
286

    
287
  if (RelocInfo::IsJSReturn(rmode())) {
288
    // Patch the frame exit code with a break point.
289
    SetDebugBreakAtReturn();
290
  } else {
291
    // Patch the original code with the current address as the current address
292
    // might have changed by the inline caching since the code was copied.
293
    original_rinfo()->set_target_address(rinfo()->target_address());
294

    
295
    // Patch the code to invoke the builtin debug break function matching the
296
    // calling convention used by the call site.
297
    Handle<Code> dbgbrk_code(Debug::FindDebugBreak(rinfo()));
298
    rinfo()->set_target_address(dbgbrk_code->entry());
299
  }
300
  ASSERT(IsDebugBreak());
301
}
302

    
303

    
304
void BreakLocationIterator::ClearDebugBreak() {
305
  if (RelocInfo::IsJSReturn(rmode())) {
306
    // Restore the frame exit code.
307
    ClearDebugBreakAtReturn();
308
  } else {
309
    // Patch the code to the original invoke.
310
    rinfo()->set_target_address(original_rinfo()->target_address());
311
  }
312
  ASSERT(!IsDebugBreak());
313
}
314

    
315

    
316
void BreakLocationIterator::PrepareStepIn() {
317
  HandleScope scope;
318

    
319
  // Step in can only be prepared if currently positioned on an IC call or
320
  // construct call.
321
  Address target = rinfo()->target_address();
322
  Code* code = Code::GetCodeFromTargetAddress(target);
323
  if (code->is_call_stub()) {
324
    // Step in through IC call is handled by the runtime system. Therefore make
325
    // sure that the any current IC is cleared and the runtime system is
326
    // called. If the executing code has a debug break at the location change
327
    // the call in the original code as it is the code there that will be
328
    // executed in place of the debug break call.
329
    Handle<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count());
330
    if (IsDebugBreak()) {
331
      original_rinfo()->set_target_address(stub->entry());
332
    } else {
333
      rinfo()->set_target_address(stub->entry());
334
    }
335
  } else {
336
    // Step in through constructs call requires no changes to the running code.
337
    ASSERT(RelocInfo::IsConstructCall(rmode()));
338
  }
339
}
340

    
341

    
342
// Check whether the break point is at a position which will exit the function.
343
bool BreakLocationIterator::IsExit() const {
344
  return (RelocInfo::IsJSReturn(rmode()));
345
}
346

    
347

    
348
bool BreakLocationIterator::HasBreakPoint() {
349
  return debug_info_->HasBreakPoint(code_position());
350
}
351

    
352

    
353
// Check whether there is a debug break at the current position.
354
bool BreakLocationIterator::IsDebugBreak() {
355
  if (RelocInfo::IsJSReturn(rmode())) {
356
    return IsDebugBreakAtReturn();
357
  } else {
358
    return Debug::IsDebugBreak(rinfo()->target_address());
359
  }
360
}
361

    
362

    
363
Object* BreakLocationIterator::BreakPointObjects() {
364
  return debug_info_->GetBreakPointObjects(code_position());
365
}
366

    
367

    
368
// Clear out all the debug break code. This is ONLY supposed to be used when
369
// shutting down the debugger as it will leave the break point information in
370
// DebugInfo even though the code is patched back to the non break point state.
371
void BreakLocationIterator::ClearAllDebugBreak() {
372
  while (!Done()) {
373
    ClearDebugBreak();
374
    Next();
375
  }
376
}
377

    
378

    
379
bool BreakLocationIterator::RinfoDone() const {
380
  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
381
  return reloc_iterator_->done();
382
}
383

    
384

    
385
void BreakLocationIterator::RinfoNext() {
386
  reloc_iterator_->next();
387
  reloc_iterator_original_->next();
388
#ifdef DEBUG
389
  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
390
  if (!reloc_iterator_->done()) {
391
    ASSERT(rmode() == original_rmode());
392
  }
393
#endif
394
}
395

    
396

    
397
bool Debug::has_break_points_ = false;
398
DebugInfoListNode* Debug::debug_info_list_ = NULL;
399

    
400

    
401
// Threading support.
402
void Debug::ThreadInit() {
403
  thread_local_.break_count_ = 0;
404
  thread_local_.break_id_ = 0;
405
  thread_local_.break_frame_id_ = StackFrame::NO_ID;
406
  thread_local_.last_step_action_ = StepNone;
407
  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
408
  thread_local_.step_count_ = 0;
409
  thread_local_.last_fp_ = 0;
410
  thread_local_.step_into_fp_ = 0;
411
  thread_local_.after_break_target_ = 0;
412
  thread_local_.debugger_entry_ = NULL;
413
  thread_local_.preemption_pending_ = false;
414
}
415

    
416

    
417
JSCallerSavedBuffer Debug::registers_;
418
Debug::ThreadLocal Debug::thread_local_;
419

    
420

    
421
char* Debug::ArchiveDebug(char* storage) {
422
  char* to = storage;
423
  memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
424
  to += sizeof(ThreadLocal);
425
  memcpy(to, reinterpret_cast<char*>(&registers_), sizeof(registers_));
426
  ThreadInit();
427
  ASSERT(to <= storage + ArchiveSpacePerThread());
428
  return storage + ArchiveSpacePerThread();
429
}
430

    
431

    
432
char* Debug::RestoreDebug(char* storage) {
433
  char* from = storage;
434
  memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
435
  from += sizeof(ThreadLocal);
436
  memcpy(reinterpret_cast<char*>(&registers_), from, sizeof(registers_));
437
  ASSERT(from <= storage + ArchiveSpacePerThread());
438
  return storage + ArchiveSpacePerThread();
439
}
440

    
441

    
442
int Debug::ArchiveSpacePerThread() {
443
  return sizeof(ThreadLocal) + sizeof(registers_);
444
}
445

    
446

    
447
// Default break enabled.
448
bool Debug::disable_break_ = false;
449

    
450
// Default call debugger on uncaught exception.
451
bool Debug::break_on_exception_ = false;
452
bool Debug::break_on_uncaught_exception_ = true;
453

    
454
Handle<Context> Debug::debug_context_ = Handle<Context>();
455
Code* Debug::debug_break_return_entry_ = NULL;
456
Code* Debug::debug_break_return_ = NULL;
457

    
458

    
459
void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) {
460
  DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
461
  RemoveDebugInfo(node->debug_info());
462
#ifdef DEBUG
463
  node = Debug::debug_info_list_;
464
  while (node != NULL) {
465
    ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
466
    node = node->next();
467
  }
468
#endif
469
}
470

    
471

    
472
DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
473
  // Globalize the request debug info object and make it weak.
474
  debug_info_ = Handle<DebugInfo>::cast((GlobalHandles::Create(debug_info)));
475
  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
476
                          this, Debug::HandleWeakDebugInfo);
477
}
478

    
479

    
480
DebugInfoListNode::~DebugInfoListNode() {
481
  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
482
}
483

    
484

    
485
void Debug::Setup(bool create_heap_objects) {
486
  ThreadInit();
487
  if (create_heap_objects) {
488
    // Get code to handle entry to debug break on return.
489
    debug_break_return_entry_ =
490
        Builtins::builtin(Builtins::Return_DebugBreakEntry);
491
    ASSERT(debug_break_return_entry_->IsCode());
492

    
493
    // Get code to handle debug break on return.
494
    debug_break_return_ =
495
        Builtins::builtin(Builtins::Return_DebugBreak);
496
    ASSERT(debug_break_return_->IsCode());
497
  }
498
}
499

    
500

    
501
bool Debug::CompileDebuggerScript(int index) {
502
  HandleScope scope;
503

    
504
  // Bail out if the index is invalid.
505
  if (index == -1) {
506
    return false;
507
  }
508

    
509
  // Find source and name for the requested script.
510
  Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
511
  Vector<const char> name = Natives::GetScriptName(index);
512
  Handle<String> script_name = Factory::NewStringFromAscii(name);
513

    
514
  // Compile the script.
515
  bool allow_natives_syntax = FLAG_allow_natives_syntax;
516
  FLAG_allow_natives_syntax = true;
517
  Handle<JSFunction> boilerplate;
518
  boilerplate = Compiler::Compile(source_code, script_name, 0, 0, NULL, NULL);
519
  FLAG_allow_natives_syntax = allow_natives_syntax;
520

    
521
  // Silently ignore stack overflows during compilation.
522
  if (boilerplate.is_null()) {
523
    ASSERT(Top::has_pending_exception());
524
    Top::clear_pending_exception();
525
    return false;
526
  }
527

    
528
  // Execute the boilerplate function in the debugger context.
529
  Handle<Context> context = Top::global_context();
530
  bool caught_exception = false;
531
  Handle<JSFunction> function =
532
      Factory::NewFunctionFromBoilerplate(boilerplate, context);
533
  Handle<Object> result =
534
      Execution::TryCall(function, Handle<Object>(context->global()),
535
                         0, NULL, &caught_exception);
536

    
537
  // Check for caught exceptions.
538
  if (caught_exception) {
539
    Handle<Object> message = MessageHandler::MakeMessageObject(
540
        "error_loading_debugger", NULL, HandleVector<Object>(&result, 1),
541
        Handle<String>());
542
    MessageHandler::ReportMessage(NULL, message);
543
    return false;
544
  }
545

    
546
  // Mark this script as native and return successfully.
547
  Handle<Script> script(Script::cast(function->shared()->script()));
548
  script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE));
549
  return true;
550
}
551

    
552

    
553
bool Debug::Load() {
554
  // Return if debugger is already loaded.
555
  if (IsLoaded()) return true;
556

    
557
  // Bail out if we're already in the process of compiling the native
558
  // JavaScript source code for the debugger.
559
  if (Debugger::compiling_natives() || Debugger::is_loading_debugger())
560
    return false;
561
  Debugger::set_loading_debugger(true);
562

    
563
  // Disable breakpoints and interrupts while compiling and running the
564
  // debugger scripts including the context creation code.
565
  DisableBreak disable(true);
566
  PostponeInterruptsScope postpone;
567

    
568
  // Create the debugger context.
569
  HandleScope scope;
570
  Handle<Context> context =
571
      Bootstrapper::CreateEnvironment(Handle<Object>::null(),
572
                                      v8::Handle<ObjectTemplate>(),
573
                                      NULL);
574

    
575
  // Use the debugger context.
576
  SaveContext save;
577
  Top::set_context(*context);
578

    
579
  // Expose the builtins object in the debugger context.
580
  Handle<String> key = Factory::LookupAsciiSymbol("builtins");
581
  Handle<GlobalObject> global = Handle<GlobalObject>(context->global());
582
  SetProperty(global, key, Handle<Object>(global->builtins()), NONE);
583

    
584
  // Compile the JavaScript for the debugger in the debugger context.
585
  Debugger::set_compiling_natives(true);
586
  bool caught_exception =
587
      !CompileDebuggerScript(Natives::GetIndex("mirror")) ||
588
      !CompileDebuggerScript(Natives::GetIndex("debug"));
589
  Debugger::set_compiling_natives(false);
590

    
591
  // Make sure we mark the debugger as not loading before we might
592
  // return.
593
  Debugger::set_loading_debugger(false);
594

    
595
  // Check for caught exceptions.
596
  if (caught_exception) return false;
597

    
598
  // Debugger loaded.
599
  debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
600
  return true;
601
}
602

    
603

    
604
void Debug::Unload() {
605
  // Return debugger is not loaded.
606
  if (!IsLoaded()) {
607
    return;
608
  }
609

    
610
  // Clear debugger context global handle.
611
  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
612
  debug_context_ = Handle<Context>();
613
}
614

    
615

    
616
// Set the flag indicating that preemption happened during debugging.
617
void Debug::PreemptionWhileInDebugger() {
618
  ASSERT(InDebugger());
619
  Debug::set_preemption_pending(true);
620
}
621

    
622

    
623
void Debug::Iterate(ObjectVisitor* v) {
624
  v->VisitPointer(bit_cast<Object**, Code**>(&(debug_break_return_entry_)));
625
  v->VisitPointer(bit_cast<Object**, Code**>(&(debug_break_return_)));
626
}
627

    
628

    
629
Object* Debug::Break(Arguments args) {
630
  HandleScope scope;
631
  ASSERT(args.length() == 0);
632

    
633
  // Get the top-most JavaScript frame.
634
  JavaScriptFrameIterator it;
635
  JavaScriptFrame* frame = it.frame();
636

    
637
  // Just continue if breaks are disabled or debugger cannot be loaded.
638
  if (disable_break() || !Load()) {
639
    SetAfterBreakTarget(frame);
640
    return Heap::undefined_value();
641
  }
642

    
643
  // Enter the debugger.
644
  EnterDebugger debugger;
645
  if (debugger.FailedToEnter()) {
646
    return Heap::undefined_value();
647
  }
648

    
649
  // Postpone interrupt during breakpoint processing.
650
  PostponeInterruptsScope postpone;
651

    
652
  // Get the debug info (create it if it does not exist).
653
  Handle<SharedFunctionInfo> shared =
654
      Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
655
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
656

    
657
  // Find the break point where execution has stopped.
658
  BreakLocationIterator break_location_iterator(debug_info,
659
                                                ALL_BREAK_LOCATIONS);
660
  break_location_iterator.FindBreakLocationFromAddress(frame->pc());
661

    
662
  // Check whether step next reached a new statement.
663
  if (!StepNextContinue(&break_location_iterator, frame)) {
664
    // Decrease steps left if performing multiple steps.
665
    if (thread_local_.step_count_ > 0) {
666
      thread_local_.step_count_--;
667
    }
668
  }
669

    
670
  // If there is one or more real break points check whether any of these are
671
  // triggered.
672
  Handle<Object> break_points_hit(Heap::undefined_value());
673
  if (break_location_iterator.HasBreakPoint()) {
674
    Handle<Object> break_point_objects =
675
        Handle<Object>(break_location_iterator.BreakPointObjects());
676
    break_points_hit = CheckBreakPoints(break_point_objects);
677
  }
678

    
679
  // Notify debugger if a real break point is triggered or if performing single
680
  // stepping with no more steps to perform. Otherwise do another step.
681
  if (!break_points_hit->IsUndefined() ||
682
    (thread_local_.last_step_action_ != StepNone &&
683
     thread_local_.step_count_ == 0)) {
684
    // Clear all current stepping setup.
685
    ClearStepping();
686

    
687
    // Notify the debug event listeners.
688
    Debugger::OnDebugBreak(break_points_hit, false);
689
  } else if (thread_local_.last_step_action_ != StepNone) {
690
    // Hold on to last step action as it is cleared by the call to
691
    // ClearStepping.
692
    StepAction step_action = thread_local_.last_step_action_;
693
    int step_count = thread_local_.step_count_;
694

    
695
    // Clear all current stepping setup.
696
    ClearStepping();
697

    
698
    // Set up for the remaining steps.
699
    PrepareStep(step_action, step_count);
700
  }
701

    
702
  // Install jump to the call address which was overwritten.
703
  SetAfterBreakTarget(frame);
704

    
705
  return Heap::undefined_value();
706
}
707

    
708

    
709
// Check the break point objects for whether one or more are actually
710
// triggered. This function returns a JSArray with the break point objects
711
// which is triggered.
712
Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
713
  int break_points_hit_count = 0;
714
  Handle<JSArray> break_points_hit = Factory::NewJSArray(1);
715

    
716
  // If there are multiple break points they are in a FixedArray.
717
  ASSERT(!break_point_objects->IsUndefined());
718
  if (break_point_objects->IsFixedArray()) {
719
    Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
720
    for (int i = 0; i < array->length(); i++) {
721
      Handle<Object> o(array->get(i));
722
      if (CheckBreakPoint(o)) {
723
        break_points_hit->SetElement(break_points_hit_count++, *o);
724
      }
725
    }
726
  } else {
727
    if (CheckBreakPoint(break_point_objects)) {
728
      break_points_hit->SetElement(break_points_hit_count++,
729
                                   *break_point_objects);
730
    }
731
  }
732

    
733
  // Return undefined if no break points where triggered.
734
  if (break_points_hit_count == 0) {
735
    return Factory::undefined_value();
736
  }
737
  return break_points_hit;
738
}
739

    
740

    
741
// Check whether a single break point object is triggered.
742
bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
743
  HandleScope scope;
744

    
745
  // Ignore check if break point object is not a JSObject.
746
  if (!break_point_object->IsJSObject()) return true;
747

    
748
  // Get the function CheckBreakPoint (defined in debug.js).
749
  Handle<JSFunction> check_break_point =
750
    Handle<JSFunction>(JSFunction::cast(
751
      debug_context()->global()->GetProperty(
752
          *Factory::LookupAsciiSymbol("IsBreakPointTriggered"))));
753

    
754
  // Get the break id as an object.
755
  Handle<Object> break_id = Factory::NewNumberFromInt(Debug::break_id());
756

    
757
  // Call HandleBreakPointx.
758
  bool caught_exception = false;
759
  const int argc = 2;
760
  Object** argv[argc] = {
761
    break_id.location(),
762
    reinterpret_cast<Object**>(break_point_object.location())
763
  };
764
  Handle<Object> result = Execution::TryCall(check_break_point,
765
                                             Top::builtins(), argc, argv,
766
                                             &caught_exception);
767

    
768
  // If exception or non boolean result handle as not triggered
769
  if (caught_exception || !result->IsBoolean()) {
770
    return false;
771
  }
772

    
773
  // Return whether the break point is triggered.
774
  return *result == Heap::true_value();
775
}
776

    
777

    
778
// Check whether the function has debug information.
779
bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
780
  return !shared->debug_info()->IsUndefined();
781
}
782

    
783

    
784
// Return the debug info for this function. EnsureDebugInfo must be called
785
// prior to ensure the debug info has been generated for shared.
786
Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
787
  ASSERT(HasDebugInfo(shared));
788
  return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
789
}
790

    
791

    
792
void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
793
                          int source_position,
794
                          Handle<Object> break_point_object) {
795
  HandleScope scope;
796

    
797
  if (!EnsureDebugInfo(shared)) {
798
    // Return if retrieving debug info failed.
799
    return;
800
  }
801

    
802
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
803
  // Source positions starts with zero.
804
  ASSERT(source_position >= 0);
805

    
806
  // Find the break point and change it.
807
  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
808
  it.FindBreakLocationFromPosition(source_position);
809
  it.SetBreakPoint(break_point_object);
810

    
811
  // At least one active break point now.
812
  ASSERT(debug_info->GetBreakPointCount() > 0);
813
}
814

    
815

    
816
void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
817
  HandleScope scope;
818

    
819
  DebugInfoListNode* node = debug_info_list_;
820
  while (node != NULL) {
821
    Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
822
                                                   break_point_object);
823
    if (!result->IsUndefined()) {
824
      // Get information in the break point.
825
      BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
826
      Handle<DebugInfo> debug_info = node->debug_info();
827
      Handle<SharedFunctionInfo> shared(debug_info->shared());
828
      int source_position =  break_point_info->statement_position()->value();
829

    
830
      // Source positions starts with zero.
831
      ASSERT(source_position >= 0);
832

    
833
      // Find the break point and clear it.
834
      BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
835
      it.FindBreakLocationFromPosition(source_position);
836
      it.ClearBreakPoint(break_point_object);
837

    
838
      // If there are no more break points left remove the debug info for this
839
      // function.
840
      if (debug_info->GetBreakPointCount() == 0) {
841
        RemoveDebugInfo(debug_info);
842
      }
843

    
844
      return;
845
    }
846
    node = node->next();
847
  }
848
}
849

    
850

    
851
void Debug::ClearAllBreakPoints() {
852
  DebugInfoListNode* node = debug_info_list_;
853
  while (node != NULL) {
854
    // Remove all debug break code.
855
    BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
856
    it.ClearAllDebugBreak();
857
    node = node->next();
858
  }
859

    
860
  // Remove all debug info.
861
  while (debug_info_list_ != NULL) {
862
    RemoveDebugInfo(debug_info_list_->debug_info());
863
  }
864
}
865

    
866

    
867
void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) {
868
  // Make sure the function has setup the debug info.
869
  if (!EnsureDebugInfo(shared)) {
870
    // Return if we failed to retrieve the debug info.
871
    return;
872
  }
873

    
874
  // Flood the function with break points.
875
  BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
876
  while (!it.Done()) {
877
    it.SetOneShot();
878
    it.Next();
879
  }
880
}
881

    
882

    
883
void Debug::FloodHandlerWithOneShot() {
884
  // Iterate through the JavaScript stack looking for handlers.
885
  StackFrame::Id id = break_frame_id();
886
  if (id == StackFrame::NO_ID) {
887
    // If there is no JavaScript stack don't do anything.
888
    return;
889
  }
890
  for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) {
891
    JavaScriptFrame* frame = it.frame();
892
    if (frame->HasHandler()) {
893
      Handle<SharedFunctionInfo> shared =
894
          Handle<SharedFunctionInfo>(
895
              JSFunction::cast(frame->function())->shared());
896
      // Flood the function with the catch block with break points
897
      FloodWithOneShot(shared);
898
      return;
899
    }
900
  }
901
}
902

    
903

    
904
void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
905
  if (type == BreakUncaughtException) {
906
    break_on_uncaught_exception_ = enable;
907
  } else {
908
    break_on_exception_ = enable;
909
  }
910
}
911

    
912

    
913
void Debug::PrepareStep(StepAction step_action, int step_count) {
914
  HandleScope scope;
915
  ASSERT(Debug::InDebugger());
916

    
917
  // Remember this step action and count.
918
  thread_local_.last_step_action_ = step_action;
919
  thread_local_.step_count_ = step_count;
920

    
921
  // Get the frame where the execution has stopped and skip the debug frame if
922
  // any. The debug frame will only be present if execution was stopped due to
923
  // hitting a break point. In other situations (e.g. unhandled exception) the
924
  // debug frame is not present.
925
  StackFrame::Id id = break_frame_id();
926
  if (id == StackFrame::NO_ID) {
927
    // If there is no JavaScript stack don't do anything.
928
    return;
929
  }
930
  JavaScriptFrameIterator frames_it(id);
931
  JavaScriptFrame* frame = frames_it.frame();
932

    
933
  // First of all ensure there is one-shot break points in the top handler
934
  // if any.
935
  FloodHandlerWithOneShot();
936

    
937
  // If the function on the top frame is unresolved perform step out. This will
938
  // be the case when calling unknown functions and having the debugger stopped
939
  // in an unhandled exception.
940
  if (!frame->function()->IsJSFunction()) {
941
    // Step out: Find the calling JavaScript frame and flood it with
942
    // breakpoints.
943
    frames_it.Advance();
944
    // Fill the function to return to with one-shot break points.
945
    JSFunction* function = JSFunction::cast(frames_it.frame()->function());
946
    FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
947
    return;
948
  }
949

    
950
  // Get the debug info (create it if it does not exist).
951
  Handle<SharedFunctionInfo> shared =
952
      Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
953
  if (!EnsureDebugInfo(shared)) {
954
    // Return if ensuring debug info failed.
955
    return;
956
  }
957
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
958

    
959
  // Find the break location where execution has stopped.
960
  BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
961
  it.FindBreakLocationFromAddress(frame->pc());
962

    
963
  // Compute whether or not the target is a call target.
964
  bool is_call_target = false;
965
  if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
966
    Address target = it.rinfo()->target_address();
967
    Code* code = Code::GetCodeFromTargetAddress(target);
968
    if (code->is_call_stub()) is_call_target = true;
969
  }
970

    
971
  // If this is the last break code target step out is the only possibility.
972
  if (it.IsExit() || step_action == StepOut) {
973
    // Step out: If there is a JavaScript caller frame, we need to
974
    // flood it with breakpoints.
975
    frames_it.Advance();
976
    if (!frames_it.done()) {
977
      // Fill the function to return to with one-shot break points.
978
      JSFunction* function = JSFunction::cast(frames_it.frame()->function());
979
      FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
980
    }
981
  } else if (!(is_call_target || RelocInfo::IsConstructCall(it.rmode())) ||
982
             step_action == StepNext || step_action == StepMin) {
983
    // Step next or step min.
984

    
985
    // Fill the current function with one-shot break points.
986
    FloodWithOneShot(shared);
987

    
988
    // Remember source position and frame to handle step next.
989
    thread_local_.last_statement_position_ =
990
        debug_info->code()->SourceStatementPosition(frame->pc());
991
    thread_local_.last_fp_ = frame->fp();
992
  } else {
993
    // Fill the current function with one-shot break points even for step in on
994
    // a call target as the function called might be a native function for
995
    // which step in will not stop.
996
    FloodWithOneShot(shared);
997

    
998
    // Step in or Step in min
999
    it.PrepareStepIn();
1000
    ActivateStepIn(frame);
1001
  }
1002
}
1003

    
1004

    
1005
// Check whether the current debug break should be reported to the debugger. It
1006
// is used to have step next and step in only report break back to the debugger
1007
// if on a different frame or in a different statement. In some situations
1008
// there will be several break points in the same statement when the code is
1009
// flooded with one-shot break points. This function helps to perform several
1010
// steps before reporting break back to the debugger.
1011
bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1012
                             JavaScriptFrame* frame) {
1013
  // If the step last action was step next or step in make sure that a new
1014
  // statement is hit.
1015
  if (thread_local_.last_step_action_ == StepNext ||
1016
      thread_local_.last_step_action_ == StepIn) {
1017
    // Never continue if returning from function.
1018
    if (break_location_iterator->IsExit()) return false;
1019

    
1020
    // Continue if we are still on the same frame and in the same statement.
1021
    int current_statement_position =
1022
        break_location_iterator->code()->SourceStatementPosition(frame->pc());
1023
    return thread_local_.last_fp_ == frame->fp() &&
1024
        thread_local_.last_statement_position_ == current_statement_position;
1025
  }
1026

    
1027
  // No step next action - don't continue.
1028
  return false;
1029
}
1030

    
1031

    
1032
// Check whether the code object at the specified address is a debug break code
1033
// object.
1034
bool Debug::IsDebugBreak(Address addr) {
1035
  Code* code = Code::GetCodeFromTargetAddress(addr);
1036
  return code->ic_state() == DEBUG_BREAK;
1037
}
1038

    
1039

    
1040
// Check whether a code stub with the specified major key is a possible break
1041
// point location when looking for source break locations.
1042
bool Debug::IsSourceBreakStub(Code* code) {
1043
  CodeStub::Major major_key = code->major_key();
1044
  return major_key == CodeStub::CallFunction;
1045
}
1046

    
1047

    
1048
// Check whether a code stub with the specified major key is a possible break
1049
// location.
1050
bool Debug::IsBreakStub(Code* code) {
1051
  CodeStub::Major major_key = code->major_key();
1052
  return major_key == CodeStub::CallFunction ||
1053
         major_key == CodeStub::StackCheck;
1054
}
1055

    
1056

    
1057
// Find the builtin to use for invoking the debug break
1058
Handle<Code> Debug::FindDebugBreak(RelocInfo* rinfo) {
1059
  // Find the builtin debug break function matching the calling convention
1060
  // used by the call site.
1061
  RelocInfo::Mode mode = rinfo->rmode();
1062

    
1063
  if (RelocInfo::IsCodeTarget(mode)) {
1064
    Address target = rinfo->target_address();
1065
    Code* code = Code::GetCodeFromTargetAddress(target);
1066
    if (code->is_inline_cache_stub()) {
1067
      if (code->is_call_stub()) {
1068
        return ComputeCallDebugBreak(code->arguments_count());
1069
      }
1070
      if (code->is_load_stub()) {
1071
        return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak));
1072
      }
1073
      if (code->is_store_stub()) {
1074
        return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak));
1075
      }
1076
      if (code->is_keyed_load_stub()) {
1077
        Handle<Code> result =
1078
            Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
1079
        return result;
1080
      }
1081
      if (code->is_keyed_store_stub()) {
1082
        Handle<Code> result =
1083
            Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
1084
        return result;
1085
      }
1086
    }
1087
    if (RelocInfo::IsConstructCall(mode)) {
1088
      Handle<Code> result =
1089
          Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak));
1090
      return result;
1091
    }
1092
    if (code->kind() == Code::STUB) {
1093
      ASSERT(code->major_key() == CodeStub::CallFunction ||
1094
             code->major_key() == CodeStub::StackCheck);
1095
      Handle<Code> result =
1096
          Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
1097
      return result;
1098
    }
1099
  }
1100

    
1101
  UNREACHABLE();
1102
  return Handle<Code>::null();
1103
}
1104

    
1105

    
1106
// Simple function for returning the source positions for active break points.
1107
Handle<Object> Debug::GetSourceBreakLocations(
1108
    Handle<SharedFunctionInfo> shared) {
1109
  if (!HasDebugInfo(shared)) return Handle<Object>(Heap::undefined_value());
1110
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1111
  if (debug_info->GetBreakPointCount() == 0) {
1112
    return Handle<Object>(Heap::undefined_value());
1113
  }
1114
  Handle<FixedArray> locations =
1115
      Factory::NewFixedArray(debug_info->GetBreakPointCount());
1116
  int count = 0;
1117
  for (int i = 0; i < debug_info->break_points()->length(); i++) {
1118
    if (!debug_info->break_points()->get(i)->IsUndefined()) {
1119
      BreakPointInfo* break_point_info =
1120
          BreakPointInfo::cast(debug_info->break_points()->get(i));
1121
      if (break_point_info->GetBreakPointCount() > 0) {
1122
        locations->set(count++, break_point_info->statement_position());
1123
      }
1124
    }
1125
  }
1126
  return locations;
1127
}
1128

    
1129

    
1130
void Debug::NewBreak(StackFrame::Id break_frame_id) {
1131
  thread_local_.break_frame_id_ = break_frame_id;
1132
  thread_local_.break_id_ = ++thread_local_.break_count_;
1133
}
1134

    
1135

    
1136
void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) {
1137
  thread_local_.break_frame_id_ = break_frame_id;
1138
  thread_local_.break_id_ = break_id;
1139
}
1140

    
1141

    
1142
// Handle stepping into a function.
1143
void Debug::HandleStepIn(Handle<JSFunction> function,
1144
                         Address fp,
1145
                         bool is_constructor) {
1146
  // If the frame pointer is not supplied by the caller find it.
1147
  if (fp == 0) {
1148
    StackFrameIterator it;
1149
    it.Advance();
1150
    // For constructor functions skip another frame.
1151
    if (is_constructor) {
1152
      ASSERT(it.frame()->is_construct());
1153
      it.Advance();
1154
    }
1155
    fp = it.frame()->fp();
1156
  }
1157

    
1158
  // Flood the function with one-shot break points if it is called from where
1159
  // step into was requested.
1160
  if (fp == Debug::step_in_fp()) {
1161
    // Don't allow step into functions in the native context.
1162
    if (function->context()->global() != Top::context()->builtins()) {
1163
      if (function->shared()->code() ==
1164
          Builtins::builtin(Builtins::FunctionApply) ||
1165
          function->shared()->code() ==
1166
          Builtins::builtin(Builtins::FunctionCall)) {
1167
        // Handle function.apply and function.call separately to flood the
1168
        // function to be called and not the code for Builtins::FunctionApply or
1169
        // Builtins::FunctionCall. At the point of the call IC to call either
1170
        // Builtins::FunctionApply or Builtins::FunctionCall the expression
1171
        // stack has the following content:
1172
        //   symbol "apply" or "call"
1173
        //   function apply or call was called on
1174
        //   receiver for apply or call (first parameter to apply or call)
1175
        //   ... further arguments to apply or call.
1176
        JavaScriptFrameIterator it;
1177
        ASSERT(it.frame()->fp() == fp);
1178
        ASSERT(it.frame()->GetExpression(1)->IsJSFunction());
1179
        if (it.frame()->GetExpression(1)->IsJSFunction()) {
1180
          Handle<JSFunction>
1181
              actual_function(JSFunction::cast(it.frame()->GetExpression(1)));
1182
          Handle<SharedFunctionInfo> actual_shared(actual_function->shared());
1183
          Debug::FloodWithOneShot(actual_shared);
1184
        }
1185
      } else {
1186
        Debug::FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
1187
      }
1188
    }
1189
  }
1190
}
1191

    
1192

    
1193
void Debug::ClearStepping() {
1194
  // Clear the various stepping setup.
1195
  ClearOneShot();
1196
  ClearStepIn();
1197
  ClearStepNext();
1198

    
1199
  // Clear multiple step counter.
1200
  thread_local_.step_count_ = 0;
1201
}
1202

    
1203
// Clears all the one-shot break points that are currently set. Normally this
1204
// function is called each time a break point is hit as one shot break points
1205
// are used to support stepping.
1206
void Debug::ClearOneShot() {
1207
  // The current implementation just runs through all the breakpoints. When the
1208
  // last break point for a function is removed that function is automatically
1209
  // removed from the list.
1210

    
1211
  DebugInfoListNode* node = debug_info_list_;
1212
  while (node != NULL) {
1213
    BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1214
    while (!it.Done()) {
1215
      it.ClearOneShot();
1216
      it.Next();
1217
    }
1218
    node = node->next();
1219
  }
1220
}
1221

    
1222

    
1223
void Debug::ActivateStepIn(StackFrame* frame) {
1224
  thread_local_.step_into_fp_ = frame->fp();
1225
}
1226

    
1227

    
1228
void Debug::ClearStepIn() {
1229
  thread_local_.step_into_fp_ = 0;
1230
}
1231

    
1232

    
1233
void Debug::ClearStepNext() {
1234
  thread_local_.last_step_action_ = StepNone;
1235
  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1236
  thread_local_.last_fp_ = 0;
1237
}
1238

    
1239

    
1240
bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
1241
  if (shared->is_compiled()) return true;
1242
  return CompileLazyShared(shared, CLEAR_EXCEPTION, 0);
1243
}
1244

    
1245

    
1246
// Ensures the debug information is present for shared.
1247
bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
1248
  // Return if we already have the debug info for shared.
1249
  if (HasDebugInfo(shared)) return true;
1250

    
1251
  // Ensure shared in compiled. Return false if this failed.
1252
  if (!EnsureCompiled(shared)) return false;
1253

    
1254
  // Create the debug info object.
1255
  Handle<DebugInfo> debug_info = Factory::NewDebugInfo(shared);
1256

    
1257
  // Add debug info to the list.
1258
  DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
1259
  node->set_next(debug_info_list_);
1260
  debug_info_list_ = node;
1261

    
1262
  // Now there is at least one break point.
1263
  has_break_points_ = true;
1264

    
1265
  return true;
1266
}
1267

    
1268

    
1269
void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
1270
  ASSERT(debug_info_list_ != NULL);
1271
  // Run through the debug info objects to find this one and remove it.
1272
  DebugInfoListNode* prev = NULL;
1273
  DebugInfoListNode* current = debug_info_list_;
1274
  while (current != NULL) {
1275
    if (*current->debug_info() == *debug_info) {
1276
      // Unlink from list. If prev is NULL we are looking at the first element.
1277
      if (prev == NULL) {
1278
        debug_info_list_ = current->next();
1279
      } else {
1280
        prev->set_next(current->next());
1281
      }
1282
      current->debug_info()->shared()->set_debug_info(Heap::undefined_value());
1283
      delete current;
1284

    
1285
      // If there are no more debug info objects there are not more break
1286
      // points.
1287
      has_break_points_ = debug_info_list_ != NULL;
1288

    
1289
      return;
1290
    }
1291
    // Move to next in list.
1292
    prev = current;
1293
    current = current->next();
1294
  }
1295
  UNREACHABLE();
1296
}
1297

    
1298

    
1299
void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
1300
  HandleScope scope;
1301

    
1302
  // Get the executing function in which the debug break occurred.
1303
  Handle<SharedFunctionInfo> shared =
1304
      Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
1305
  if (!EnsureDebugInfo(shared)) {
1306
    // Return if we failed to retrieve the debug info.
1307
    return;
1308
  }
1309
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1310
  Handle<Code> code(debug_info->code());
1311
  Handle<Code> original_code(debug_info->original_code());
1312
#ifdef DEBUG
1313
  // Get the code which is actually executing.
1314
  Handle<Code> frame_code(frame->code());
1315
  ASSERT(frame_code.is_identical_to(code));
1316
#endif
1317

    
1318
  // Find the call address in the running code. This address holds the call to
1319
  // either a DebugBreakXXX or to the debug break return entry code if the
1320
  // break point is still active after processing the break point.
1321
  Address addr = frame->pc() - Assembler::kTargetAddrToReturnAddrDist;
1322

    
1323
  // Check if the location is at JS exit.
1324
  bool at_js_exit = false;
1325
  RelocIterator it(debug_info->code());
1326
  while (!it.done()) {
1327
    if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
1328
      at_js_exit = it.rinfo()->pc() == addr - 1;
1329
    }
1330
    it.next();
1331
  }
1332

    
1333
  // Handle the jump to continue execution after break point depending on the
1334
  // break location.
1335
  if (at_js_exit) {
1336
    // First check if the call in the code is still the debug break return
1337
    // entry code. If it is the break point is still active. If not the break
1338
    // point was removed during break point processing.
1339
    if (Assembler::target_address_at(addr) ==
1340
        debug_break_return_entry()->entry()) {
1341
      // Break point still active. Jump to the corresponding place in the
1342
      // original code.
1343
      addr +=  original_code->instruction_start() - code->instruction_start();
1344
    }
1345

    
1346
    // Move one byte back to where the call instruction was placed.
1347
    thread_local_.after_break_target_ = addr - 1;
1348
  } else {
1349
    // Check if there still is a debug break call at the target address. If the
1350
    // break point has been removed it will have disappeared. If it have
1351
    // disappeared don't try to look in the original code as the running code
1352
    // will have the right address. This takes care of the case where the last
1353
    // break point is removed from the function and therefore no "original code"
1354
    // is available. If the debug break call is still there find the address in
1355
    // the original code.
1356
    if (IsDebugBreak(Assembler::target_address_at(addr))) {
1357
      // If the break point is still there find the call address which was
1358
      // overwritten in the original code by the call to DebugBreakXXX.
1359

    
1360
      // Find the corresponding address in the original code.
1361
      addr += original_code->instruction_start() - code->instruction_start();
1362
    }
1363

    
1364
    // Install jump to the call address in the original code. This will be the
1365
    // call which was overwritten by the call to DebugBreakXXX.
1366
    thread_local_.after_break_target_ = Assembler::target_address_at(addr);
1367
  }
1368
}
1369

    
1370

    
1371
bool Debug::IsDebugGlobal(GlobalObject* global) {
1372
  return IsLoaded() && global == Debug::debug_context()->global();
1373
}
1374

    
1375

    
1376
void Debug::ClearMirrorCache() {
1377
  HandleScope scope;
1378
  ASSERT(Top::context() == *Debug::debug_context());
1379

    
1380
  // Clear the mirror cache.
1381
  Handle<String> function_name =
1382
      Factory::LookupSymbol(CStrVector("ClearMirrorCache"));
1383
  Handle<Object> fun(Top::global()->GetProperty(*function_name));
1384
  ASSERT(fun->IsJSFunction());
1385
  bool caught_exception;
1386
  Handle<Object> js_object = Execution::TryCall(
1387
      Handle<JSFunction>::cast(fun),
1388
      Handle<JSObject>(Debug::debug_context()->global()),
1389
      0, NULL, &caught_exception);
1390
}
1391

    
1392

    
1393
Mutex* Debugger::debugger_access_ = OS::CreateMutex();
1394
Handle<Object> Debugger::event_listener_ = Handle<Object>();
1395
Handle<Object> Debugger::event_listener_data_ = Handle<Object>();
1396
bool Debugger::compiling_natives_ = false;
1397
bool Debugger::is_loading_debugger_ = false;
1398
bool Debugger::never_unload_debugger_ = false;
1399
DebugMessageThread* Debugger::message_thread_ = NULL;
1400
v8::DebugMessageHandler Debugger::message_handler_ = NULL;
1401
bool Debugger::message_handler_cleared_ = false;
1402
void* Debugger::message_handler_data_ = NULL;
1403
v8::DebugHostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
1404
void* Debugger::host_dispatch_handler_data_ = NULL;
1405
DebuggerAgent* Debugger::agent_ = NULL;
1406
LockingMessageQueue Debugger::command_queue_(kQueueInitialSize);
1407
LockingMessageQueue Debugger::message_queue_(kQueueInitialSize);
1408
Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0);
1409
Semaphore* Debugger::message_received_ = OS::CreateSemaphore(0);
1410

    
1411

    
1412
Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
1413
                                      int argc, Object*** argv,
1414
                                      bool* caught_exception) {
1415
  ASSERT(Top::context() == *Debug::debug_context());
1416

    
1417
  // Create the execution state object.
1418
  Handle<String> constructor_str = Factory::LookupSymbol(constructor_name);
1419
  Handle<Object> constructor(Top::global()->GetProperty(*constructor_str));
1420
  ASSERT(constructor->IsJSFunction());
1421
  if (!constructor->IsJSFunction()) {
1422
    *caught_exception = true;
1423
    return Factory::undefined_value();
1424
  }
1425
  Handle<Object> js_object = Execution::TryCall(
1426
      Handle<JSFunction>::cast(constructor),
1427
      Handle<JSObject>(Debug::debug_context()->global()), argc, argv,
1428
      caught_exception);
1429
  return js_object;
1430
}
1431

    
1432

    
1433
Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
1434
  // Create the execution state object.
1435
  Handle<Object> break_id = Factory::NewNumberFromInt(Debug::break_id());
1436
  const int argc = 1;
1437
  Object** argv[argc] = { break_id.location() };
1438
  return MakeJSObject(CStrVector("MakeExecutionState"),
1439
                      argc, argv, caught_exception);
1440
}
1441

    
1442

    
1443
Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
1444
                                        Handle<Object> break_points_hit,
1445
                                        bool* caught_exception) {
1446
  // Create the new break event object.
1447
  const int argc = 2;
1448
  Object** argv[argc] = { exec_state.location(),
1449
                          break_points_hit.location() };
1450
  return MakeJSObject(CStrVector("MakeBreakEvent"),
1451
                      argc,
1452
                      argv,
1453
                      caught_exception);
1454
}
1455

    
1456

    
1457
Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
1458
                                            Handle<Object> exception,
1459
                                            bool uncaught,
1460
                                            bool* caught_exception) {
1461
  // Create the new exception event object.
1462
  const int argc = 3;
1463
  Object** argv[argc] = { exec_state.location(),
1464
                          exception.location(),
1465
                          uncaught ? Factory::true_value().location() :
1466
                                     Factory::false_value().location()};
1467
  return MakeJSObject(CStrVector("MakeExceptionEvent"),
1468
                      argc, argv, caught_exception);
1469
}
1470

    
1471

    
1472
Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
1473
                                              bool* caught_exception) {
1474
  // Create the new function event object.
1475
  const int argc = 1;
1476
  Object** argv[argc] = { function.location() };
1477
  return MakeJSObject(CStrVector("MakeNewFunctionEvent"),
1478
                      argc, argv, caught_exception);
1479
}
1480

    
1481

    
1482
Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
1483
                                          bool before,
1484
                                          bool* caught_exception) {
1485
  // Create the compile event object.
1486
  Handle<Object> exec_state = MakeExecutionState(caught_exception);
1487
  Handle<Object> script_wrapper = GetScriptWrapper(script);
1488
  const int argc = 3;
1489
  Object** argv[argc] = { exec_state.location(),
1490
                          script_wrapper.location(),
1491
                          before ? Factory::true_value().location() :
1492
                                   Factory::false_value().location() };
1493

    
1494
  return MakeJSObject(CStrVector("MakeCompileEvent"),
1495
                      argc,
1496
                      argv,
1497
                      caught_exception);
1498
}
1499

    
1500

    
1501
void Debugger::OnException(Handle<Object> exception, bool uncaught) {
1502
  HandleScope scope;
1503

    
1504
  // Bail out based on state or if there is no listener for this event
1505
  if (Debug::InDebugger()) return;
1506
  if (!Debugger::EventActive(v8::Exception)) return;
1507

    
1508
  // Bail out if exception breaks are not active
1509
  if (uncaught) {
1510
    // Uncaught exceptions are reported by either flags.
1511
    if (!(Debug::break_on_uncaught_exception() ||
1512
          Debug::break_on_exception())) return;
1513
  } else {
1514
    // Caught exceptions are reported is activated.
1515
    if (!Debug::break_on_exception()) return;
1516
  }
1517

    
1518
  // Enter the debugger.
1519
  EnterDebugger debugger;
1520
  if (debugger.FailedToEnter()) return;
1521

    
1522
  // Clear all current stepping setup.
1523
  Debug::ClearStepping();
1524
  // Create the event data object.
1525
  bool caught_exception = false;
1526
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
1527
  Handle<Object> event_data;
1528
  if (!caught_exception) {
1529
    event_data = MakeExceptionEvent(exec_state, exception, uncaught,
1530
                                    &caught_exception);
1531
  }
1532
  // Bail out and don't call debugger if exception.
1533
  if (caught_exception) {
1534
    return;
1535
  }
1536

    
1537
  // Process debug event
1538
  ProcessDebugEvent(v8::Exception, event_data, false);
1539
  // Return to continue execution from where the exception was thrown.
1540
}
1541

    
1542

    
1543
void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
1544
                            bool auto_continue) {
1545
  HandleScope scope;
1546

    
1547
  // Debugger has already been entered by caller.
1548
  ASSERT(Top::context() == *Debug::debug_context());
1549

    
1550
  // Bail out if there is no listener for this event
1551
  if (!Debugger::EventActive(v8::Break)) return;
1552

    
1553
  // Debugger must be entered in advance.
1554
  ASSERT(Top::context() == *Debug::debug_context());
1555

    
1556
  // Create the event data object.
1557
  bool caught_exception = false;
1558
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
1559
  Handle<Object> event_data;
1560
  if (!caught_exception) {
1561
    event_data = MakeBreakEvent(exec_state, break_points_hit,
1562
                                &caught_exception);
1563
  }
1564
  // Bail out and don't call debugger if exception.
1565
  if (caught_exception) {
1566
    return;
1567
  }
1568

    
1569
  // Process debug event
1570
  ProcessDebugEvent(v8::Break, event_data, auto_continue);
1571
}
1572

    
1573

    
1574
void Debugger::OnBeforeCompile(Handle<Script> script) {
1575
  HandleScope scope;
1576

    
1577
  // Bail out based on state or if there is no listener for this event
1578
  if (Debug::InDebugger()) return;
1579
  if (compiling_natives()) return;
1580
  if (!EventActive(v8::BeforeCompile)) return;
1581

    
1582
  // Enter the debugger.
1583
  EnterDebugger debugger;
1584
  if (debugger.FailedToEnter()) return;
1585

    
1586
  // Create the event data object.
1587
  bool caught_exception = false;
1588
  Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception);
1589
  // Bail out and don't call debugger if exception.
1590
  if (caught_exception) {
1591
    return;
1592
  }
1593

    
1594
  // Process debug event
1595
  ProcessDebugEvent(v8::BeforeCompile, event_data, false);
1596
}
1597

    
1598

    
1599
// Handle debugger actions when a new script is compiled.
1600
void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
1601
  HandleScope scope;
1602

    
1603
  // No compile events while compiling natives.
1604
  if (compiling_natives()) return;
1605

    
1606
  // No more to do if not debugging.
1607
  if (!IsDebuggerActive()) return;
1608

    
1609
  // Store whether in debugger before entering debugger.
1610
  bool in_debugger = Debug::InDebugger();
1611

    
1612
  // Enter the debugger.
1613
  EnterDebugger debugger;
1614
  if (debugger.FailedToEnter()) return;
1615

    
1616
  // If debugging there might be script break points registered for this
1617
  // script. Make sure that these break points are set.
1618

    
1619
  // Get the function UpdateScriptBreakPoints (defined in debug-delay.js).
1620
  Handle<Object> update_script_break_points =
1621
      Handle<Object>(Debug::debug_context()->global()->GetProperty(
1622
          *Factory::LookupAsciiSymbol("UpdateScriptBreakPoints")));
1623
  if (!update_script_break_points->IsJSFunction()) {
1624
    return;
1625
  }
1626
  ASSERT(update_script_break_points->IsJSFunction());
1627

    
1628
  // Wrap the script object in a proper JS object before passing it
1629
  // to JavaScript.
1630
  Handle<JSValue> wrapper = GetScriptWrapper(script);
1631

    
1632
  // Call UpdateScriptBreakPoints expect no exceptions.
1633
  bool caught_exception = false;
1634
  const int argc = 1;
1635
  Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) };
1636
  Handle<Object> result = Execution::TryCall(
1637
      Handle<JSFunction>::cast(update_script_break_points),
1638
      Top::builtins(), argc, argv,
1639
      &caught_exception);
1640
  if (caught_exception) {
1641
    return;
1642
  }
1643
  // Bail out based on state or if there is no listener for this event
1644
  if (in_debugger) return;
1645
  if (!Debugger::EventActive(v8::AfterCompile)) return;
1646

    
1647
  // Create the compile state object.
1648
  Handle<Object> event_data = MakeCompileEvent(script,
1649
                                               false,
1650
                                               &caught_exception);
1651
  // Bail out and don't call debugger if exception.
1652
  if (caught_exception) {
1653
    return;
1654
  }
1655
  // Process debug event
1656
  ProcessDebugEvent(v8::AfterCompile, event_data, false);
1657
}
1658

    
1659

    
1660
void Debugger::OnNewFunction(Handle<JSFunction> function) {
1661
  return;
1662
  HandleScope scope;
1663

    
1664
  // Bail out based on state or if there is no listener for this event
1665
  if (Debug::InDebugger()) return;
1666
  if (compiling_natives()) return;
1667
  if (!Debugger::EventActive(v8::NewFunction)) return;
1668

    
1669
  // Enter the debugger.
1670
  EnterDebugger debugger;
1671
  if (debugger.FailedToEnter()) return;
1672

    
1673
  // Create the event object.
1674
  bool caught_exception = false;
1675
  Handle<Object> event_data = MakeNewFunctionEvent(function, &caught_exception);
1676
  // Bail out and don't call debugger if exception.
1677
  if (caught_exception) {
1678
    return;
1679
  }
1680
  // Process debug event.
1681
  ProcessDebugEvent(v8::NewFunction, event_data, false);
1682
}
1683

    
1684

    
1685
void Debugger::ProcessDebugEvent(v8::DebugEvent event,
1686
                                 Handle<Object> event_data,
1687
                                 bool auto_continue) {
1688
  HandleScope scope;
1689

    
1690
  // Create the execution state.
1691
  bool caught_exception = false;
1692
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
1693
  if (caught_exception) {
1694
    return;
1695
  }
1696
  // First notify the message handler if any.
1697
  if (message_handler_ != NULL) {
1698
    NotifyMessageHandler(event, exec_state, event_data, auto_continue);
1699
  }
1700
  // Notify registered debug event listener. This can be either a C or a
1701
  // JavaScript function.
1702
  if (!event_listener_.is_null()) {
1703
    if (event_listener_->IsProxy()) {
1704
      // C debug event listener.
1705
      Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_));
1706
      v8::DebugEventCallback callback =
1707
            FUNCTION_CAST<v8::DebugEventCallback>(callback_obj->proxy());
1708
      callback(event,
1709
               v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1710
               v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)),
1711
               v8::Utils::ToLocal(Handle<Object>::cast(event_listener_data_)));
1712
    } else {
1713
      // JavaScript debug event listener.
1714
      ASSERT(event_listener_->IsJSFunction());
1715
      Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
1716

    
1717
      // Invoke the JavaScript debug event listener.
1718
      const int argc = 4;
1719
      Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(),
1720
                              exec_state.location(),
1721
                              event_data.location(),
1722
                              event_listener_data_.location() };
1723
      Handle<Object> result = Execution::TryCall(fun, Top::global(),
1724
                                                 argc, argv, &caught_exception);
1725
      if (caught_exception) {
1726
        // Silently ignore exceptions from debug event listeners.
1727
      }
1728
    }
1729
  }
1730

    
1731
  // Clear the mirror cache.
1732
  Debug::ClearMirrorCache();
1733
}
1734

    
1735

    
1736
void Debugger::UnloadDebugger() {
1737
  // Make sure that there are no breakpoints left.
1738
  Debug::ClearAllBreakPoints();
1739

    
1740
  // Unload the debugger if feasible.
1741
  if (!never_unload_debugger_) {
1742
    Debug::Unload();
1743
  }
1744

    
1745
  // Clear the flag indicating that the message handler was recently cleared.
1746
  message_handler_cleared_ = false;
1747
}
1748

    
1749

    
1750
void Debugger::NotifyMessageHandler(v8::DebugEvent event,
1751
                                    Handle<Object> exec_state,
1752
                                    Handle<Object> event_data,
1753
                                    bool auto_continue) {
1754
  HandleScope scope;
1755

    
1756
  if (!Debug::Load()) return;
1757

    
1758
  // Process the individual events.
1759
  bool interactive = false;
1760
  switch (event) {
1761
    case v8::Break:
1762
      interactive = true;  // Break event is always interactive
1763
      break;
1764
    case v8::Exception:
1765
      interactive = true;  // Exception event is always interactive
1766
      break;
1767
    case v8::BeforeCompile:
1768
      break;
1769
    case v8::AfterCompile:
1770
      break;
1771
    case v8::NewFunction:
1772
      break;
1773
    default:
1774
      UNREACHABLE();
1775
  }
1776

    
1777
  // Done if not interactive.
1778
  if (!interactive) return;
1779

    
1780
  // Get the DebugCommandProcessor.
1781
  v8::Local<v8::Object> api_exec_state =
1782
      v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
1783
  v8::Local<v8::String> fun_name =
1784
      v8::String::New("debugCommandProcessor");
1785
  v8::Local<v8::Function> fun =
1786
      v8::Function::Cast(*api_exec_state->Get(fun_name));
1787
  v8::TryCatch try_catch;
1788
  v8::Local<v8::Object> cmd_processor =
1789
      v8::Object::Cast(*fun->Call(api_exec_state, 0, NULL));
1790
  if (try_catch.HasCaught()) {
1791
    PrintLn(try_catch.Exception());
1792
    return;
1793
  }
1794

    
1795
  // Notify the debugger that a debug event has occurred unless auto continue is
1796
  // active in which case no event is send.
1797
  if (!auto_continue) {
1798
    bool success = SendEventMessage(event_data);
1799
    if (!success) {
1800
      // If failed to notify debugger just continue running.
1801
      return;
1802
    }
1803
  }
1804

    
1805
  // Process requests from the debugger.
1806
  while (true) {
1807
    // Wait for new command in the queue.
1808
    command_received_->Wait();
1809

    
1810
    // The debug command interrupt flag might have been set when the command was
1811
    // added.
1812
    StackGuard::Continue(DEBUGCOMMAND);
1813

    
1814
    // Get the command from the queue.
1815
    Vector<uint16_t> command = command_queue_.Get();
1816
    Logger::DebugTag("Got request from command queue, in interactive loop.");
1817
    if (!Debugger::IsDebuggerActive()) {
1818
      return;
1819
    }
1820

    
1821
    // Check if the command is a host dispatch.
1822
    if (command[0] == 0) {
1823
      if (Debugger::host_dispatch_handler_) {
1824
        int32_t dispatch = (command[1] << 16) | command[2];
1825
        Debugger::host_dispatch_handler_(reinterpret_cast<void*>(dispatch),
1826
                                         Debugger::host_dispatch_handler_data_);
1827
      }
1828
      if (auto_continue && !HasCommands()) {
1829
        return;
1830
      }
1831
      continue;
1832
    }
1833

    
1834
    // Invoke JavaScript to process the debug request.
1835
    v8::Local<v8::String> fun_name;
1836
    v8::Local<v8::Function> fun;
1837
    v8::Local<v8::Value> request;
1838
    v8::TryCatch try_catch;
1839
    fun_name = v8::String::New("processDebugRequest");
1840
    fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
1841
    request = v8::String::New(reinterpret_cast<uint16_t*>(command.start()),
1842
                              command.length());
1843
    static const int kArgc = 1;
1844
    v8::Handle<Value> argv[kArgc] = { request };
1845
    v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
1846

    
1847
    // Get the response.
1848
    v8::Local<v8::String> response;
1849
    bool running = false;
1850
    if (!try_catch.HasCaught()) {
1851
      // Get response string.
1852
      if (!response_val->IsUndefined()) {
1853
        response = v8::String::Cast(*response_val);
1854
      } else {
1855
        response = v8::String::New("");
1856
      }
1857

    
1858
      // Log the JSON request/response.
1859
      if (FLAG_trace_debug_json) {
1860
        PrintLn(request);
1861
        PrintLn(response);
1862
      }
1863

    
1864
      // Get the running state.
1865
      fun_name = v8::String::New("isRunning");
1866
      fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
1867
      static const int kArgc = 1;
1868
      v8::Handle<Value> argv[kArgc] = { response };
1869
      v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv);
1870
      if (!try_catch.HasCaught()) {
1871
        running = running_val->ToBoolean()->Value();
1872
      }
1873
    } else {
1874
      // In case of failure the result text is the exception text.
1875
      response = try_catch.Exception()->ToString();
1876
    }
1877

    
1878
    // Convert text result to C string.
1879
    v8::String::Value val(response);
1880
    Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
1881
                        response->Length());
1882

    
1883
    // Return the result.
1884
    SendMessage(str);
1885

    
1886
    // Return from debug event processing if either the VM is put into the
1887
    // runnning state (through a continue command) or auto continue is active
1888
    // and there are no more commands queued.
1889
    if (running || (auto_continue && !HasCommands())) {
1890
      return;
1891
    }
1892
  }
1893
}
1894

    
1895

    
1896
void Debugger::SetEventListener(Handle<Object> callback,
1897
                                Handle<Object> data) {
1898
  HandleScope scope;
1899

    
1900
  // Clear the global handles for the event listener and the event listener data
1901
  // object.
1902
  if (!event_listener_.is_null()) {
1903
    GlobalHandles::Destroy(
1904
        reinterpret_cast<Object**>(event_listener_.location()));
1905
    event_listener_ = Handle<Object>();
1906
  }
1907
  if (!event_listener_data_.is_null()) {
1908
    GlobalHandles::Destroy(
1909
        reinterpret_cast<Object**>(event_listener_data_.location()));
1910
    event_listener_data_ = Handle<Object>();
1911
  }
1912

    
1913
  // If there is a new debug event listener register it together with its data
1914
  // object.
1915
  if (!callback->IsUndefined() && !callback->IsNull()) {
1916
    event_listener_ = Handle<Object>::cast(GlobalHandles::Create(*callback));
1917
    if (data.is_null()) {
1918
      data = Factory::undefined_value();
1919
    }
1920
    event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data));
1921
  }
1922

    
1923
  // Unload the debugger if event listener cleared.
1924
  if (callback->IsUndefined()) {
1925
    UnloadDebugger();
1926
  }
1927
}
1928

    
1929

    
1930
void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data,
1931
                                 bool message_handler_thread) {
1932
  ScopedLock with(debugger_access_);
1933

    
1934
  message_handler_ = handler;
1935
  message_handler_data_ = data;
1936
  if (handler != NULL) {
1937
    if (!message_thread_ && message_handler_thread) {
1938
      message_thread_ = new DebugMessageThread();
1939
      message_thread_->Start();
1940
    }
1941
  } else {
1942
    // Indicate that the message handler was recently cleared.
1943
    message_handler_cleared_ = true;
1944

    
1945
    // Send an empty command to the debugger if in a break to make JavaScript
1946
    // run again if the debugger is closed.
1947
    if (Debug::InDebugger()) {
1948
      ProcessCommand(Vector<const uint16_t>::empty());
1949
    }
1950
  }
1951
}
1952

    
1953

    
1954
void Debugger::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
1955
                                      void* data) {
1956
  host_dispatch_handler_ = handler;
1957
  host_dispatch_handler_data_ = data;
1958
}
1959

    
1960

    
1961
// Calls the registered debug message handler. This callback is part of the
1962
// public API. Messages are kept internally as Vector<uint16_t> strings, which
1963
// are allocated in various places and deallocated by the calling function
1964
// sometime after this call.
1965
void Debugger::InvokeMessageHandler(Vector<uint16_t> message) {
1966
  ScopedLock with(debugger_access_);
1967

    
1968
  if (message_handler_ != NULL) {
1969
    message_handler_(message.start(), message.length(), message_handler_data_);
1970
  }
1971
}
1972

    
1973

    
1974
void Debugger::SendMessage(Vector<uint16_t> message) {
1975
  if (message_thread_ == NULL) {
1976
    // If there is no message thread just invoke the message handler from the
1977
    // V8 thread.
1978
    InvokeMessageHandler(message);
1979
  } else {
1980
    // Put a copy of the message coming from V8 on the queue. The new copy of
1981
    // the event string is destroyed by the message thread.
1982
    Vector<uint16_t> message_copy = message.Clone();
1983
    Logger::DebugTag("Put message on event message_queue.");
1984
    message_queue_.Put(message_copy);
1985
    message_received_->Signal();
1986
  }
1987
}
1988

    
1989

    
1990
bool Debugger::SendEventMessage(Handle<Object> event_data) {
1991
  v8::HandleScope scope;
1992
  // Call toJSONProtocol on the debug event object.
1993
  v8::Local<v8::Object> api_event_data =
1994
      v8::Utils::ToLocal(Handle<JSObject>::cast(event_data));
1995
  v8::Local<v8::String> fun_name = v8::String::New("toJSONProtocol");
1996
  v8::Local<v8::Function> fun =
1997
      v8::Function::Cast(*api_event_data->Get(fun_name));
1998
  v8::TryCatch try_catch;
1999
  v8::Local<v8::Value> json_event = *fun->Call(api_event_data, 0, NULL);
2000
  v8::Local<v8::String> json_event_string;
2001
  if (!try_catch.HasCaught()) {
2002
    if (!json_event->IsUndefined()) {
2003
      json_event_string = json_event->ToString();
2004
      if (FLAG_trace_debug_json) {
2005
        PrintLn(json_event_string);
2006
      }
2007
      v8::String::Value val(json_event_string);
2008
      Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
2009
                           json_event_string->Length());
2010
      SendMessage(str);
2011
    } else {
2012
      SendMessage(Vector<uint16_t>::empty());
2013
    }
2014
  } else {
2015
    PrintLn(try_catch.Exception());
2016
    return false;
2017
  }
2018
  return true;
2019
}
2020

    
2021

    
2022
// Puts a command coming from the public API on the queue.  Creates
2023
// a copy of the command string managed by the debugger.  Up to this
2024
// point, the command data was managed by the API client.  Called
2025
// by the API client thread.  This is where the API client hands off
2026
// processing of the command to the DebugMessageThread thread.
2027
// The new copy of the command is destroyed in HandleCommand().
2028
void Debugger::ProcessCommand(Vector<const uint16_t> command) {
2029
  // Make a copy of the command. Need to cast away const for Clone to work.
2030
  Vector<uint16_t> command_copy =
2031
      Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
2032
                       command.length()).Clone();
2033
  Logger::DebugTag("Put command on command_queue.");
2034
  command_queue_.Put(command_copy);
2035
  command_received_->Signal();
2036

    
2037
  // Set the debug command break flag to have the command processed.
2038
  if (!Debug::InDebugger()) {
2039
    StackGuard::DebugCommand();
2040
  }
2041
}
2042

    
2043

    
2044
bool Debugger::HasCommands() {
2045
  return !command_queue_.IsEmpty();
2046
}
2047

    
2048

    
2049
void Debugger::ProcessHostDispatch(void* dispatch) {
2050
  // Puts a host dispatch comming from the public API on the queue.
2051
  uint16_t hack[3];
2052
  hack[0] = 0;
2053
  hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16;
2054
  hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF;
2055
  Logger::DebugTag("Put dispatch on command_queue.");
2056
  command_queue_.Put(Vector<uint16_t>(hack, 3).Clone());
2057
  command_received_->Signal();
2058

    
2059
  // Set the debug command break flag to have the host dispatch processed.
2060
  if (!Debug::InDebugger()) {
2061
    StackGuard::DebugCommand();
2062
  }
2063
}
2064

    
2065

    
2066
bool Debugger::IsDebuggerActive() {
2067
  ScopedLock with(debugger_access_);
2068

    
2069
  return message_handler_ != NULL || !event_listener_.is_null();
2070
}
2071

    
2072

    
2073
Handle<Object> Debugger::Call(Handle<JSFunction> fun,
2074
                              Handle<Object> data,
2075
                              bool* pending_exception) {
2076
  // When calling functions in the debugger prevent it from beeing unloaded.
2077
  Debugger::never_unload_debugger_ = true;
2078

    
2079
  // Enter the debugger.
2080
  EnterDebugger debugger;
2081
  if (debugger.FailedToEnter() || !debugger.HasJavaScriptFrames()) {
2082
    return Factory::undefined_value();
2083
  }
2084

    
2085
  // Create the execution state.
2086
  bool caught_exception = false;
2087
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2088
  if (caught_exception) {
2089
    return Factory::undefined_value();
2090
  }
2091

    
2092
  static const int kArgc = 2;
2093
  Object** argv[kArgc] = { exec_state.location(), data.location() };
2094
  Handle<Object> result = Execution::Call(fun, Factory::undefined_value(),
2095
                                          kArgc, argv, pending_exception);
2096
  return result;
2097
}
2098

    
2099

    
2100
bool Debugger::StartAgent(const char* name, int port) {
2101
  if (Socket::Setup()) {
2102
    agent_ = new DebuggerAgent(name, port);
2103
    agent_->Start();
2104
    return true;
2105
  }
2106

    
2107
  return false;
2108
}
2109

    
2110

    
2111
void Debugger::StopAgent() {
2112
  if (agent_ != NULL) {
2113
    agent_->Shutdown();
2114
    agent_->Join();
2115
    delete agent_;
2116
    agent_ = NULL;
2117
  }
2118
}
2119

    
2120

    
2121
void Debugger::TearDown() {
2122
  if (message_thread_ != NULL) {
2123
    message_thread_->Stop();
2124
    delete message_thread_;
2125
    message_thread_ = NULL;
2126
  }
2127
}
2128

    
2129

    
2130
void DebugMessageThread::Run() {
2131
  // Sends debug events to an installed debugger message callback.
2132
  while (keep_running_) {
2133
    // Wait and Get are paired so that semaphore count equals queue length.
2134
    Debugger::message_received_->Wait();
2135
    Logger::DebugTag("Get message from event message_queue.");
2136
    Vector<uint16_t> message = Debugger::message_queue_.Get();
2137
    if (message.length() > 0) {
2138
      Debugger::InvokeMessageHandler(message);
2139
    }
2140
  }
2141
}
2142

    
2143

    
2144
void DebugMessageThread::Stop() {
2145
  keep_running_ = false;
2146
  Debugger::SendMessage(Vector<uint16_t>(NULL, 0));
2147
  Join();
2148
}
2149

    
2150

    
2151
MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) {
2152
  messages_ = NewArray<Vector<uint16_t> >(size);
2153
}
2154

    
2155

    
2156
MessageQueue::~MessageQueue() {
2157
  DeleteArray(messages_);
2158
}
2159

    
2160

    
2161
Vector<uint16_t> MessageQueue::Get() {
2162
  ASSERT(!IsEmpty());
2163
  int result = start_;
2164
  start_ = (start_ + 1) % size_;
2165
  return messages_[result];
2166
}
2167

    
2168

    
2169
void MessageQueue::Put(const Vector<uint16_t>& message) {
2170
  if ((end_ + 1) % size_ == start_) {
2171
    Expand();
2172
  }
2173
  messages_[end_] = message;
2174
  end_ = (end_ + 1) % size_;
2175
}
2176

    
2177

    
2178
void MessageQueue::Expand() {
2179
  MessageQueue new_queue(size_ * 2);
2180
  while (!IsEmpty()) {
2181
    new_queue.Put(Get());
2182
  }
2183
  Vector<uint16_t>* array_to_free = messages_;
2184
  *this = new_queue;
2185
  new_queue.messages_ = array_to_free;
2186
  // Automatic destructor called on new_queue, freeing array_to_free.
2187
}
2188

    
2189

    
2190
LockingMessageQueue::LockingMessageQueue(int size) : queue_(size) {
2191
  lock_ = OS::CreateMutex();
2192
}
2193

    
2194

    
2195
LockingMessageQueue::~LockingMessageQueue() {
2196
  delete lock_;
2197
}
2198

    
2199

    
2200
bool LockingMessageQueue::IsEmpty() const {
2201
  ScopedLock sl(lock_);
2202
  return queue_.IsEmpty();
2203
}
2204

    
2205

    
2206
Vector<uint16_t> LockingMessageQueue::Get() {
2207
  ScopedLock sl(lock_);
2208
  Vector<uint16_t> result = queue_.Get();
2209
  Logger::DebugEvent("Get", result);
2210
  return result;
2211
}
2212

    
2213

    
2214
void LockingMessageQueue::Put(const Vector<uint16_t>& message) {
2215
  ScopedLock sl(lock_);
2216
  queue_.Put(message);
2217
  Logger::DebugEvent("Put", message);
2218
}
2219

    
2220

    
2221
void LockingMessageQueue::Clear() {
2222
  ScopedLock sl(lock_);
2223
  queue_.Clear();
2224
}
2225

    
2226

    
2227
} }  // namespace v8::internal