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 @ f230a1cf

History | View | Annotate | Download (127 KB)

1
// Copyright 2012 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 "codegen.h"
35
#include "compilation-cache.h"
36
#include "compiler.h"
37
#include "debug.h"
38
#include "deoptimizer.h"
39
#include "execution.h"
40
#include "full-codegen.h"
41
#include "global-handles.h"
42
#include "ic.h"
43
#include "ic-inl.h"
44
#include "isolate-inl.h"
45
#include "list.h"
46
#include "messages.h"
47
#include "natives.h"
48
#include "stub-cache.h"
49
#include "log.h"
50

    
51
#include "../include/v8-debug.h"
52

    
53
namespace v8 {
54
namespace internal {
55

    
56
#ifdef ENABLE_DEBUGGER_SUPPORT
57

    
58

    
59
Debug::Debug(Isolate* isolate)
60
    : has_break_points_(false),
61
      script_cache_(NULL),
62
      debug_info_list_(NULL),
63
      disable_break_(false),
64
      break_on_exception_(false),
65
      break_on_uncaught_exception_(false),
66
      debug_break_return_(NULL),
67
      debug_break_slot_(NULL),
68
      isolate_(isolate) {
69
  memset(registers_, 0, sizeof(JSCallerSavedBuffer));
70
}
71

    
72

    
73
Debug::~Debug() {
74
}
75

    
76

    
77
static void PrintLn(v8::Local<v8::Value> value) {
78
  v8::Local<v8::String> s = value->ToString();
79
  ScopedVector<char> data(s->Utf8Length() + 1);
80
  if (data.start() == NULL) {
81
    V8::FatalProcessOutOfMemory("PrintLn");
82
    return;
83
  }
84
  s->WriteUtf8(data.start());
85
  PrintF("%s\n", data.start());
86
}
87

    
88

    
89
static Handle<Code> ComputeCallDebugPrepareStepIn(Isolate* isolate,
90
                                                  int argc,
91
                                                  Code::Kind kind) {
92
  return isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind);
93
}
94

    
95

    
96
static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
97
  Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
98
  // Isolate::context() may have been NULL when "script collected" event
99
  // occured.
100
  if (context.is_null()) return v8::Local<v8::Context>();
101
  Handle<Context> native_context(context->native_context());
102
  return v8::Utils::ToLocal(native_context);
103
}
104

    
105

    
106
BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
107
                                             BreakLocatorType type) {
108
  debug_info_ = debug_info;
109
  type_ = type;
110
  reloc_iterator_ = NULL;
111
  reloc_iterator_original_ = NULL;
112
  Reset();  // Initialize the rest of the member variables.
113
}
114

    
115

    
116
BreakLocationIterator::~BreakLocationIterator() {
117
  ASSERT(reloc_iterator_ != NULL);
118
  ASSERT(reloc_iterator_original_ != NULL);
119
  delete reloc_iterator_;
120
  delete reloc_iterator_original_;
121
}
122

    
123

    
124
void BreakLocationIterator::Next() {
125
  DisallowHeapAllocation no_gc;
126
  ASSERT(!RinfoDone());
127

    
128
  // Iterate through reloc info for code and original code stopping at each
129
  // breakable code target.
130
  bool first = break_point_ == -1;
131
  while (!RinfoDone()) {
132
    if (!first) RinfoNext();
133
    first = false;
134
    if (RinfoDone()) return;
135

    
136
    // Whenever a statement position or (plain) position is passed update the
137
    // current value of these.
138
    if (RelocInfo::IsPosition(rmode())) {
139
      if (RelocInfo::IsStatementPosition(rmode())) {
140
        statement_position_ = static_cast<int>(
141
            rinfo()->data() - debug_info_->shared()->start_position());
142
      }
143
      // Always update the position as we don't want that to be before the
144
      // statement position.
145
      position_ = static_cast<int>(
146
          rinfo()->data() - debug_info_->shared()->start_position());
147
      ASSERT(position_ >= 0);
148
      ASSERT(statement_position_ >= 0);
149
    }
150

    
151
    if (IsDebugBreakSlot()) {
152
      // There is always a possible break point at a debug break slot.
153
      break_point_++;
154
      return;
155
    } else if (RelocInfo::IsCodeTarget(rmode())) {
156
      // Check for breakable code target. Look in the original code as setting
157
      // break points can cause the code targets in the running (debugged) code
158
      // to be of a different kind than in the original code.
159
      Address target = original_rinfo()->target_address();
160
      Code* code = Code::GetCodeFromTargetAddress(target);
161
      if ((code->is_inline_cache_stub() &&
162
           !code->is_binary_op_stub() &&
163
           !code->is_compare_ic_stub() &&
164
           !code->is_to_boolean_ic_stub()) ||
165
          RelocInfo::IsConstructCall(rmode())) {
166
        break_point_++;
167
        return;
168
      }
169
      if (code->kind() == Code::STUB) {
170
        if (IsDebuggerStatement()) {
171
          break_point_++;
172
          return;
173
        }
174
        if (type_ == ALL_BREAK_LOCATIONS) {
175
          if (Debug::IsBreakStub(code)) {
176
            break_point_++;
177
            return;
178
          }
179
        } else {
180
          ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
181
          if (Debug::IsSourceBreakStub(code)) {
182
            break_point_++;
183
            return;
184
          }
185
        }
186
      }
187
    }
188

    
189
    // Check for break at return.
190
    if (RelocInfo::IsJSReturn(rmode())) {
191
      // Set the positions to the end of the function.
192
      if (debug_info_->shared()->HasSourceCode()) {
193
        position_ = debug_info_->shared()->end_position() -
194
                    debug_info_->shared()->start_position() - 1;
195
      } else {
196
        position_ = 0;
197
      }
198
      statement_position_ = position_;
199
      break_point_++;
200
      return;
201
    }
202
  }
203
}
204

    
205

    
206
void BreakLocationIterator::Next(int count) {
207
  while (count > 0) {
208
    Next();
209
    count--;
210
  }
211
}
212

    
213

    
214
// Find the break point at the supplied address, or the closest one before
215
// the address.
216
void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
217
  // Run through all break points to locate the one closest to the address.
218
  int closest_break_point = 0;
219
  int distance = kMaxInt;
220
  while (!Done()) {
221
    // Check if this break point is closer that what was previously found.
222
    if (this->pc() <= pc && pc - this->pc() < distance) {
223
      closest_break_point = break_point();
224
      distance = static_cast<int>(pc - this->pc());
225
      // Check whether we can't get any closer.
226
      if (distance == 0) break;
227
    }
228
    Next();
229
  }
230

    
231
  // Move to the break point found.
232
  Reset();
233
  Next(closest_break_point);
234
}
235

    
236

    
237
// Find the break point closest to the supplied source position.
238
void BreakLocationIterator::FindBreakLocationFromPosition(int position,
239
    BreakPositionAlignment alignment) {
240
  // Run through all break points to locate the one closest to the source
241
  // position.
242
  int closest_break_point = 0;
243
  int distance = kMaxInt;
244

    
245
  while (!Done()) {
246
    int next_position;
247
    switch (alignment) {
248
    case STATEMENT_ALIGNED:
249
      next_position = this->statement_position();
250
      break;
251
    case BREAK_POSITION_ALIGNED:
252
      next_position = this->position();
253
      break;
254
    default:
255
      UNREACHABLE();
256
      next_position = this->statement_position();
257
    }
258
    // Check if this break point is closer that what was previously found.
259
    if (position <= next_position && next_position - position < distance) {
260
      closest_break_point = break_point();
261
      distance = next_position - position;
262
      // Check whether we can't get any closer.
263
      if (distance == 0) break;
264
    }
265
    Next();
266
  }
267

    
268
  // Move to the break point found.
269
  Reset();
270
  Next(closest_break_point);
271
}
272

    
273

    
274
void BreakLocationIterator::Reset() {
275
  // Create relocation iterators for the two code objects.
276
  if (reloc_iterator_ != NULL) delete reloc_iterator_;
277
  if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
278
  reloc_iterator_ = new RelocIterator(
279
      debug_info_->code(),
280
      ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
281
  reloc_iterator_original_ = new RelocIterator(
282
      debug_info_->original_code(),
283
      ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
284

    
285
  // Position at the first break point.
286
  break_point_ = -1;
287
  position_ = 1;
288
  statement_position_ = 1;
289
  Next();
290
}
291

    
292

    
293
bool BreakLocationIterator::Done() const {
294
  return RinfoDone();
295
}
296

    
297

    
298
void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
299
  // If there is not already a real break point here patch code with debug
300
  // break.
301
  if (!HasBreakPoint()) {
302
    SetDebugBreak();
303
  }
304
  ASSERT(IsDebugBreak() || IsDebuggerStatement());
305
  // Set the break point information.
306
  DebugInfo::SetBreakPoint(debug_info_, code_position(),
307
                           position(), statement_position(),
308
                           break_point_object);
309
}
310

    
311

    
312
void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
313
  // Clear the break point information.
314
  DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
315
  // If there are no more break points here remove the debug break.
316
  if (!HasBreakPoint()) {
317
    ClearDebugBreak();
318
    ASSERT(!IsDebugBreak());
319
  }
320
}
321

    
322

    
323
void BreakLocationIterator::SetOneShot() {
324
  // Debugger statement always calls debugger. No need to modify it.
325
  if (IsDebuggerStatement()) {
326
    return;
327
  }
328

    
329
  // If there is a real break point here no more to do.
330
  if (HasBreakPoint()) {
331
    ASSERT(IsDebugBreak());
332
    return;
333
  }
334

    
335
  // Patch code with debug break.
336
  SetDebugBreak();
337
}
338

    
339

    
340
void BreakLocationIterator::ClearOneShot() {
341
  // Debugger statement always calls debugger. No need to modify it.
342
  if (IsDebuggerStatement()) {
343
    return;
344
  }
345

    
346
  // If there is a real break point here no more to do.
347
  if (HasBreakPoint()) {
348
    ASSERT(IsDebugBreak());
349
    return;
350
  }
351

    
352
  // Patch code removing debug break.
353
  ClearDebugBreak();
354
  ASSERT(!IsDebugBreak());
355
}
356

    
357

    
358
void BreakLocationIterator::SetDebugBreak() {
359
  // Debugger statement always calls debugger. No need to modify it.
360
  if (IsDebuggerStatement()) {
361
    return;
362
  }
363

    
364
  // If there is already a break point here just return. This might happen if
365
  // the same code is flooded with break points twice. Flooding the same
366
  // function twice might happen when stepping in a function with an exception
367
  // handler as the handler and the function is the same.
368
  if (IsDebugBreak()) {
369
    return;
370
  }
371

    
372
  if (RelocInfo::IsJSReturn(rmode())) {
373
    // Patch the frame exit code with a break point.
374
    SetDebugBreakAtReturn();
375
  } else if (IsDebugBreakSlot()) {
376
    // Patch the code in the break slot.
377
    SetDebugBreakAtSlot();
378
  } else {
379
    // Patch the IC call.
380
    SetDebugBreakAtIC();
381
  }
382
  ASSERT(IsDebugBreak());
383
}
384

    
385

    
386
void BreakLocationIterator::ClearDebugBreak() {
387
  // Debugger statement always calls debugger. No need to modify it.
388
  if (IsDebuggerStatement()) {
389
    return;
390
  }
391

    
392
  if (RelocInfo::IsJSReturn(rmode())) {
393
    // Restore the frame exit code.
394
    ClearDebugBreakAtReturn();
395
  } else if (IsDebugBreakSlot()) {
396
    // Restore the code in the break slot.
397
    ClearDebugBreakAtSlot();
398
  } else {
399
    // Patch the IC call.
400
    ClearDebugBreakAtIC();
401
  }
402
  ASSERT(!IsDebugBreak());
403
}
404

    
405

    
406
bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
407
  if (RelocInfo::IsConstructCall(original_rmode())) {
408
    return true;
409
  } else if (RelocInfo::IsCodeTarget(rmode())) {
410
    HandleScope scope(debug_info_->GetIsolate());
411
    Address target = original_rinfo()->target_address();
412
    Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
413
    if (target_code->kind() == Code::STUB) {
414
      return target_code->major_key() == CodeStub::CallFunction;
415
    }
416
    return target_code->is_call_stub() || target_code->is_keyed_call_stub();
417
  } else {
418
    return false;
419
  }
420
}
421

    
422

    
423
void BreakLocationIterator::PrepareStepIn(Isolate* isolate) {
424
  HandleScope scope(isolate);
425

    
426
  // Step in can only be prepared if currently positioned on an IC call,
427
  // construct call or CallFunction stub call.
428
  Address target = rinfo()->target_address();
429
  Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
430
  if (target_code->is_call_stub() || target_code->is_keyed_call_stub()) {
431
    // Step in through IC call is handled by the runtime system. Therefore make
432
    // sure that the any current IC is cleared and the runtime system is
433
    // called. If the executing code has a debug break at the location change
434
    // the call in the original code as it is the code there that will be
435
    // executed in place of the debug break call.
436
    Handle<Code> stub = ComputeCallDebugPrepareStepIn(
437
        isolate, target_code->arguments_count(), target_code->kind());
438
    if (IsDebugBreak()) {
439
      original_rinfo()->set_target_address(stub->entry());
440
    } else {
441
      rinfo()->set_target_address(stub->entry());
442
    }
443
  } else {
444
#ifdef DEBUG
445
    // All the following stuff is needed only for assertion checks so the code
446
    // is wrapped in ifdef.
447
    Handle<Code> maybe_call_function_stub = target_code;
448
    if (IsDebugBreak()) {
449
      Address original_target = original_rinfo()->target_address();
450
      maybe_call_function_stub =
451
          Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
452
    }
453
    bool is_call_function_stub =
454
        (maybe_call_function_stub->kind() == Code::STUB &&
455
         maybe_call_function_stub->major_key() == CodeStub::CallFunction);
456

    
457
    // Step in through construct call requires no changes to the running code.
458
    // Step in through getters/setters should already be prepared as well
459
    // because caller of this function (Debug::PrepareStep) is expected to
460
    // flood the top frame's function with one shot breakpoints.
461
    // Step in through CallFunction stub should also be prepared by caller of
462
    // this function (Debug::PrepareStep) which should flood target function
463
    // with breakpoints.
464
    ASSERT(RelocInfo::IsConstructCall(rmode()) ||
465
           target_code->is_inline_cache_stub() ||
466
           is_call_function_stub);
467
#endif
468
  }
469
}
470

    
471

    
472
// Check whether the break point is at a position which will exit the function.
473
bool BreakLocationIterator::IsExit() const {
474
  return (RelocInfo::IsJSReturn(rmode()));
475
}
476

    
477

    
478
bool BreakLocationIterator::HasBreakPoint() {
479
  return debug_info_->HasBreakPoint(code_position());
480
}
481

    
482

    
483
// Check whether there is a debug break at the current position.
484
bool BreakLocationIterator::IsDebugBreak() {
485
  if (RelocInfo::IsJSReturn(rmode())) {
486
    return IsDebugBreakAtReturn();
487
  } else if (IsDebugBreakSlot()) {
488
    return IsDebugBreakAtSlot();
489
  } else {
490
    return Debug::IsDebugBreak(rinfo()->target_address());
491
  }
492
}
493

    
494

    
495
void BreakLocationIterator::SetDebugBreakAtIC() {
496
  // Patch the original code with the current address as the current address
497
  // might have changed by the inline caching since the code was copied.
498
  original_rinfo()->set_target_address(rinfo()->target_address());
499

    
500
  RelocInfo::Mode mode = rmode();
501
  if (RelocInfo::IsCodeTarget(mode)) {
502
    Address target = rinfo()->target_address();
503
    Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
504

    
505
    // Patch the code to invoke the builtin debug break function matching the
506
    // calling convention used by the call site.
507
    Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode));
508
    rinfo()->set_target_address(dbgbrk_code->entry());
509
  }
510
}
511

    
512

    
513
void BreakLocationIterator::ClearDebugBreakAtIC() {
514
  // Patch the code to the original invoke.
515
  rinfo()->set_target_address(original_rinfo()->target_address());
516
}
517

    
518

    
519
bool BreakLocationIterator::IsDebuggerStatement() {
520
  return RelocInfo::DEBUG_BREAK == rmode();
521
}
522

    
523

    
524
bool BreakLocationIterator::IsDebugBreakSlot() {
525
  return RelocInfo::DEBUG_BREAK_SLOT == rmode();
526
}
527

    
528

    
529
Object* BreakLocationIterator::BreakPointObjects() {
530
  return debug_info_->GetBreakPointObjects(code_position());
531
}
532

    
533

    
534
// Clear out all the debug break code. This is ONLY supposed to be used when
535
// shutting down the debugger as it will leave the break point information in
536
// DebugInfo even though the code is patched back to the non break point state.
537
void BreakLocationIterator::ClearAllDebugBreak() {
538
  while (!Done()) {
539
    ClearDebugBreak();
540
    Next();
541
  }
542
}
543

    
544

    
545
bool BreakLocationIterator::RinfoDone() const {
546
  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
547
  return reloc_iterator_->done();
548
}
549

    
550

    
551
void BreakLocationIterator::RinfoNext() {
552
  reloc_iterator_->next();
553
  reloc_iterator_original_->next();
554
#ifdef DEBUG
555
  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
556
  if (!reloc_iterator_->done()) {
557
    ASSERT(rmode() == original_rmode());
558
  }
559
#endif
560
}
561

    
562

    
563
// Threading support.
564
void Debug::ThreadInit() {
565
  thread_local_.break_count_ = 0;
566
  thread_local_.break_id_ = 0;
567
  thread_local_.break_frame_id_ = StackFrame::NO_ID;
568
  thread_local_.last_step_action_ = StepNone;
569
  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
570
  thread_local_.step_count_ = 0;
571
  thread_local_.last_fp_ = 0;
572
  thread_local_.queued_step_count_ = 0;
573
  thread_local_.step_into_fp_ = 0;
574
  thread_local_.step_out_fp_ = 0;
575
  thread_local_.after_break_target_ = 0;
576
  // TODO(isolates): frames_are_dropped_?
577
  thread_local_.debugger_entry_ = NULL;
578
  thread_local_.pending_interrupts_ = 0;
579
  thread_local_.restarter_frame_function_pointer_ = NULL;
580
}
581

    
582

    
583
char* Debug::ArchiveDebug(char* storage) {
584
  char* to = storage;
585
  OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
586
  to += sizeof(ThreadLocal);
587
  OS::MemCopy(to, reinterpret_cast<char*>(&registers_), sizeof(registers_));
588
  ThreadInit();
589
  ASSERT(to <= storage + ArchiveSpacePerThread());
590
  return storage + ArchiveSpacePerThread();
591
}
592

    
593

    
594
char* Debug::RestoreDebug(char* storage) {
595
  char* from = storage;
596
  OS::MemCopy(
597
      reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
598
  from += sizeof(ThreadLocal);
599
  OS::MemCopy(reinterpret_cast<char*>(&registers_), from, sizeof(registers_));
600
  ASSERT(from <= storage + ArchiveSpacePerThread());
601
  return storage + ArchiveSpacePerThread();
602
}
603

    
604

    
605
int Debug::ArchiveSpacePerThread() {
606
  return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer);
607
}
608

    
609

    
610
// Frame structure (conforms InternalFrame structure):
611
//   -- code
612
//   -- SMI maker
613
//   -- function (slot is called "context")
614
//   -- frame base
615
Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
616
                                       Handle<Code> code) {
617
  ASSERT(bottom_js_frame->is_java_script());
618

    
619
  Address fp = bottom_js_frame->fp();
620

    
621
  // Move function pointer into "context" slot.
622
  Memory::Object_at(fp + StandardFrameConstants::kContextOffset) =
623
      Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset);
624

    
625
  Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code;
626
  Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) =
627
      Smi::FromInt(StackFrame::INTERNAL);
628

    
629
  return reinterpret_cast<Object**>(&Memory::Object_at(
630
      fp + StandardFrameConstants::kContextOffset));
631
}
632

    
633
const int Debug::kFrameDropperFrameSize = 4;
634

    
635

    
636
void ScriptCache::Add(Handle<Script> script) {
637
  GlobalHandles* global_handles = isolate_->global_handles();
638
  // Create an entry in the hash map for the script.
639
  int id = script->id()->value();
640
  HashMap::Entry* entry =
641
      HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
642
  if (entry->value != NULL) {
643
    ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
644
    return;
645
  }
646
  // Globalize the script object, make it weak and use the location of the
647
  // global handle as the value in the hash map.
648
  Handle<Script> script_ =
649
      Handle<Script>::cast(
650
          (global_handles->Create(*script)));
651
  global_handles->MakeWeak(reinterpret_cast<Object**>(script_.location()),
652
                           this,
653
                           ScriptCache::HandleWeakScript);
654
  entry->value = script_.location();
655
}
656

    
657

    
658
Handle<FixedArray> ScriptCache::GetScripts() {
659
  Factory* factory = isolate_->factory();
660
  Handle<FixedArray> instances = factory->NewFixedArray(occupancy());
661
  int count = 0;
662
  for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
663
    ASSERT(entry->value != NULL);
664
    if (entry->value != NULL) {
665
      instances->set(count, *reinterpret_cast<Script**>(entry->value));
666
      count++;
667
    }
668
  }
669
  return instances;
670
}
671

    
672

    
673
void ScriptCache::ProcessCollectedScripts() {
674
  Debugger* debugger = isolate_->debugger();
675
  for (int i = 0; i < collected_scripts_.length(); i++) {
676
    debugger->OnScriptCollected(collected_scripts_[i]);
677
  }
678
  collected_scripts_.Clear();
679
}
680

    
681

    
682
void ScriptCache::Clear() {
683
  GlobalHandles* global_handles = isolate_->global_handles();
684
  // Iterate the script cache to get rid of all the weak handles.
685
  for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
686
    ASSERT(entry != NULL);
687
    Object** location = reinterpret_cast<Object**>(entry->value);
688
    ASSERT((*location)->IsScript());
689
    global_handles->ClearWeakness(location);
690
    global_handles->Destroy(location);
691
  }
692
  // Clear the content of the hash map.
693
  HashMap::Clear();
694
}
695

    
696

    
697
void ScriptCache::HandleWeakScript(v8::Isolate* isolate,
698
                                   v8::Persistent<v8::Value>* obj,
699
                                   void* data) {
700
  ScriptCache* script_cache = reinterpret_cast<ScriptCache*>(data);
701
  // Find the location of the global handle.
702
  Script** location =
703
      reinterpret_cast<Script**>(Utils::OpenPersistent(*obj).location());
704
  ASSERT((*location)->IsScript());
705

    
706
  // Remove the entry from the cache.
707
  int id = (*location)->id()->value();
708
  script_cache->Remove(reinterpret_cast<void*>(id), Hash(id));
709
  script_cache->collected_scripts_.Add(id);
710

    
711
  // Clear the weak handle.
712
  obj->Dispose();
713
}
714

    
715

    
716
void Debug::SetUp(bool create_heap_objects) {
717
  ThreadInit();
718
  if (create_heap_objects) {
719
    // Get code to handle debug break on return.
720
    debug_break_return_ =
721
        isolate_->builtins()->builtin(Builtins::kReturn_DebugBreak);
722
    ASSERT(debug_break_return_->IsCode());
723
    // Get code to handle debug break in debug break slots.
724
    debug_break_slot_ =
725
        isolate_->builtins()->builtin(Builtins::kSlot_DebugBreak);
726
    ASSERT(debug_break_slot_->IsCode());
727
  }
728
}
729

    
730

    
731
void Debug::HandleWeakDebugInfo(v8::Isolate* isolate,
732
                                v8::Persistent<v8::Value>* obj,
733
                                void* data) {
734
  Debug* debug = reinterpret_cast<Isolate*>(isolate)->debug();
735
  DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
736
  // We need to clear all breakpoints associated with the function to restore
737
  // original code and avoid patching the code twice later because
738
  // the function will live in the heap until next gc, and can be found by
739
  // Debug::FindSharedFunctionInfoInScript.
740
  BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
741
  it.ClearAllDebugBreak();
742
  debug->RemoveDebugInfo(node->debug_info());
743
#ifdef DEBUG
744
  node = debug->debug_info_list_;
745
  while (node != NULL) {
746
    ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
747
    node = node->next();
748
  }
749
#endif
750
}
751

    
752

    
753
DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
754
  GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
755
  // Globalize the request debug info object and make it weak.
756
  debug_info_ = Handle<DebugInfo>::cast(
757
      (global_handles->Create(debug_info)));
758
  global_handles->MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
759
                           this,
760
                           Debug::HandleWeakDebugInfo);
761
}
762

    
763

    
764
DebugInfoListNode::~DebugInfoListNode() {
765
  debug_info_->GetIsolate()->global_handles()->Destroy(
766
      reinterpret_cast<Object**>(debug_info_.location()));
767
}
768

    
769

    
770
bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
771
  Factory* factory = isolate->factory();
772
  HandleScope scope(isolate);
773

    
774
  // Bail out if the index is invalid.
775
  if (index == -1) {
776
    return false;
777
  }
778

    
779
  // Find source and name for the requested script.
780
  Handle<String> source_code =
781
      isolate->bootstrapper()->NativesSourceLookup(index);
782
  Vector<const char> name = Natives::GetScriptName(index);
783
  Handle<String> script_name = factory->NewStringFromAscii(name);
784
  Handle<Context> context = isolate->native_context();
785

    
786
  // Compile the script.
787
  Handle<SharedFunctionInfo> function_info;
788
  function_info = Compiler::Compile(source_code,
789
                                    script_name,
790
                                    0, 0,
791
                                    false,
792
                                    context,
793
                                    NULL, NULL,
794
                                    Handle<String>::null(),
795
                                    NATIVES_CODE);
796

    
797
  // Silently ignore stack overflows during compilation.
798
  if (function_info.is_null()) {
799
    ASSERT(isolate->has_pending_exception());
800
    isolate->clear_pending_exception();
801
    return false;
802
  }
803

    
804
  // Execute the shared function in the debugger context.
805
  bool caught_exception;
806
  Handle<JSFunction> function =
807
      factory->NewFunctionFromSharedFunctionInfo(function_info, context);
808

    
809
  Handle<Object> exception =
810
      Execution::TryCall(function,
811
                         Handle<Object>(context->global_object(), isolate),
812
                         0,
813
                         NULL,
814
                         &caught_exception);
815

    
816
  // Check for caught exceptions.
817
  if (caught_exception) {
818
    ASSERT(!isolate->has_pending_exception());
819
    MessageLocation computed_location;
820
    isolate->ComputeLocation(&computed_location);
821
    Handle<Object> message = MessageHandler::MakeMessageObject(
822
        isolate, "error_loading_debugger", &computed_location,
823
        Vector<Handle<Object> >::empty(), Handle<String>(), Handle<JSArray>());
824
    ASSERT(!isolate->has_pending_exception());
825
    if (!exception.is_null()) {
826
      isolate->set_pending_exception(*exception);
827
      MessageHandler::ReportMessage(isolate, NULL, message);
828
      isolate->clear_pending_exception();
829
    }
830
    return false;
831
  }
832

    
833
  // Mark this script as native and return successfully.
834
  Handle<Script> script(Script::cast(function->shared()->script()));
835
  script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
836
  return true;
837
}
838

    
839

    
840
bool Debug::Load() {
841
  // Return if debugger is already loaded.
842
  if (IsLoaded()) return true;
843

    
844
  Debugger* debugger = isolate_->debugger();
845

    
846
  // Bail out if we're already in the process of compiling the native
847
  // JavaScript source code for the debugger.
848
  if (debugger->compiling_natives() ||
849
      debugger->is_loading_debugger())
850
    return false;
851
  debugger->set_loading_debugger(true);
852

    
853
  // Disable breakpoints and interrupts while compiling and running the
854
  // debugger scripts including the context creation code.
855
  DisableBreak disable(isolate_, true);
856
  PostponeInterruptsScope postpone(isolate_);
857

    
858
  // Create the debugger context.
859
  HandleScope scope(isolate_);
860
  Handle<Context> context =
861
      isolate_->bootstrapper()->CreateEnvironment(
862
          Handle<Object>::null(),
863
          v8::Handle<ObjectTemplate>(),
864
          NULL);
865

    
866
  // Fail if no context could be created.
867
  if (context.is_null()) return false;
868

    
869
  // Use the debugger context.
870
  SaveContext save(isolate_);
871
  isolate_->set_context(*context);
872

    
873
  // Expose the builtins object in the debugger context.
874
  Handle<String> key = isolate_->factory()->InternalizeOneByteString(
875
      STATIC_ASCII_VECTOR("builtins"));
876
  Handle<GlobalObject> global = Handle<GlobalObject>(context->global_object());
877
  RETURN_IF_EMPTY_HANDLE_VALUE(
878
      isolate_,
879
      JSReceiver::SetProperty(global,
880
                              key,
881
                              Handle<Object>(global->builtins(), isolate_),
882
                              NONE,
883
                              kNonStrictMode),
884
      false);
885

    
886
  // Compile the JavaScript for the debugger in the debugger context.
887
  debugger->set_compiling_natives(true);
888
  bool caught_exception =
889
      !CompileDebuggerScript(isolate_, Natives::GetIndex("mirror")) ||
890
      !CompileDebuggerScript(isolate_, Natives::GetIndex("debug"));
891

    
892
  if (FLAG_enable_liveedit) {
893
    caught_exception = caught_exception ||
894
        !CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit"));
895
  }
896

    
897
  debugger->set_compiling_natives(false);
898

    
899
  // Make sure we mark the debugger as not loading before we might
900
  // return.
901
  debugger->set_loading_debugger(false);
902

    
903
  // Check for caught exceptions.
904
  if (caught_exception) return false;
905

    
906
  // Debugger loaded, create debugger context global handle.
907
  debug_context_ = Handle<Context>::cast(
908
      isolate_->global_handles()->Create(*context));
909

    
910
  return true;
911
}
912

    
913

    
914
void Debug::Unload() {
915
  // Return debugger is not loaded.
916
  if (!IsLoaded()) {
917
    return;
918
  }
919

    
920
  // Clear the script cache.
921
  DestroyScriptCache();
922

    
923
  // Clear debugger context global handle.
924
  isolate_->global_handles()->Destroy(
925
      reinterpret_cast<Object**>(debug_context_.location()));
926
  debug_context_ = Handle<Context>();
927
}
928

    
929

    
930
// Set the flag indicating that preemption happened during debugging.
931
void Debug::PreemptionWhileInDebugger() {
932
  ASSERT(InDebugger());
933
  Debug::set_interrupts_pending(PREEMPT);
934
}
935

    
936

    
937
void Debug::Iterate(ObjectVisitor* v) {
938
  v->VisitPointer(BitCast<Object**>(&(debug_break_return_)));
939
  v->VisitPointer(BitCast<Object**>(&(debug_break_slot_)));
940
}
941

    
942

    
943
Object* Debug::Break(Arguments args) {
944
  Heap* heap = isolate_->heap();
945
  HandleScope scope(isolate_);
946
  ASSERT(args.length() == 0);
947

    
948
  thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED;
949

    
950
  // Get the top-most JavaScript frame.
951
  JavaScriptFrameIterator it(isolate_);
952
  JavaScriptFrame* frame = it.frame();
953

    
954
  // Just continue if breaks are disabled or debugger cannot be loaded.
955
  if (disable_break() || !Load()) {
956
    SetAfterBreakTarget(frame);
957
    return heap->undefined_value();
958
  }
959

    
960
  // Enter the debugger.
961
  EnterDebugger debugger(isolate_);
962
  if (debugger.FailedToEnter()) {
963
    return heap->undefined_value();
964
  }
965

    
966
  // Postpone interrupt during breakpoint processing.
967
  PostponeInterruptsScope postpone(isolate_);
968

    
969
  // Get the debug info (create it if it does not exist).
970
  Handle<SharedFunctionInfo> shared =
971
      Handle<SharedFunctionInfo>(frame->function()->shared());
972
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
973

    
974
  // Find the break point where execution has stopped.
975
  BreakLocationIterator break_location_iterator(debug_info,
976
                                                ALL_BREAK_LOCATIONS);
977
  // pc points to the instruction after the current one, possibly a break
978
  // location as well. So the "- 1" to exclude it from the search.
979
  break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
980

    
981
  // Check whether step next reached a new statement.
982
  if (!StepNextContinue(&break_location_iterator, frame)) {
983
    // Decrease steps left if performing multiple steps.
984
    if (thread_local_.step_count_ > 0) {
985
      thread_local_.step_count_--;
986
    }
987
  }
988

    
989
  // If there is one or more real break points check whether any of these are
990
  // triggered.
991
  Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
992
  if (break_location_iterator.HasBreakPoint()) {
993
    Handle<Object> break_point_objects =
994
        Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_);
995
    break_points_hit = CheckBreakPoints(break_point_objects);
996
  }
997

    
998
  // If step out is active skip everything until the frame where we need to step
999
  // out to is reached, unless real breakpoint is hit.
1000
  if (StepOutActive() && frame->fp() != step_out_fp() &&
1001
      break_points_hit->IsUndefined() ) {
1002
      // Step count should always be 0 for StepOut.
1003
      ASSERT(thread_local_.step_count_ == 0);
1004
  } else if (!break_points_hit->IsUndefined() ||
1005
             (thread_local_.last_step_action_ != StepNone &&
1006
              thread_local_.step_count_ == 0)) {
1007
    // Notify debugger if a real break point is triggered or if performing
1008
    // single stepping with no more steps to perform. Otherwise do another step.
1009

    
1010
    // Clear all current stepping setup.
1011
    ClearStepping();
1012

    
1013
    if (thread_local_.queued_step_count_ > 0) {
1014
      // Perform queued steps
1015
      int step_count = thread_local_.queued_step_count_;
1016

    
1017
      // Clear queue
1018
      thread_local_.queued_step_count_ = 0;
1019

    
1020
      PrepareStep(StepNext, step_count, StackFrame::NO_ID);
1021
    } else {
1022
      // Notify the debug event listeners.
1023
      isolate_->debugger()->OnDebugBreak(break_points_hit, false);
1024
    }
1025
  } else if (thread_local_.last_step_action_ != StepNone) {
1026
    // Hold on to last step action as it is cleared by the call to
1027
    // ClearStepping.
1028
    StepAction step_action = thread_local_.last_step_action_;
1029
    int step_count = thread_local_.step_count_;
1030

    
1031
    // If StepNext goes deeper in code, StepOut until original frame
1032
    // and keep step count queued up in the meantime.
1033
    if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
1034
      // Count frames until target frame
1035
      int count = 0;
1036
      JavaScriptFrameIterator it(isolate_);
1037
      while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
1038
        count++;
1039
        it.Advance();
1040
      }
1041

    
1042
      // Check that we indeed found the frame we are looking for.
1043
      CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
1044
      if (step_count > 1) {
1045
        // Save old count and action to continue stepping after StepOut.
1046
        thread_local_.queued_step_count_ = step_count - 1;
1047
      }
1048

    
1049
      // Set up for StepOut to reach target frame.
1050
      step_action = StepOut;
1051
      step_count = count;
1052
    }
1053

    
1054
    // Clear all current stepping setup.
1055
    ClearStepping();
1056

    
1057
    // Set up for the remaining steps.
1058
    PrepareStep(step_action, step_count, StackFrame::NO_ID);
1059
  }
1060

    
1061
  if (thread_local_.frame_drop_mode_ == FRAMES_UNTOUCHED) {
1062
    SetAfterBreakTarget(frame);
1063
  } else if (thread_local_.frame_drop_mode_ ==
1064
      FRAME_DROPPED_IN_IC_CALL) {
1065
    // We must have been calling IC stub. Do not go there anymore.
1066
    Code* plain_return = isolate_->builtins()->builtin(
1067
        Builtins::kPlainReturn_LiveEdit);
1068
    thread_local_.after_break_target_ = plain_return->entry();
1069
  } else if (thread_local_.frame_drop_mode_ ==
1070
      FRAME_DROPPED_IN_DEBUG_SLOT_CALL) {
1071
    // Debug break slot stub does not return normally, instead it manually
1072
    // cleans the stack and jumps. We should patch the jump address.
1073
    Code* plain_return = isolate_->builtins()->builtin(
1074
        Builtins::kFrameDropper_LiveEdit);
1075
    thread_local_.after_break_target_ = plain_return->entry();
1076
  } else if (thread_local_.frame_drop_mode_ ==
1077
      FRAME_DROPPED_IN_DIRECT_CALL) {
1078
    // Nothing to do, after_break_target is not used here.
1079
  } else if (thread_local_.frame_drop_mode_ ==
1080
      FRAME_DROPPED_IN_RETURN_CALL) {
1081
    Code* plain_return = isolate_->builtins()->builtin(
1082
        Builtins::kFrameDropper_LiveEdit);
1083
    thread_local_.after_break_target_ = plain_return->entry();
1084
  } else {
1085
    UNREACHABLE();
1086
  }
1087

    
1088
  return heap->undefined_value();
1089
}
1090

    
1091

    
1092
RUNTIME_FUNCTION(Object*, Debug_Break) {
1093
  return isolate->debug()->Break(args);
1094
}
1095

    
1096

    
1097
// Check the break point objects for whether one or more are actually
1098
// triggered. This function returns a JSArray with the break point objects
1099
// which is triggered.
1100
Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
1101
  Factory* factory = isolate_->factory();
1102

    
1103
  // Count the number of break points hit. If there are multiple break points
1104
  // they are in a FixedArray.
1105
  Handle<FixedArray> break_points_hit;
1106
  int break_points_hit_count = 0;
1107
  ASSERT(!break_point_objects->IsUndefined());
1108
  if (break_point_objects->IsFixedArray()) {
1109
    Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
1110
    break_points_hit = factory->NewFixedArray(array->length());
1111
    for (int i = 0; i < array->length(); i++) {
1112
      Handle<Object> o(array->get(i), isolate_);
1113
      if (CheckBreakPoint(o)) {
1114
        break_points_hit->set(break_points_hit_count++, *o);
1115
      }
1116
    }
1117
  } else {
1118
    break_points_hit = factory->NewFixedArray(1);
1119
    if (CheckBreakPoint(break_point_objects)) {
1120
      break_points_hit->set(break_points_hit_count++, *break_point_objects);
1121
    }
1122
  }
1123

    
1124
  // Return undefined if no break points were triggered.
1125
  if (break_points_hit_count == 0) {
1126
    return factory->undefined_value();
1127
  }
1128
  // Return break points hit as a JSArray.
1129
  Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
1130
  result->set_length(Smi::FromInt(break_points_hit_count));
1131
  return result;
1132
}
1133

    
1134

    
1135
// Check whether a single break point object is triggered.
1136
bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
1137
  Factory* factory = isolate_->factory();
1138
  HandleScope scope(isolate_);
1139

    
1140
  // Ignore check if break point object is not a JSObject.
1141
  if (!break_point_object->IsJSObject()) return true;
1142

    
1143
  // Get the function IsBreakPointTriggered (defined in debug-debugger.js).
1144
  Handle<String> is_break_point_triggered_string =
1145
      factory->InternalizeOneByteString(
1146
          STATIC_ASCII_VECTOR("IsBreakPointTriggered"));
1147
  Handle<JSFunction> check_break_point =
1148
    Handle<JSFunction>(JSFunction::cast(
1149
        debug_context()->global_object()->GetPropertyNoExceptionThrown(
1150
            *is_break_point_triggered_string)));
1151

    
1152
  // Get the break id as an object.
1153
  Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
1154

    
1155
  // Call HandleBreakPointx.
1156
  bool caught_exception;
1157
  Handle<Object> argv[] = { break_id, break_point_object };
1158
  Handle<Object> result = Execution::TryCall(check_break_point,
1159
                                             isolate_->js_builtins_object(),
1160
                                             ARRAY_SIZE(argv),
1161
                                             argv,
1162
                                             &caught_exception);
1163

    
1164
  // If exception or non boolean result handle as not triggered
1165
  if (caught_exception || !result->IsBoolean()) {
1166
    return false;
1167
  }
1168

    
1169
  // Return whether the break point is triggered.
1170
  ASSERT(!result.is_null());
1171
  return (*result)->IsTrue();
1172
}
1173

    
1174

    
1175
// Check whether the function has debug information.
1176
bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
1177
  return !shared->debug_info()->IsUndefined();
1178
}
1179

    
1180

    
1181
// Return the debug info for this function. EnsureDebugInfo must be called
1182
// prior to ensure the debug info has been generated for shared.
1183
Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
1184
  ASSERT(HasDebugInfo(shared));
1185
  return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
1186
}
1187

    
1188

    
1189
void Debug::SetBreakPoint(Handle<JSFunction> function,
1190
                          Handle<Object> break_point_object,
1191
                          int* source_position) {
1192
  HandleScope scope(isolate_);
1193

    
1194
  PrepareForBreakPoints();
1195

    
1196
  // Make sure the function is compiled and has set up the debug info.
1197
  Handle<SharedFunctionInfo> shared(function->shared());
1198
  if (!EnsureDebugInfo(shared, function)) {
1199
    // Return if retrieving debug info failed.
1200
    return;
1201
  }
1202

    
1203
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1204
  // Source positions starts with zero.
1205
  ASSERT(*source_position >= 0);
1206

    
1207
  // Find the break point and change it.
1208
  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1209
  it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED);
1210
  it.SetBreakPoint(break_point_object);
1211

    
1212
  *source_position = it.position();
1213

    
1214
  // At least one active break point now.
1215
  ASSERT(debug_info->GetBreakPointCount() > 0);
1216
}
1217

    
1218

    
1219
bool Debug::SetBreakPointForScript(Handle<Script> script,
1220
                                   Handle<Object> break_point_object,
1221
                                   int* source_position,
1222
                                   BreakPositionAlignment alignment) {
1223
  HandleScope scope(isolate_);
1224

    
1225
  PrepareForBreakPoints();
1226

    
1227
  // Obtain shared function info for the function.
1228
  Object* result = FindSharedFunctionInfoInScript(script, *source_position);
1229
  if (result->IsUndefined()) return false;
1230

    
1231
  // Make sure the function has set up the debug info.
1232
  Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
1233
  if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1234
    // Return if retrieving debug info failed.
1235
    return false;
1236
  }
1237

    
1238
  // Find position within function. The script position might be before the
1239
  // source position of the first function.
1240
  int position;
1241
  if (shared->start_position() > *source_position) {
1242
    position = 0;
1243
  } else {
1244
    position = *source_position - shared->start_position();
1245
  }
1246

    
1247
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1248
  // Source positions starts with zero.
1249
  ASSERT(position >= 0);
1250

    
1251
  // Find the break point and change it.
1252
  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1253
  it.FindBreakLocationFromPosition(position, alignment);
1254
  it.SetBreakPoint(break_point_object);
1255

    
1256
  *source_position = it.position() + shared->start_position();
1257

    
1258
  // At least one active break point now.
1259
  ASSERT(debug_info->GetBreakPointCount() > 0);
1260
  return true;
1261
}
1262

    
1263

    
1264
void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1265
  HandleScope scope(isolate_);
1266

    
1267
  DebugInfoListNode* node = debug_info_list_;
1268
  while (node != NULL) {
1269
    Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
1270
                                                   break_point_object);
1271
    if (!result->IsUndefined()) {
1272
      // Get information in the break point.
1273
      BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
1274
      Handle<DebugInfo> debug_info = node->debug_info();
1275

    
1276
      // Find the break point and clear it.
1277
      BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1278
      it.FindBreakLocationFromAddress(debug_info->code()->entry() +
1279
          break_point_info->code_position()->value());
1280
      it.ClearBreakPoint(break_point_object);
1281

    
1282
      // If there are no more break points left remove the debug info for this
1283
      // function.
1284
      if (debug_info->GetBreakPointCount() == 0) {
1285
        RemoveDebugInfo(debug_info);
1286
      }
1287

    
1288
      return;
1289
    }
1290
    node = node->next();
1291
  }
1292
}
1293

    
1294

    
1295
void Debug::ClearAllBreakPoints() {
1296
  DebugInfoListNode* node = debug_info_list_;
1297
  while (node != NULL) {
1298
    // Remove all debug break code.
1299
    BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1300
    it.ClearAllDebugBreak();
1301
    node = node->next();
1302
  }
1303

    
1304
  // Remove all debug info.
1305
  while (debug_info_list_ != NULL) {
1306
    RemoveDebugInfo(debug_info_list_->debug_info());
1307
  }
1308
}
1309

    
1310

    
1311
void Debug::FloodWithOneShot(Handle<JSFunction> function) {
1312
  PrepareForBreakPoints();
1313

    
1314
  // Make sure the function is compiled and has set up the debug info.
1315
  Handle<SharedFunctionInfo> shared(function->shared());
1316
  if (!EnsureDebugInfo(shared, function)) {
1317
    // Return if we failed to retrieve the debug info.
1318
    return;
1319
  }
1320

    
1321
  // Flood the function with break points.
1322
  BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
1323
  while (!it.Done()) {
1324
    it.SetOneShot();
1325
    it.Next();
1326
  }
1327
}
1328

    
1329

    
1330
void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
1331
  Handle<FixedArray> new_bindings(function->function_bindings());
1332
  Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
1333
                        isolate_);
1334

    
1335
  if (!bindee.is_null() && bindee->IsJSFunction() &&
1336
      !JSFunction::cast(*bindee)->IsBuiltin()) {
1337
    Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
1338
    Debug::FloodWithOneShot(bindee_function);
1339
  }
1340
}
1341

    
1342

    
1343
void Debug::FloodHandlerWithOneShot() {
1344
  // Iterate through the JavaScript stack looking for handlers.
1345
  StackFrame::Id id = break_frame_id();
1346
  if (id == StackFrame::NO_ID) {
1347
    // If there is no JavaScript stack don't do anything.
1348
    return;
1349
  }
1350
  for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
1351
    JavaScriptFrame* frame = it.frame();
1352
    if (frame->HasHandler()) {
1353
      // Flood the function with the catch block with break points
1354
      FloodWithOneShot(Handle<JSFunction>(frame->function()));
1355
      return;
1356
    }
1357
  }
1358
}
1359

    
1360

    
1361
void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
1362
  if (type == BreakUncaughtException) {
1363
    break_on_uncaught_exception_ = enable;
1364
  } else {
1365
    break_on_exception_ = enable;
1366
  }
1367
}
1368

    
1369

    
1370
bool Debug::IsBreakOnException(ExceptionBreakType type) {
1371
  if (type == BreakUncaughtException) {
1372
    return break_on_uncaught_exception_;
1373
  } else {
1374
    return break_on_exception_;
1375
  }
1376
}
1377

    
1378

    
1379
void Debug::PrepareStep(StepAction step_action,
1380
                        int step_count,
1381
                        StackFrame::Id frame_id) {
1382
  HandleScope scope(isolate_);
1383

    
1384
  PrepareForBreakPoints();
1385

    
1386
  ASSERT(Debug::InDebugger());
1387

    
1388
  // Remember this step action and count.
1389
  thread_local_.last_step_action_ = step_action;
1390
  if (step_action == StepOut) {
1391
    // For step out target frame will be found on the stack so there is no need
1392
    // to set step counter for it. It's expected to always be 0 for StepOut.
1393
    thread_local_.step_count_ = 0;
1394
  } else {
1395
    thread_local_.step_count_ = step_count;
1396
  }
1397

    
1398
  // Get the frame where the execution has stopped and skip the debug frame if
1399
  // any. The debug frame will only be present if execution was stopped due to
1400
  // hitting a break point. In other situations (e.g. unhandled exception) the
1401
  // debug frame is not present.
1402
  StackFrame::Id id = break_frame_id();
1403
  if (id == StackFrame::NO_ID) {
1404
    // If there is no JavaScript stack don't do anything.
1405
    return;
1406
  }
1407
  if (frame_id != StackFrame::NO_ID) {
1408
    id = frame_id;
1409
  }
1410
  JavaScriptFrameIterator frames_it(isolate_, id);
1411
  JavaScriptFrame* frame = frames_it.frame();
1412

    
1413
  // First of all ensure there is one-shot break points in the top handler
1414
  // if any.
1415
  FloodHandlerWithOneShot();
1416

    
1417
  // If the function on the top frame is unresolved perform step out. This will
1418
  // be the case when calling unknown functions and having the debugger stopped
1419
  // in an unhandled exception.
1420
  if (!frame->function()->IsJSFunction()) {
1421
    // Step out: Find the calling JavaScript frame and flood it with
1422
    // breakpoints.
1423
    frames_it.Advance();
1424
    // Fill the function to return to with one-shot break points.
1425
    JSFunction* function = frames_it.frame()->function();
1426
    FloodWithOneShot(Handle<JSFunction>(function));
1427
    return;
1428
  }
1429

    
1430
  // Get the debug info (create it if it does not exist).
1431
  Handle<JSFunction> function(frame->function());
1432
  Handle<SharedFunctionInfo> shared(function->shared());
1433
  if (!EnsureDebugInfo(shared, function)) {
1434
    // Return if ensuring debug info failed.
1435
    return;
1436
  }
1437
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1438

    
1439
  // Find the break location where execution has stopped.
1440
  BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1441
  // pc points to the instruction after the current one, possibly a break
1442
  // location as well. So the "- 1" to exclude it from the search.
1443
  it.FindBreakLocationFromAddress(frame->pc() - 1);
1444

    
1445
  // Compute whether or not the target is a call target.
1446
  bool is_load_or_store = false;
1447
  bool is_inline_cache_stub = false;
1448
  bool is_at_restarted_function = false;
1449
  Handle<Code> call_function_stub;
1450

    
1451
  if (thread_local_.restarter_frame_function_pointer_ == NULL) {
1452
    if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1453
      bool is_call_target = false;
1454
      Address target = it.rinfo()->target_address();
1455
      Code* code = Code::GetCodeFromTargetAddress(target);
1456
      if (code->is_call_stub() || code->is_keyed_call_stub()) {
1457
        is_call_target = true;
1458
      }
1459
      if (code->is_inline_cache_stub()) {
1460
        is_inline_cache_stub = true;
1461
        is_load_or_store = !is_call_target;
1462
      }
1463

    
1464
      // Check if target code is CallFunction stub.
1465
      Code* maybe_call_function_stub = code;
1466
      // If there is a breakpoint at this line look at the original code to
1467
      // check if it is a CallFunction stub.
1468
      if (it.IsDebugBreak()) {
1469
        Address original_target = it.original_rinfo()->target_address();
1470
        maybe_call_function_stub =
1471
            Code::GetCodeFromTargetAddress(original_target);
1472
      }
1473
      if (maybe_call_function_stub->kind() == Code::STUB &&
1474
          maybe_call_function_stub->major_key() == CodeStub::CallFunction) {
1475
        // Save reference to the code as we may need it to find out arguments
1476
        // count for 'step in' later.
1477
        call_function_stub = Handle<Code>(maybe_call_function_stub);
1478
      }
1479
    }
1480
  } else {
1481
    is_at_restarted_function = true;
1482
  }
1483

    
1484
  // If this is the last break code target step out is the only possibility.
1485
  if (it.IsExit() || step_action == StepOut) {
1486
    if (step_action == StepOut) {
1487
      // Skip step_count frames starting with the current one.
1488
      while (step_count-- > 0 && !frames_it.done()) {
1489
        frames_it.Advance();
1490
      }
1491
    } else {
1492
      ASSERT(it.IsExit());
1493
      frames_it.Advance();
1494
    }
1495
    // Skip builtin functions on the stack.
1496
    while (!frames_it.done() && frames_it.frame()->function()->IsBuiltin()) {
1497
      frames_it.Advance();
1498
    }
1499
    // Step out: If there is a JavaScript caller frame, we need to
1500
    // flood it with breakpoints.
1501
    if (!frames_it.done()) {
1502
      // Fill the function to return to with one-shot break points.
1503
      JSFunction* function = frames_it.frame()->function();
1504
      FloodWithOneShot(Handle<JSFunction>(function));
1505
      // Set target frame pointer.
1506
      ActivateStepOut(frames_it.frame());
1507
    }
1508
  } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
1509
               !call_function_stub.is_null() || is_at_restarted_function)
1510
             || step_action == StepNext || step_action == StepMin) {
1511
    // Step next or step min.
1512

    
1513
    // Fill the current function with one-shot break points.
1514
    FloodWithOneShot(function);
1515

    
1516
    // Remember source position and frame to handle step next.
1517
    thread_local_.last_statement_position_ =
1518
        debug_info->code()->SourceStatementPosition(frame->pc());
1519
    thread_local_.last_fp_ = frame->UnpaddedFP();
1520
  } else {
1521
    // If there's restarter frame on top of the stack, just get the pointer
1522
    // to function which is going to be restarted.
1523
    if (is_at_restarted_function) {
1524
      Handle<JSFunction> restarted_function(
1525
          JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
1526
      FloodWithOneShot(restarted_function);
1527
    } else if (!call_function_stub.is_null()) {
1528
      // If it's CallFunction stub ensure target function is compiled and flood
1529
      // it with one shot breakpoints.
1530

    
1531
      // Find out number of arguments from the stub minor key.
1532
      // Reverse lookup required as the minor key cannot be retrieved
1533
      // from the code object.
1534
      Handle<Object> obj(
1535
          isolate_->heap()->code_stubs()->SlowReverseLookup(
1536
              *call_function_stub),
1537
          isolate_);
1538
      ASSERT(!obj.is_null());
1539
      ASSERT(!(*obj)->IsUndefined());
1540
      ASSERT(obj->IsSmi());
1541
      // Get the STUB key and extract major and minor key.
1542
      uint32_t key = Smi::cast(*obj)->value();
1543
      // Argc in the stub is the number of arguments passed - not the
1544
      // expected arguments of the called function.
1545
      int call_function_arg_count =
1546
          CallFunctionStub::ExtractArgcFromMinorKey(
1547
              CodeStub::MinorKeyFromKey(key));
1548
      ASSERT(call_function_stub->major_key() ==
1549
             CodeStub::MajorKeyFromKey(key));
1550

    
1551
      // Find target function on the expression stack.
1552
      // Expression stack looks like this (top to bottom):
1553
      // argN
1554
      // ...
1555
      // arg0
1556
      // Receiver
1557
      // Function to call
1558
      int expressions_count = frame->ComputeExpressionsCount();
1559
      ASSERT(expressions_count - 2 - call_function_arg_count >= 0);
1560
      Object* fun = frame->GetExpression(
1561
          expressions_count - 2 - call_function_arg_count);
1562
      if (fun->IsJSFunction()) {
1563
        Handle<JSFunction> js_function(JSFunction::cast(fun));
1564
        if (js_function->shared()->bound()) {
1565
          Debug::FloodBoundFunctionWithOneShot(js_function);
1566
        } else if (!js_function->IsBuiltin()) {
1567
          // Don't step into builtins.
1568
          // It will also compile target function if it's not compiled yet.
1569
          FloodWithOneShot(js_function);
1570
        }
1571
      }
1572
    }
1573

    
1574
    // Fill the current function with one-shot break points even for step in on
1575
    // a call target as the function called might be a native function for
1576
    // which step in will not stop. It also prepares for stepping in
1577
    // getters/setters.
1578
    FloodWithOneShot(function);
1579

    
1580
    if (is_load_or_store) {
1581
      // Remember source position and frame to handle step in getter/setter. If
1582
      // there is a custom getter/setter it will be handled in
1583
      // Object::Get/SetPropertyWithCallback, otherwise the step action will be
1584
      // propagated on the next Debug::Break.
1585
      thread_local_.last_statement_position_ =
1586
          debug_info->code()->SourceStatementPosition(frame->pc());
1587
      thread_local_.last_fp_ = frame->UnpaddedFP();
1588
    }
1589

    
1590
    // Step in or Step in min
1591
    it.PrepareStepIn(isolate_);
1592
    ActivateStepIn(frame);
1593
  }
1594
}
1595

    
1596

    
1597
// Check whether the current debug break should be reported to the debugger. It
1598
// is used to have step next and step in only report break back to the debugger
1599
// if on a different frame or in a different statement. In some situations
1600
// there will be several break points in the same statement when the code is
1601
// flooded with one-shot break points. This function helps to perform several
1602
// steps before reporting break back to the debugger.
1603
bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1604
                             JavaScriptFrame* frame) {
1605
  // StepNext and StepOut shouldn't bring us deeper in code, so last frame
1606
  // shouldn't be a parent of current frame.
1607
  if (thread_local_.last_step_action_ == StepNext ||
1608
      thread_local_.last_step_action_ == StepOut) {
1609
    if (frame->fp() < thread_local_.last_fp_) return true;
1610
  }
1611

    
1612
  // If the step last action was step next or step in make sure that a new
1613
  // statement is hit.
1614
  if (thread_local_.last_step_action_ == StepNext ||
1615
      thread_local_.last_step_action_ == StepIn) {
1616
    // Never continue if returning from function.
1617
    if (break_location_iterator->IsExit()) return false;
1618

    
1619
    // Continue if we are still on the same frame and in the same statement.
1620
    int current_statement_position =
1621
        break_location_iterator->code()->SourceStatementPosition(frame->pc());
1622
    return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1623
        thread_local_.last_statement_position_ == current_statement_position;
1624
  }
1625

    
1626
  // No step next action - don't continue.
1627
  return false;
1628
}
1629

    
1630

    
1631
// Check whether the code object at the specified address is a debug break code
1632
// object.
1633
bool Debug::IsDebugBreak(Address addr) {
1634
  Code* code = Code::GetCodeFromTargetAddress(addr);
1635
  return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK;
1636
}
1637

    
1638

    
1639
// Check whether a code stub with the specified major key is a possible break
1640
// point location when looking for source break locations.
1641
bool Debug::IsSourceBreakStub(Code* code) {
1642
  CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1643
  return major_key == CodeStub::CallFunction;
1644
}
1645

    
1646

    
1647
// Check whether a code stub with the specified major key is a possible break
1648
// location.
1649
bool Debug::IsBreakStub(Code* code) {
1650
  CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1651
  return major_key == CodeStub::CallFunction;
1652
}
1653

    
1654

    
1655
// Find the builtin to use for invoking the debug break
1656
Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
1657
  Isolate* isolate = code->GetIsolate();
1658

    
1659
  // Find the builtin debug break function matching the calling convention
1660
  // used by the call site.
1661
  if (code->is_inline_cache_stub()) {
1662
    switch (code->kind()) {
1663
      case Code::CALL_IC:
1664
      case Code::KEYED_CALL_IC:
1665
        return isolate->stub_cache()->ComputeCallDebugBreak(
1666
            code->arguments_count(), code->kind());
1667

    
1668
      case Code::LOAD_IC:
1669
        return isolate->builtins()->LoadIC_DebugBreak();
1670

    
1671
      case Code::STORE_IC:
1672
        return isolate->builtins()->StoreIC_DebugBreak();
1673

    
1674
      case Code::KEYED_LOAD_IC:
1675
        return isolate->builtins()->KeyedLoadIC_DebugBreak();
1676

    
1677
      case Code::KEYED_STORE_IC:
1678
        return isolate->builtins()->KeyedStoreIC_DebugBreak();
1679

    
1680
      case Code::COMPARE_NIL_IC:
1681
        return isolate->builtins()->CompareNilIC_DebugBreak();
1682

    
1683
      default:
1684
        UNREACHABLE();
1685
    }
1686
  }
1687
  if (RelocInfo::IsConstructCall(mode)) {
1688
    if (code->has_function_cache()) {
1689
      return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
1690
    } else {
1691
      return isolate->builtins()->CallConstructStub_DebugBreak();
1692
    }
1693
  }
1694
  if (code->kind() == Code::STUB) {
1695
    ASSERT(code->major_key() == CodeStub::CallFunction);
1696
    if (code->has_function_cache()) {
1697
      return isolate->builtins()->CallFunctionStub_Recording_DebugBreak();
1698
    } else {
1699
      return isolate->builtins()->CallFunctionStub_DebugBreak();
1700
    }
1701
  }
1702

    
1703
  UNREACHABLE();
1704
  return Handle<Code>::null();
1705
}
1706

    
1707

    
1708
// Simple function for returning the source positions for active break points.
1709
Handle<Object> Debug::GetSourceBreakLocations(
1710
    Handle<SharedFunctionInfo> shared,
1711
    BreakPositionAlignment position_alignment) {
1712
  Isolate* isolate = shared->GetIsolate();
1713
  Heap* heap = isolate->heap();
1714
  if (!HasDebugInfo(shared)) {
1715
    return Handle<Object>(heap->undefined_value(), isolate);
1716
  }
1717
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1718
  if (debug_info->GetBreakPointCount() == 0) {
1719
    return Handle<Object>(heap->undefined_value(), isolate);
1720
  }
1721
  Handle<FixedArray> locations =
1722
      isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1723
  int count = 0;
1724
  for (int i = 0; i < debug_info->break_points()->length(); i++) {
1725
    if (!debug_info->break_points()->get(i)->IsUndefined()) {
1726
      BreakPointInfo* break_point_info =
1727
          BreakPointInfo::cast(debug_info->break_points()->get(i));
1728
      if (break_point_info->GetBreakPointCount() > 0) {
1729
        Smi* position;
1730
        switch (position_alignment) {
1731
        case STATEMENT_ALIGNED:
1732
          position = break_point_info->statement_position();
1733
          break;
1734
        case BREAK_POSITION_ALIGNED:
1735
          position = break_point_info->source_position();
1736
          break;
1737
        default:
1738
          UNREACHABLE();
1739
          position = break_point_info->statement_position();
1740
        }
1741

    
1742
        locations->set(count++, position);
1743
      }
1744
    }
1745
  }
1746
  return locations;
1747
}
1748

    
1749

    
1750
void Debug::NewBreak(StackFrame::Id break_frame_id) {
1751
  thread_local_.break_frame_id_ = break_frame_id;
1752
  thread_local_.break_id_ = ++thread_local_.break_count_;
1753
}
1754

    
1755

    
1756
void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) {
1757
  thread_local_.break_frame_id_ = break_frame_id;
1758
  thread_local_.break_id_ = break_id;
1759
}
1760

    
1761

    
1762
// Handle stepping into a function.
1763
void Debug::HandleStepIn(Handle<JSFunction> function,
1764
                         Handle<Object> holder,
1765
                         Address fp,
1766
                         bool is_constructor) {
1767
  Isolate* isolate = function->GetIsolate();
1768
  // If the frame pointer is not supplied by the caller find it.
1769
  if (fp == 0) {
1770
    StackFrameIterator it(isolate);
1771
    it.Advance();
1772
    // For constructor functions skip another frame.
1773
    if (is_constructor) {
1774
      ASSERT(it.frame()->is_construct());
1775
      it.Advance();
1776
    }
1777
    fp = it.frame()->fp();
1778
  }
1779

    
1780
  // Flood the function with one-shot break points if it is called from where
1781
  // step into was requested.
1782
  if (fp == step_in_fp()) {
1783
    if (function->shared()->bound()) {
1784
      // Handle Function.prototype.bind
1785
      Debug::FloodBoundFunctionWithOneShot(function);
1786
    } else if (!function->IsBuiltin()) {
1787
      // Don't allow step into functions in the native context.
1788
      if (function->shared()->code() ==
1789
          isolate->builtins()->builtin(Builtins::kFunctionApply) ||
1790
          function->shared()->code() ==
1791
          isolate->builtins()->builtin(Builtins::kFunctionCall)) {
1792
        // Handle function.apply and function.call separately to flood the
1793
        // function to be called and not the code for Builtins::FunctionApply or
1794
        // Builtins::FunctionCall. The receiver of call/apply is the target
1795
        // function.
1796
        if (!holder.is_null() && holder->IsJSFunction()) {
1797
          Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
1798
          if (!js_function->IsBuiltin()) {
1799
            Debug::FloodWithOneShot(js_function);
1800
          } else if (js_function->shared()->bound()) {
1801
            // Handle Function.prototype.bind
1802
            Debug::FloodBoundFunctionWithOneShot(js_function);
1803
          }
1804
        }
1805
      } else {
1806
        Debug::FloodWithOneShot(function);
1807
      }
1808
    }
1809
  }
1810
}
1811

    
1812

    
1813
void Debug::ClearStepping() {
1814
  // Clear the various stepping setup.
1815
  ClearOneShot();
1816
  ClearStepIn();
1817
  ClearStepOut();
1818
  ClearStepNext();
1819

    
1820
  // Clear multiple step counter.
1821
  thread_local_.step_count_ = 0;
1822
}
1823

    
1824

    
1825
// Clears all the one-shot break points that are currently set. Normally this
1826
// function is called each time a break point is hit as one shot break points
1827
// are used to support stepping.
1828
void Debug::ClearOneShot() {
1829
  // The current implementation just runs through all the breakpoints. When the
1830
  // last break point for a function is removed that function is automatically
1831
  // removed from the list.
1832

    
1833
  DebugInfoListNode* node = debug_info_list_;
1834
  while (node != NULL) {
1835
    BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1836
    while (!it.Done()) {
1837
      it.ClearOneShot();
1838
      it.Next();
1839
    }
1840
    node = node->next();
1841
  }
1842
}
1843

    
1844

    
1845
void Debug::ActivateStepIn(StackFrame* frame) {
1846
  ASSERT(!StepOutActive());
1847
  thread_local_.step_into_fp_ = frame->UnpaddedFP();
1848
}
1849

    
1850

    
1851
void Debug::ClearStepIn() {
1852
  thread_local_.step_into_fp_ = 0;
1853
}
1854

    
1855

    
1856
void Debug::ActivateStepOut(StackFrame* frame) {
1857
  ASSERT(!StepInActive());
1858
  thread_local_.step_out_fp_ = frame->UnpaddedFP();
1859
}
1860

    
1861

    
1862
void Debug::ClearStepOut() {
1863
  thread_local_.step_out_fp_ = 0;
1864
}
1865

    
1866

    
1867
void Debug::ClearStepNext() {
1868
  thread_local_.last_step_action_ = StepNone;
1869
  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1870
  thread_local_.last_fp_ = 0;
1871
}
1872

    
1873

    
1874
// Helper function to compile full code for debugging. This code will
1875
// have debug break slots and deoptimization information. Deoptimization
1876
// information is required in case that an optimized version of this
1877
// function is still activated on the stack. It will also make sure that
1878
// the full code is compiled with the same flags as the previous version,
1879
// that is flags which can change the code generated. The current method
1880
// of mapping from already compiled full code without debug break slots
1881
// to full code with debug break slots depends on the generated code is
1882
// otherwise exactly the same.
1883
static bool CompileFullCodeForDebugging(Handle<JSFunction> function,
1884
                                        Handle<Code> current_code) {
1885
  ASSERT(!current_code->has_debug_break_slots());
1886

    
1887
  CompilationInfoWithZone info(function);
1888
  info.MarkCompilingForDebugging(current_code);
1889
  ASSERT(!info.shared_info()->is_compiled());
1890
  ASSERT(!info.isolate()->has_pending_exception());
1891

    
1892
  // Use compile lazy which will end up compiling the full code in the
1893
  // configuration configured above.
1894
  bool result = Compiler::CompileLazy(&info);
1895
  ASSERT(result != info.isolate()->has_pending_exception());
1896
  info.isolate()->clear_pending_exception();
1897
#if DEBUG
1898
  if (result) {
1899
    Handle<Code> new_code(function->shared()->code());
1900
    ASSERT(new_code->has_debug_break_slots());
1901
    ASSERT(current_code->is_compiled_optimizable() ==
1902
           new_code->is_compiled_optimizable());
1903
  }
1904
#endif
1905
  return result;
1906
}
1907

    
1908

    
1909
static void CollectActiveFunctionsFromThread(
1910
    Isolate* isolate,
1911
    ThreadLocalTop* top,
1912
    List<Handle<JSFunction> >* active_functions,
1913
    Object* active_code_marker) {
1914
  // Find all non-optimized code functions with activation frames
1915
  // on the stack. This includes functions which have optimized
1916
  // activations (including inlined functions) on the stack as the
1917
  // non-optimized code is needed for the lazy deoptimization.
1918
  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1919
    JavaScriptFrame* frame = it.frame();
1920
    if (frame->is_optimized()) {
1921
      List<JSFunction*> functions(FLAG_max_inlining_levels + 1);
1922
      frame->GetFunctions(&functions);
1923
      for (int i = 0; i < functions.length(); i++) {
1924
        JSFunction* function = functions[i];
1925
        active_functions->Add(Handle<JSFunction>(function));
1926
        function->shared()->code()->set_gc_metadata(active_code_marker);
1927
      }
1928
    } else if (frame->function()->IsJSFunction()) {
1929
      JSFunction* function = frame->function();
1930
      ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1931
      active_functions->Add(Handle<JSFunction>(function));
1932
      function->shared()->code()->set_gc_metadata(active_code_marker);
1933
    }
1934
  }
1935
}
1936

    
1937

    
1938
static void RedirectActivationsToRecompiledCodeOnThread(
1939
    Isolate* isolate,
1940
    ThreadLocalTop* top) {
1941
  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1942
    JavaScriptFrame* frame = it.frame();
1943

    
1944
    if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue;
1945

    
1946
    JSFunction* function = frame->function();
1947

    
1948
    ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1949

    
1950
    Handle<Code> frame_code(frame->LookupCode());
1951
    if (frame_code->has_debug_break_slots()) continue;
1952

    
1953
    Handle<Code> new_code(function->shared()->code());
1954
    if (new_code->kind() != Code::FUNCTION ||
1955
        !new_code->has_debug_break_slots()) {
1956
      continue;
1957
    }
1958

    
1959
    // Iterate over the RelocInfo in the original code to compute the sum of the
1960
    // constant pools sizes. (See Assembler::CheckConstPool())
1961
    // Note that this is only useful for architectures using constant pools.
1962
    int constpool_mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL);
1963
    int frame_const_pool_size = 0;
1964
    for (RelocIterator it(*frame_code, constpool_mask); !it.done(); it.next()) {
1965
      RelocInfo* info = it.rinfo();
1966
      if (info->pc() >= frame->pc()) break;
1967
      frame_const_pool_size += static_cast<int>(info->data());
1968
    }
1969
    intptr_t frame_offset =
1970
      frame->pc() - frame_code->instruction_start() - frame_const_pool_size;
1971

    
1972
    // Iterate over the RelocInfo for new code to find the number of bytes
1973
    // generated for debug slots and constant pools.
1974
    int debug_break_slot_bytes = 0;
1975
    int new_code_const_pool_size = 0;
1976
    int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
1977
               RelocInfo::ModeMask(RelocInfo::CONST_POOL);
1978
    for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
1979
      // Check if the pc in the new code with debug break
1980
      // slots is before this slot.
1981
      RelocInfo* info = it.rinfo();
1982
      intptr_t new_offset = info->pc() - new_code->instruction_start() -
1983
                            new_code_const_pool_size - debug_break_slot_bytes;
1984
      if (new_offset >= frame_offset) {
1985
        break;
1986
      }
1987

    
1988
      if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
1989
        debug_break_slot_bytes += Assembler::kDebugBreakSlotLength;
1990
      } else {
1991
        ASSERT(RelocInfo::IsConstPool(info->rmode()));
1992
        // The size of the constant pool is encoded in the data.
1993
        new_code_const_pool_size += static_cast<int>(info->data());
1994
      }
1995
    }
1996

    
1997
    // Compute the equivalent pc in the new code.
1998
    byte* new_pc = new_code->instruction_start() + frame_offset +
1999
                   debug_break_slot_bytes + new_code_const_pool_size;
2000

    
2001
    if (FLAG_trace_deopt) {
2002
      PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
2003
             "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
2004
             "for debugging, "
2005
             "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
2006
             reinterpret_cast<intptr_t>(
2007
                 frame_code->instruction_start()),
2008
             reinterpret_cast<intptr_t>(
2009
                 frame_code->instruction_start()) +
2010
             frame_code->instruction_size(),
2011
             frame_code->instruction_size(),
2012
             reinterpret_cast<intptr_t>(new_code->instruction_start()),
2013
             reinterpret_cast<intptr_t>(new_code->instruction_start()) +
2014
             new_code->instruction_size(),
2015
             new_code->instruction_size(),
2016
             reinterpret_cast<intptr_t>(frame->pc()),
2017
             reinterpret_cast<intptr_t>(new_pc));
2018
    }
2019

    
2020
    // Patch the return address to return into the code with
2021
    // debug break slots.
2022
    frame->set_pc(new_pc);
2023
  }
2024
}
2025

    
2026

    
2027
class ActiveFunctionsCollector : public ThreadVisitor {
2028
 public:
2029
  explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
2030
                                    Object* active_code_marker)
2031
      : active_functions_(active_functions),
2032
        active_code_marker_(active_code_marker) { }
2033

    
2034
  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
2035
    CollectActiveFunctionsFromThread(isolate,
2036
                                     top,
2037
                                     active_functions_,
2038
                                     active_code_marker_);
2039
  }
2040

    
2041
 private:
2042
  List<Handle<JSFunction> >* active_functions_;
2043
  Object* active_code_marker_;
2044
};
2045

    
2046

    
2047
class ActiveFunctionsRedirector : public ThreadVisitor {
2048
 public:
2049
  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
2050
    RedirectActivationsToRecompiledCodeOnThread(isolate, top);
2051
  }
2052
};
2053

    
2054

    
2055
void Debug::PrepareForBreakPoints() {
2056
  // If preparing for the first break point make sure to deoptimize all
2057
  // functions as debugging does not work with optimized code.
2058
  if (!has_break_points_) {
2059
    if (FLAG_concurrent_recompilation) {
2060
      isolate_->optimizing_compiler_thread()->Flush();
2061
    }
2062

    
2063
    Deoptimizer::DeoptimizeAll(isolate_);
2064

    
2065
    Handle<Code> lazy_compile =
2066
        Handle<Code>(isolate_->builtins()->builtin(Builtins::kLazyCompile));
2067

    
2068
    // There will be at least one break point when we are done.
2069
    has_break_points_ = true;
2070

    
2071
    // Keep the list of activated functions in a handlified list as it
2072
    // is used both in GC and non-GC code.
2073
    List<Handle<JSFunction> > active_functions(100);
2074

    
2075
    {
2076
      // We are going to iterate heap to find all functions without
2077
      // debug break slots.
2078
      Heap* heap = isolate_->heap();
2079
      heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
2080
                              "preparing for breakpoints");
2081

    
2082
      // Ensure no GC in this scope as we are going to use gc_metadata
2083
      // field in the Code object to mark active functions.
2084
      DisallowHeapAllocation no_allocation;
2085

    
2086
      Object* active_code_marker = heap->the_hole_value();
2087

    
2088
      CollectActiveFunctionsFromThread(isolate_,
2089
                                       isolate_->thread_local_top(),
2090
                                       &active_functions,
2091
                                       active_code_marker);
2092
      ActiveFunctionsCollector active_functions_collector(&active_functions,
2093
                                                          active_code_marker);
2094
      isolate_->thread_manager()->IterateArchivedThreads(
2095
          &active_functions_collector);
2096

    
2097
      // Scan the heap for all non-optimized functions which have no
2098
      // debug break slots and are not active or inlined into an active
2099
      // function and mark them for lazy compilation.
2100
      HeapIterator iterator(heap);
2101
      HeapObject* obj = NULL;
2102
      while (((obj = iterator.next()) != NULL)) {
2103
        if (obj->IsJSFunction()) {
2104
          JSFunction* function = JSFunction::cast(obj);
2105
          SharedFunctionInfo* shared = function->shared();
2106

    
2107
          if (!shared->allows_lazy_compilation()) continue;
2108
          if (!shared->script()->IsScript()) continue;
2109
          if (function->IsBuiltin()) continue;
2110
          if (shared->code()->gc_metadata() == active_code_marker) continue;
2111

    
2112
          Code::Kind kind = function->code()->kind();
2113
          if (kind == Code::FUNCTION &&
2114
              !function->code()->has_debug_break_slots()) {
2115
            function->set_code(*lazy_compile);
2116
            function->shared()->set_code(*lazy_compile);
2117
          } else if (kind == Code::BUILTIN &&
2118
              (function->IsInRecompileQueue() ||
2119
               function->IsMarkedForLazyRecompilation() ||
2120
               function->IsMarkedForConcurrentRecompilation())) {
2121
            // Abort in-flight compilation.
2122
            Code* shared_code = function->shared()->code();
2123
            if (shared_code->kind() == Code::FUNCTION &&
2124
                shared_code->has_debug_break_slots()) {
2125
              function->set_code(shared_code);
2126
            } else {
2127
              function->set_code(*lazy_compile);
2128
              function->shared()->set_code(*lazy_compile);
2129
            }
2130
          }
2131
        }
2132
      }
2133

    
2134
      // Clear gc_metadata field.
2135
      for (int i = 0; i < active_functions.length(); i++) {
2136
        Handle<JSFunction> function = active_functions[i];
2137
        function->shared()->code()->set_gc_metadata(Smi::FromInt(0));
2138
      }
2139
    }
2140

    
2141
    // Now recompile all functions with activation frames and and
2142
    // patch the return address to run in the new compiled code.
2143
    for (int i = 0; i < active_functions.length(); i++) {
2144
      Handle<JSFunction> function = active_functions[i];
2145
      Handle<SharedFunctionInfo> shared(function->shared());
2146

    
2147
      if (function->code()->kind() == Code::FUNCTION &&
2148
          function->code()->has_debug_break_slots()) {
2149
        // Nothing to do. Function code already had debug break slots.
2150
        continue;
2151
      }
2152

    
2153
      // If recompilation is not possible just skip it.
2154
      if (shared->is_toplevel() ||
2155
          !shared->allows_lazy_compilation() ||
2156
          shared->code()->kind() == Code::BUILTIN) {
2157
        continue;
2158
      }
2159

    
2160
      // Make sure that the shared full code is compiled with debug
2161
      // break slots.
2162
      if (!shared->code()->has_debug_break_slots()) {
2163
        // Try to compile the full code with debug break slots. If it
2164
        // fails just keep the current code.
2165
        Handle<Code> current_code(function->shared()->code());
2166
        shared->set_code(*lazy_compile);
2167
        bool prev_force_debugger_active =
2168
            isolate_->debugger()->force_debugger_active();
2169
        isolate_->debugger()->set_force_debugger_active(true);
2170
        ASSERT(current_code->kind() == Code::FUNCTION);
2171
        CompileFullCodeForDebugging(function, current_code);
2172
        isolate_->debugger()->set_force_debugger_active(
2173
            prev_force_debugger_active);
2174
        if (!shared->is_compiled()) {
2175
          shared->set_code(*current_code);
2176
          continue;
2177
        }
2178
      }
2179

    
2180
      // Keep function code in sync with shared function info.
2181
      function->set_code(shared->code());
2182
    }
2183

    
2184
    RedirectActivationsToRecompiledCodeOnThread(isolate_,
2185
                                                isolate_->thread_local_top());
2186

    
2187
    ActiveFunctionsRedirector active_functions_redirector;
2188
    isolate_->thread_manager()->IterateArchivedThreads(
2189
          &active_functions_redirector);
2190
  }
2191
}
2192

    
2193

    
2194
Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2195
                                              int position) {
2196
  // Iterate the heap looking for SharedFunctionInfo generated from the
2197
  // script. The inner most SharedFunctionInfo containing the source position
2198
  // for the requested break point is found.
2199
  // NOTE: This might require several heap iterations. If the SharedFunctionInfo
2200
  // which is found is not compiled it is compiled and the heap is iterated
2201
  // again as the compilation might create inner functions from the newly
2202
  // compiled function and the actual requested break point might be in one of
2203
  // these functions.
2204
  // NOTE: The below fix-point iteration depends on all functions that cannot be
2205
  // compiled lazily without a context to not be compiled at all. Compilation
2206
  // will be triggered at points where we do not need a context.
2207
  bool done = false;
2208
  // The current candidate for the source position:
2209
  int target_start_position = RelocInfo::kNoPosition;
2210
  Handle<JSFunction> target_function;
2211
  Handle<SharedFunctionInfo> target;
2212
  Heap* heap = isolate_->heap();
2213
  while (!done) {
2214
    { // Extra scope for iterator and no-allocation.
2215
      heap->EnsureHeapIsIterable();
2216
      DisallowHeapAllocation no_alloc_during_heap_iteration;
2217
      HeapIterator iterator(heap);
2218
      for (HeapObject* obj = iterator.next();
2219
           obj != NULL; obj = iterator.next()) {
2220
        bool found_next_candidate = false;
2221
        Handle<JSFunction> function;
2222
        Handle<SharedFunctionInfo> shared;
2223
        if (obj->IsJSFunction()) {
2224
          function = Handle<JSFunction>(JSFunction::cast(obj));
2225
          shared = Handle<SharedFunctionInfo>(function->shared());
2226
          ASSERT(shared->allows_lazy_compilation() || shared->is_compiled());
2227
          found_next_candidate = true;
2228
        } else if (obj->IsSharedFunctionInfo()) {
2229
          shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj));
2230
          // Skip functions that we cannot compile lazily without a context,
2231
          // which is not available here, because there is no closure.
2232
          found_next_candidate = shared->is_compiled() ||
2233
              shared->allows_lazy_compilation_without_context();
2234
        }
2235
        if (!found_next_candidate) continue;
2236
        if (shared->script() == *script) {
2237
          // If the SharedFunctionInfo found has the requested script data and
2238
          // contains the source position it is a candidate.
2239
          int start_position = shared->function_token_position();
2240
          if (start_position == RelocInfo::kNoPosition) {
2241
            start_position = shared->start_position();
2242
          }
2243
          if (start_position <= position &&
2244
              position <= shared->end_position()) {
2245
            // If there is no candidate or this function is within the current
2246
            // candidate this is the new candidate.
2247
            if (target.is_null()) {
2248
              target_start_position = start_position;
2249
              target_function = function;
2250
              target = shared;
2251
            } else {
2252
              if (target_start_position == start_position &&
2253
                  shared->end_position() == target->end_position()) {
2254
                // If a top-level function contains only one function
2255
                // declaration the source for the top-level and the function
2256
                // is the same. In that case prefer the non top-level function.
2257
                if (!shared->is_toplevel()) {
2258
                  target_start_position = start_position;
2259
                  target_function = function;
2260
                  target = shared;
2261
                }
2262
              } else if (target_start_position <= start_position &&
2263
                         shared->end_position() <= target->end_position()) {
2264
                // This containment check includes equality as a function
2265
                // inside a top-level function can share either start or end
2266
                // position with the top-level function.
2267
                target_start_position = start_position;
2268
                target_function = function;
2269
                target = shared;
2270
              }
2271
            }
2272
          }
2273
        }
2274
      }  // End for loop.
2275
    }  // End no-allocation scope.
2276

    
2277
    if (target.is_null()) return heap->undefined_value();
2278

    
2279
    // There will be at least one break point when we are done.
2280
    has_break_points_ = true;
2281

    
2282
    // If the candidate found is compiled we are done.
2283
    done = target->is_compiled();
2284
    if (!done) {
2285
      // If the candidate is not compiled, compile it to reveal any inner
2286
      // functions which might contain the requested source position. This
2287
      // will compile all inner functions that cannot be compiled without a
2288
      // context, because Compiler::BuildFunctionInfo checks whether the
2289
      // debugger is active.
2290
      if (target_function.is_null()) {
2291
        SharedFunctionInfo::CompileLazy(target, KEEP_EXCEPTION);
2292
      } else {
2293
        JSFunction::CompileLazy(target_function, KEEP_EXCEPTION);
2294
      }
2295
    }
2296
  }  // End while loop.
2297

    
2298
  return *target;
2299
}
2300

    
2301

    
2302
// Ensures the debug information is present for shared.
2303
bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2304
                            Handle<JSFunction> function) {
2305
  Isolate* isolate = shared->GetIsolate();
2306

    
2307
  // Return if we already have the debug info for shared.
2308
  if (HasDebugInfo(shared)) {
2309
    ASSERT(shared->is_compiled());
2310
    return true;
2311
  }
2312

    
2313
  // There will be at least one break point when we are done.
2314
  has_break_points_ = true;
2315

    
2316
  // Ensure function is compiled. Return false if this failed.
2317
  if (!function.is_null() &&
2318
      !JSFunction::EnsureCompiled(function, CLEAR_EXCEPTION)) {
2319
    return false;
2320
  }
2321

    
2322
  // Create the debug info object.
2323
  Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared);
2324

    
2325
  // Add debug info to the list.
2326
  DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
2327
  node->set_next(debug_info_list_);
2328
  debug_info_list_ = node;
2329

    
2330
  return true;
2331
}
2332

    
2333

    
2334
void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
2335
  ASSERT(debug_info_list_ != NULL);
2336
  // Run through the debug info objects to find this one and remove it.
2337
  DebugInfoListNode* prev = NULL;
2338
  DebugInfoListNode* current = debug_info_list_;
2339
  while (current != NULL) {
2340
    if (*current->debug_info() == *debug_info) {
2341
      // Unlink from list. If prev is NULL we are looking at the first element.
2342
      if (prev == NULL) {
2343
        debug_info_list_ = current->next();
2344
      } else {
2345
        prev->set_next(current->next());
2346
      }
2347
      current->debug_info()->shared()->set_debug_info(
2348
              isolate_->heap()->undefined_value());
2349
      delete current;
2350

    
2351
      // If there are no more debug info objects there are not more break
2352
      // points.
2353
      has_break_points_ = debug_info_list_ != NULL;
2354

    
2355
      return;
2356
    }
2357
    // Move to next in list.
2358
    prev = current;
2359
    current = current->next();
2360
  }
2361
  UNREACHABLE();
2362
}
2363

    
2364

    
2365
void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
2366
  HandleScope scope(isolate_);
2367

    
2368
  PrepareForBreakPoints();
2369

    
2370
  // Get the executing function in which the debug break occurred.
2371
  Handle<JSFunction> function(JSFunction::cast(frame->function()));
2372
  Handle<SharedFunctionInfo> shared(function->shared());
2373
  if (!EnsureDebugInfo(shared, function)) {
2374
    // Return if we failed to retrieve the debug info.
2375
    return;
2376
  }
2377
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2378
  Handle<Code> code(debug_info->code());
2379
  Handle<Code> original_code(debug_info->original_code());
2380
#ifdef DEBUG
2381
  // Get the code which is actually executing.
2382
  Handle<Code> frame_code(frame->LookupCode());
2383
  ASSERT(frame_code.is_identical_to(code));
2384
#endif
2385

    
2386
  // Find the call address in the running code. This address holds the call to
2387
  // either a DebugBreakXXX or to the debug break return entry code if the
2388
  // break point is still active after processing the break point.
2389
  Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset;
2390

    
2391
  // Check if the location is at JS exit or debug break slot.
2392
  bool at_js_return = false;
2393
  bool break_at_js_return_active = false;
2394
  bool at_debug_break_slot = false;
2395
  RelocIterator it(debug_info->code());
2396
  while (!it.done() && !at_js_return && !at_debug_break_slot) {
2397
    if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2398
      at_js_return = (it.rinfo()->pc() ==
2399
          addr - Assembler::kPatchReturnSequenceAddressOffset);
2400
      break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
2401
    }
2402
    if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2403
      at_debug_break_slot = (it.rinfo()->pc() ==
2404
          addr - Assembler::kPatchDebugBreakSlotAddressOffset);
2405
    }
2406
    it.next();
2407
  }
2408

    
2409
  // Handle the jump to continue execution after break point depending on the
2410
  // break location.
2411
  if (at_js_return) {
2412
    // If the break point as return is still active jump to the corresponding
2413
    // place in the original code. If not the break point was removed during
2414
    // break point processing.
2415
    if (break_at_js_return_active) {
2416
      addr +=  original_code->instruction_start() - code->instruction_start();
2417
    }
2418

    
2419
    // Move back to where the call instruction sequence started.
2420
    thread_local_.after_break_target_ =
2421
        addr - Assembler::kPatchReturnSequenceAddressOffset;
2422
  } else if (at_debug_break_slot) {
2423
    // Address of where the debug break slot starts.
2424
    addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
2425

    
2426
    // Continue just after the slot.
2427
    thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
2428
  } else if (IsDebugBreak(Assembler::target_address_at(addr))) {
2429
    // We now know that there is still a debug break call at the target address,
2430
    // so the break point is still there and the original code will hold the
2431
    // address to jump to in order to complete the call which is replaced by a
2432
    // call to DebugBreakXXX.
2433

    
2434
    // Find the corresponding address in the original code.
2435
    addr += original_code->instruction_start() - code->instruction_start();
2436

    
2437
    // Install jump to the call address in the original code. This will be the
2438
    // call which was overwritten by the call to DebugBreakXXX.
2439
    thread_local_.after_break_target_ = Assembler::target_address_at(addr);
2440
  } else {
2441
    // There is no longer a break point present. Don't try to look in the
2442
    // original code as the running code will have the right address. This takes
2443
    // care of the case where the last break point is removed from the function
2444
    // and therefore no "original code" is available.
2445
    thread_local_.after_break_target_ = Assembler::target_address_at(addr);
2446
  }
2447
}
2448

    
2449

    
2450
bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
2451
  HandleScope scope(isolate_);
2452

    
2453
  // If there are no break points this cannot be break at return, as
2454
  // the debugger statement and stack guard bebug break cannot be at
2455
  // return.
2456
  if (!has_break_points_) {
2457
    return false;
2458
  }
2459

    
2460
  PrepareForBreakPoints();
2461

    
2462
  // Get the executing function in which the debug break occurred.
2463
  Handle<JSFunction> function(JSFunction::cast(frame->function()));
2464
  Handle<SharedFunctionInfo> shared(function->shared());
2465
  if (!EnsureDebugInfo(shared, function)) {
2466
    // Return if we failed to retrieve the debug info.
2467
    return false;
2468
  }
2469
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2470
  Handle<Code> code(debug_info->code());
2471
#ifdef DEBUG
2472
  // Get the code which is actually executing.
2473
  Handle<Code> frame_code(frame->LookupCode());
2474
  ASSERT(frame_code.is_identical_to(code));
2475
#endif
2476

    
2477
  // Find the call address in the running code.
2478
  Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset;
2479

    
2480
  // Check if the location is at JS return.
2481
  RelocIterator it(debug_info->code());
2482
  while (!it.done()) {
2483
    if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2484
      return (it.rinfo()->pc() ==
2485
          addr - Assembler::kPatchReturnSequenceAddressOffset);
2486
    }
2487
    it.next();
2488
  }
2489
  return false;
2490
}
2491

    
2492

    
2493
void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
2494
                                  FrameDropMode mode,
2495
                                  Object** restarter_frame_function_pointer) {
2496
  if (mode != CURRENTLY_SET_MODE) {
2497
    thread_local_.frame_drop_mode_ = mode;
2498
  }
2499
  thread_local_.break_frame_id_ = new_break_frame_id;
2500
  thread_local_.restarter_frame_function_pointer_ =
2501
      restarter_frame_function_pointer;
2502
}
2503

    
2504

    
2505
const int Debug::FramePaddingLayout::kInitialSize = 1;
2506

    
2507

    
2508
// Any even value bigger than kInitialSize as needed for stack scanning.
2509
const int Debug::FramePaddingLayout::kPaddingValue = kInitialSize + 1;
2510

    
2511

    
2512
bool Debug::IsDebugGlobal(GlobalObject* global) {
2513
  return IsLoaded() && global == debug_context()->global_object();
2514
}
2515

    
2516

    
2517
void Debug::ClearMirrorCache() {
2518
  PostponeInterruptsScope postpone(isolate_);
2519
  HandleScope scope(isolate_);
2520
  ASSERT(isolate_->context() == *Debug::debug_context());
2521

    
2522
  // Clear the mirror cache.
2523
  Handle<String> function_name = isolate_->factory()->InternalizeOneByteString(
2524
      STATIC_ASCII_VECTOR("ClearMirrorCache"));
2525
  Handle<Object> fun(
2526
      isolate_->global_object()->GetPropertyNoExceptionThrown(*function_name),
2527
      isolate_);
2528
  ASSERT(fun->IsJSFunction());
2529
  bool caught_exception;
2530
  Execution::TryCall(Handle<JSFunction>::cast(fun),
2531
      Handle<JSObject>(Debug::debug_context()->global_object()),
2532
      0, NULL, &caught_exception);
2533
}
2534

    
2535

    
2536
void Debug::CreateScriptCache() {
2537
  Heap* heap = isolate_->heap();
2538
  HandleScope scope(isolate_);
2539

    
2540
  // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
2541
  // rid of all the cached script wrappers and the second gets rid of the
2542
  // scripts which are no longer referenced.  The second also sweeps precisely,
2543
  // which saves us doing yet another GC to make the heap iterable.
2544
  heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache");
2545
  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
2546
                          "Debug::CreateScriptCache");
2547

    
2548
  ASSERT(script_cache_ == NULL);
2549
  script_cache_ = new ScriptCache(isolate_);
2550

    
2551
  // Scan heap for Script objects.
2552
  int count = 0;
2553
  HeapIterator iterator(heap);
2554
  DisallowHeapAllocation no_allocation;
2555

    
2556
  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
2557
    if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
2558
      script_cache_->Add(Handle<Script>(Script::cast(obj)));
2559
      count++;
2560
    }
2561
  }
2562
}
2563

    
2564

    
2565
void Debug::DestroyScriptCache() {
2566
  // Get rid of the script cache if it was created.
2567
  if (script_cache_ != NULL) {
2568
    delete script_cache_;
2569
    script_cache_ = NULL;
2570
  }
2571
}
2572

    
2573

    
2574
void Debug::AddScriptToScriptCache(Handle<Script> script) {
2575
  if (script_cache_ != NULL) {
2576
    script_cache_->Add(script);
2577
  }
2578
}
2579

    
2580

    
2581
Handle<FixedArray> Debug::GetLoadedScripts() {
2582
  // Create and fill the script cache when the loaded scripts is requested for
2583
  // the first time.
2584
  if (script_cache_ == NULL) {
2585
    CreateScriptCache();
2586
  }
2587

    
2588
  // If the script cache is not active just return an empty array.
2589
  ASSERT(script_cache_ != NULL);
2590
  if (script_cache_ == NULL) {
2591
    isolate_->factory()->NewFixedArray(0);
2592
  }
2593

    
2594
  // Perform GC to get unreferenced scripts evicted from the cache before
2595
  // returning the content.
2596
  isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
2597
                                      "Debug::GetLoadedScripts");
2598

    
2599
  // Get the scripts from the cache.
2600
  return script_cache_->GetScripts();
2601
}
2602

    
2603

    
2604
void Debug::AfterGarbageCollection() {
2605
  // Generate events for collected scripts.
2606
  if (script_cache_ != NULL) {
2607
    script_cache_->ProcessCollectedScripts();
2608
  }
2609
}
2610

    
2611

    
2612
Debugger::Debugger(Isolate* isolate)
2613
    : debugger_access_(isolate->debugger_access()),
2614
      event_listener_(Handle<Object>()),
2615
      event_listener_data_(Handle<Object>()),
2616
      compiling_natives_(false),
2617
      is_loading_debugger_(false),
2618
      live_edit_enabled_(true),
2619
      never_unload_debugger_(false),
2620
      force_debugger_active_(false),
2621
      message_handler_(NULL),
2622
      debugger_unload_pending_(false),
2623
      host_dispatch_handler_(NULL),
2624
      debug_message_dispatch_handler_(NULL),
2625
      message_dispatch_helper_thread_(NULL),
2626
      host_dispatch_period_(TimeDelta::FromMilliseconds(100)),
2627
      agent_(NULL),
2628
      command_queue_(isolate->logger(), kQueueInitialSize),
2629
      command_received_(0),
2630
      event_command_queue_(isolate->logger(), kQueueInitialSize),
2631
      isolate_(isolate) {
2632
}
2633

    
2634

    
2635
Debugger::~Debugger() {}
2636

    
2637

    
2638
Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
2639
                                      int argc,
2640
                                      Handle<Object> argv[],
2641
                                      bool* caught_exception) {
2642
  ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2643

    
2644
  // Create the execution state object.
2645
  Handle<String> constructor_str =
2646
      isolate_->factory()->InternalizeUtf8String(constructor_name);
2647
  Handle<Object> constructor(
2648
      isolate_->global_object()->GetPropertyNoExceptionThrown(*constructor_str),
2649
      isolate_);
2650
  ASSERT(constructor->IsJSFunction());
2651
  if (!constructor->IsJSFunction()) {
2652
    *caught_exception = true;
2653
    return isolate_->factory()->undefined_value();
2654
  }
2655
  Handle<Object> js_object = Execution::TryCall(
2656
      Handle<JSFunction>::cast(constructor),
2657
      Handle<JSObject>(isolate_->debug()->debug_context()->global_object()),
2658
      argc,
2659
      argv,
2660
      caught_exception);
2661
  return js_object;
2662
}
2663

    
2664

    
2665
Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
2666
  // Create the execution state object.
2667
  Handle<Object> break_id = isolate_->factory()->NewNumberFromInt(
2668
      isolate_->debug()->break_id());
2669
  Handle<Object> argv[] = { break_id };
2670
  return MakeJSObject(CStrVector("MakeExecutionState"),
2671
                      ARRAY_SIZE(argv),
2672
                      argv,
2673
                      caught_exception);
2674
}
2675

    
2676

    
2677
Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
2678
                                        Handle<Object> break_points_hit,
2679
                                        bool* caught_exception) {
2680
  // Create the new break event object.
2681
  Handle<Object> argv[] = { exec_state, break_points_hit };
2682
  return MakeJSObject(CStrVector("MakeBreakEvent"),
2683
                      ARRAY_SIZE(argv),
2684
                      argv,
2685
                      caught_exception);
2686
}
2687

    
2688

    
2689
Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
2690
                                            Handle<Object> exception,
2691
                                            bool uncaught,
2692
                                            bool* caught_exception) {
2693
  Factory* factory = isolate_->factory();
2694
  // Create the new exception event object.
2695
  Handle<Object> argv[] = { exec_state,
2696
                            exception,
2697
                            factory->ToBoolean(uncaught) };
2698
  return MakeJSObject(CStrVector("MakeExceptionEvent"),
2699
                      ARRAY_SIZE(argv),
2700
                      argv,
2701
                      caught_exception);
2702
}
2703

    
2704

    
2705
Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
2706
                                              bool* caught_exception) {
2707
  // Create the new function event object.
2708
  Handle<Object> argv[] = { function };
2709
  return MakeJSObject(CStrVector("MakeNewFunctionEvent"),
2710
                      ARRAY_SIZE(argv),
2711
                      argv,
2712
                      caught_exception);
2713
}
2714

    
2715

    
2716
Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
2717
                                          bool before,
2718
                                          bool* caught_exception) {
2719
  Factory* factory = isolate_->factory();
2720
  // Create the compile event object.
2721
  Handle<Object> exec_state = MakeExecutionState(caught_exception);
2722
  Handle<Object> script_wrapper = GetScriptWrapper(script);
2723
  Handle<Object> argv[] = { exec_state,
2724
                            script_wrapper,
2725
                            factory->ToBoolean(before) };
2726
  return MakeJSObject(CStrVector("MakeCompileEvent"),
2727
                      ARRAY_SIZE(argv),
2728
                      argv,
2729
                      caught_exception);
2730
}
2731

    
2732

    
2733
Handle<Object> Debugger::MakeScriptCollectedEvent(int id,
2734
                                                  bool* caught_exception) {
2735
  // Create the script collected event object.
2736
  Handle<Object> exec_state = MakeExecutionState(caught_exception);
2737
  Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_);
2738
  Handle<Object> argv[] = { exec_state, id_object };
2739

    
2740
  return MakeJSObject(CStrVector("MakeScriptCollectedEvent"),
2741
                      ARRAY_SIZE(argv),
2742
                      argv,
2743
                      caught_exception);
2744
}
2745

    
2746

    
2747
void Debugger::OnException(Handle<Object> exception, bool uncaught) {
2748
  HandleScope scope(isolate_);
2749
  Debug* debug = isolate_->debug();
2750

    
2751
  // Bail out based on state or if there is no listener for this event
2752
  if (debug->InDebugger()) return;
2753
  if (!Debugger::EventActive(v8::Exception)) return;
2754

    
2755
  // Bail out if exception breaks are not active
2756
  if (uncaught) {
2757
    // Uncaught exceptions are reported by either flags.
2758
    if (!(debug->break_on_uncaught_exception() ||
2759
          debug->break_on_exception())) return;
2760
  } else {
2761
    // Caught exceptions are reported is activated.
2762
    if (!debug->break_on_exception()) return;
2763
  }
2764

    
2765
  // Enter the debugger.
2766
  EnterDebugger debugger(isolate_);
2767
  if (debugger.FailedToEnter()) return;
2768

    
2769
  // Clear all current stepping setup.
2770
  debug->ClearStepping();
2771
  // Create the event data object.
2772
  bool caught_exception = false;
2773
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2774
  Handle<Object> event_data;
2775
  if (!caught_exception) {
2776
    event_data = MakeExceptionEvent(exec_state, exception, uncaught,
2777
                                    &caught_exception);
2778
  }
2779
  // Bail out and don't call debugger if exception.
2780
  if (caught_exception) {
2781
    return;
2782
  }
2783

    
2784
  // Process debug event.
2785
  ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
2786
  // Return to continue execution from where the exception was thrown.
2787
}
2788

    
2789

    
2790
void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
2791
                            bool auto_continue) {
2792
  HandleScope scope(isolate_);
2793

    
2794
  // Debugger has already been entered by caller.
2795
  ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2796

    
2797
  // Bail out if there is no listener for this event
2798
  if (!Debugger::EventActive(v8::Break)) return;
2799

    
2800
  // Debugger must be entered in advance.
2801
  ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2802

    
2803
  // Create the event data object.
2804
  bool caught_exception = false;
2805
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2806
  Handle<Object> event_data;
2807
  if (!caught_exception) {
2808
    event_data = MakeBreakEvent(exec_state, break_points_hit,
2809
                                &caught_exception);
2810
  }
2811
  // Bail out and don't call debugger if exception.
2812
  if (caught_exception) {
2813
    return;
2814
  }
2815

    
2816
  // Process debug event.
2817
  ProcessDebugEvent(v8::Break,
2818
                    Handle<JSObject>::cast(event_data),
2819
                    auto_continue);
2820
}
2821

    
2822

    
2823
void Debugger::OnBeforeCompile(Handle<Script> script) {
2824
  HandleScope scope(isolate_);
2825

    
2826
  // Bail out based on state or if there is no listener for this event
2827
  if (isolate_->debug()->InDebugger()) return;
2828
  if (compiling_natives()) return;
2829
  if (!EventActive(v8::BeforeCompile)) return;
2830

    
2831
  // Enter the debugger.
2832
  EnterDebugger debugger(isolate_);
2833
  if (debugger.FailedToEnter()) return;
2834

    
2835
  // Create the event data object.
2836
  bool caught_exception = false;
2837
  Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception);
2838
  // Bail out and don't call debugger if exception.
2839
  if (caught_exception) {
2840
    return;
2841
  }
2842

    
2843
  // Process debug event.
2844
  ProcessDebugEvent(v8::BeforeCompile,
2845
                    Handle<JSObject>::cast(event_data),
2846
                    true);
2847
}
2848

    
2849

    
2850
// Handle debugger actions when a new script is compiled.
2851
void Debugger::OnAfterCompile(Handle<Script> script,
2852
                              AfterCompileFlags after_compile_flags) {
2853
  HandleScope scope(isolate_);
2854
  Debug* debug = isolate_->debug();
2855

    
2856
  // Add the newly compiled script to the script cache.
2857
  debug->AddScriptToScriptCache(script);
2858

    
2859
  // No more to do if not debugging.
2860
  if (!IsDebuggerActive()) return;
2861

    
2862
  // No compile events while compiling natives.
2863
  if (compiling_natives()) return;
2864

    
2865
  // Store whether in debugger before entering debugger.
2866
  bool in_debugger = debug->InDebugger();
2867

    
2868
  // Enter the debugger.
2869
  EnterDebugger debugger(isolate_);
2870
  if (debugger.FailedToEnter()) return;
2871

    
2872
  // If debugging there might be script break points registered for this
2873
  // script. Make sure that these break points are set.
2874

    
2875
  // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js).
2876
  Handle<String> update_script_break_points_string =
2877
      isolate_->factory()->InternalizeOneByteString(
2878
          STATIC_ASCII_VECTOR("UpdateScriptBreakPoints"));
2879
  Handle<Object> update_script_break_points =
2880
      Handle<Object>(
2881
          debug->debug_context()->global_object()->GetPropertyNoExceptionThrown(
2882
              *update_script_break_points_string),
2883
          isolate_);
2884
  if (!update_script_break_points->IsJSFunction()) {
2885
    return;
2886
  }
2887
  ASSERT(update_script_break_points->IsJSFunction());
2888

    
2889
  // Wrap the script object in a proper JS object before passing it
2890
  // to JavaScript.
2891
  Handle<JSValue> wrapper = GetScriptWrapper(script);
2892

    
2893
  // Call UpdateScriptBreakPoints expect no exceptions.
2894
  bool caught_exception;
2895
  Handle<Object> argv[] = { wrapper };
2896
  Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
2897
                     isolate_->js_builtins_object(),
2898
                     ARRAY_SIZE(argv),
2899
                     argv,
2900
                     &caught_exception);
2901
  if (caught_exception) {
2902
    return;
2903
  }
2904
  // Bail out based on state or if there is no listener for this event
2905
  if (in_debugger && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return;
2906
  if (!Debugger::EventActive(v8::AfterCompile)) return;
2907

    
2908
  // Create the compile state object.
2909
  Handle<Object> event_data = MakeCompileEvent(script,
2910
                                               false,
2911
                                               &caught_exception);
2912
  // Bail out and don't call debugger if exception.
2913
  if (caught_exception) {
2914
    return;
2915
  }
2916
  // Process debug event.
2917
  ProcessDebugEvent(v8::AfterCompile,
2918
                    Handle<JSObject>::cast(event_data),
2919
                    true);
2920
}
2921

    
2922

    
2923
void Debugger::OnScriptCollected(int id) {
2924
  HandleScope scope(isolate_);
2925

    
2926
  // No more to do if not debugging.
2927
  if (isolate_->debug()->InDebugger()) return;
2928
  if (!IsDebuggerActive()) return;
2929
  if (!Debugger::EventActive(v8::ScriptCollected)) return;
2930

    
2931
  // Enter the debugger.
2932
  EnterDebugger debugger(isolate_);
2933
  if (debugger.FailedToEnter()) return;
2934

    
2935
  // Create the script collected state object.
2936
  bool caught_exception = false;
2937
  Handle<Object> event_data = MakeScriptCollectedEvent(id,
2938
                                                       &caught_exception);
2939
  // Bail out and don't call debugger if exception.
2940
  if (caught_exception) {
2941
    return;
2942
  }
2943

    
2944
  // Process debug event.
2945
  ProcessDebugEvent(v8::ScriptCollected,
2946
                    Handle<JSObject>::cast(event_data),
2947
                    true);
2948
}
2949

    
2950

    
2951
void Debugger::ProcessDebugEvent(v8::DebugEvent event,
2952
                                 Handle<JSObject> event_data,
2953
                                 bool auto_continue) {
2954
  HandleScope scope(isolate_);
2955

    
2956
  // Clear any pending debug break if this is a real break.
2957
  if (!auto_continue) {
2958
    isolate_->debug()->clear_interrupt_pending(DEBUGBREAK);
2959
  }
2960

    
2961
  // Create the execution state.
2962
  bool caught_exception = false;
2963
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2964
  if (caught_exception) {
2965
    return;
2966
  }
2967
  // First notify the message handler if any.
2968
  if (message_handler_ != NULL) {
2969
    NotifyMessageHandler(event,
2970
                         Handle<JSObject>::cast(exec_state),
2971
                         event_data,
2972
                         auto_continue);
2973
  }
2974
  // Notify registered debug event listener. This can be either a C or
2975
  // a JavaScript function. Don't call event listener for v8::Break
2976
  // here, if it's only a debug command -- they will be processed later.
2977
  if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
2978
    CallEventCallback(event, exec_state, event_data, NULL);
2979
  }
2980
  // Process pending debug commands.
2981
  if (event == v8::Break) {
2982
    while (!event_command_queue_.IsEmpty()) {
2983
      CommandMessage command = event_command_queue_.Get();
2984
      if (!event_listener_.is_null()) {
2985
        CallEventCallback(v8::BreakForCommand,
2986
                          exec_state,
2987
                          event_data,
2988
                          command.client_data());
2989
      }
2990
      command.Dispose();
2991
    }
2992
  }
2993
}
2994

    
2995

    
2996
void Debugger::CallEventCallback(v8::DebugEvent event,
2997
                                 Handle<Object> exec_state,
2998
                                 Handle<Object> event_data,
2999
                                 v8::Debug::ClientData* client_data) {
3000
  if (event_listener_->IsForeign()) {
3001
    CallCEventCallback(event, exec_state, event_data, client_data);
3002
  } else {
3003
    CallJSEventCallback(event, exec_state, event_data);
3004
  }
3005
}
3006

    
3007

    
3008
void Debugger::CallCEventCallback(v8::DebugEvent event,
3009
                                  Handle<Object> exec_state,
3010
                                  Handle<Object> event_data,
3011
                                  v8::Debug::ClientData* client_data) {
3012
  Handle<Foreign> callback_obj(Handle<Foreign>::cast(event_listener_));
3013
  v8::Debug::EventCallback2 callback =
3014
      FUNCTION_CAST<v8::Debug::EventCallback2>(
3015
          callback_obj->foreign_address());
3016
  EventDetailsImpl event_details(
3017
      event,
3018
      Handle<JSObject>::cast(exec_state),
3019
      Handle<JSObject>::cast(event_data),
3020
      event_listener_data_,
3021
      client_data);
3022
  callback(event_details);
3023
}
3024

    
3025

    
3026
void Debugger::CallJSEventCallback(v8::DebugEvent event,
3027
                                   Handle<Object> exec_state,
3028
                                   Handle<Object> event_data) {
3029
  ASSERT(event_listener_->IsJSFunction());
3030
  Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
3031

    
3032
  // Invoke the JavaScript debug event listener.
3033
  Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
3034
                            exec_state,
3035
                            event_data,
3036
                            event_listener_data_ };
3037
  bool caught_exception;
3038
  Execution::TryCall(fun,
3039
                     isolate_->global_object(),
3040
                     ARRAY_SIZE(argv),
3041
                     argv,
3042
                     &caught_exception);
3043
  // Silently ignore exceptions from debug event listeners.
3044
}
3045

    
3046

    
3047
Handle<Context> Debugger::GetDebugContext() {
3048
  never_unload_debugger_ = true;
3049
  EnterDebugger debugger(isolate_);
3050
  return isolate_->debug()->debug_context();
3051
}
3052

    
3053

    
3054
void Debugger::UnloadDebugger() {
3055
  Debug* debug = isolate_->debug();
3056

    
3057
  // Make sure that there are no breakpoints left.
3058
  debug->ClearAllBreakPoints();
3059

    
3060
  // Unload the debugger if feasible.
3061
  if (!never_unload_debugger_) {
3062
    debug->Unload();
3063
  }
3064

    
3065
  // Clear the flag indicating that the debugger should be unloaded.
3066
  debugger_unload_pending_ = false;
3067
}
3068

    
3069

    
3070
void Debugger::NotifyMessageHandler(v8::DebugEvent event,
3071
                                    Handle<JSObject> exec_state,
3072
                                    Handle<JSObject> event_data,
3073
                                    bool auto_continue) {
3074
  HandleScope scope(isolate_);
3075

    
3076
  if (!isolate_->debug()->Load()) return;
3077

    
3078
  // Process the individual events.
3079
  bool sendEventMessage = false;
3080
  switch (event) {
3081
    case v8::Break:
3082
    case v8::BreakForCommand:
3083
      sendEventMessage = !auto_continue;
3084
      break;
3085
    case v8::Exception:
3086
      sendEventMessage = true;
3087
      break;
3088
    case v8::BeforeCompile:
3089
      break;
3090
    case v8::AfterCompile:
3091
      sendEventMessage = true;
3092
      break;
3093
    case v8::ScriptCollected:
3094
      sendEventMessage = true;
3095
      break;
3096
    case v8::NewFunction:
3097
      break;
3098
    default:
3099
      UNREACHABLE();
3100
  }
3101

    
3102
  // The debug command interrupt flag might have been set when the command was
3103
  // added. It should be enough to clear the flag only once while we are in the
3104
  // debugger.
3105
  ASSERT(isolate_->debug()->InDebugger());
3106
  isolate_->stack_guard()->Continue(DEBUGCOMMAND);
3107

    
3108
  // Notify the debugger that a debug event has occurred unless auto continue is
3109
  // active in which case no event is send.
3110
  if (sendEventMessage) {
3111
    MessageImpl message = MessageImpl::NewEvent(
3112
        event,
3113
        auto_continue,
3114
        Handle<JSObject>::cast(exec_state),
3115
        Handle<JSObject>::cast(event_data));
3116
    InvokeMessageHandler(message);
3117
  }
3118

    
3119
  // If auto continue don't make the event cause a break, but process messages
3120
  // in the queue if any. For script collected events don't even process
3121
  // messages in the queue as the execution state might not be what is expected
3122
  // by the client.
3123
  if ((auto_continue && !HasCommands()) || event == v8::ScriptCollected) {
3124
    return;
3125
  }
3126

    
3127
  v8::TryCatch try_catch;
3128

    
3129
  // DebugCommandProcessor goes here.
3130
  v8::Local<v8::Object> cmd_processor;
3131
  {
3132
    v8::Local<v8::Object> api_exec_state =
3133
        v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
3134
    v8::Local<v8::String> fun_name =
3135
        v8::String::New("debugCommandProcessor");
3136
    v8::Local<v8::Function> fun =
3137
        v8::Local<v8::Function>::Cast(api_exec_state->Get(fun_name));
3138

    
3139
    v8::Handle<v8::Boolean> running = v8::Boolean::New(auto_continue);
3140
    static const int kArgc = 1;
3141
    v8::Handle<Value> argv[kArgc] = { running };
3142
    cmd_processor = v8::Local<v8::Object>::Cast(
3143
        fun->Call(api_exec_state, kArgc, argv));
3144
    if (try_catch.HasCaught()) {
3145
      PrintLn(try_catch.Exception());
3146
      return;
3147
    }
3148
  }
3149

    
3150
  bool running = auto_continue;
3151

    
3152
  // Process requests from the debugger.
3153
  while (true) {
3154
    // Wait for new command in the queue.
3155
    if (Debugger::host_dispatch_handler_) {
3156
      // In case there is a host dispatch - do periodic dispatches.
3157
      if (!command_received_.WaitFor(host_dispatch_period_)) {
3158
        // Timout expired, do the dispatch.
3159
        Debugger::host_dispatch_handler_();
3160
        continue;
3161
      }
3162
    } else {
3163
      // In case there is no host dispatch - just wait.
3164
      command_received_.Wait();
3165
    }
3166

    
3167
    // Get the command from the queue.
3168
    CommandMessage command = command_queue_.Get();
3169
    isolate_->logger()->DebugTag(
3170
        "Got request from command queue, in interactive loop.");
3171
    if (!Debugger::IsDebuggerActive()) {
3172
      // Delete command text and user data.
3173
      command.Dispose();
3174
      return;
3175
    }
3176

    
3177
    // Invoke JavaScript to process the debug request.
3178
    v8::Local<v8::String> fun_name;
3179
    v8::Local<v8::Function> fun;
3180
    v8::Local<v8::Value> request;
3181
    v8::TryCatch try_catch;
3182
    fun_name = v8::String::New("processDebugRequest");
3183
    fun = v8::Local<v8::Function>::Cast(cmd_processor->Get(fun_name));
3184

    
3185
    request = v8::String::New(command.text().start(),
3186
                              command.text().length());
3187
    static const int kArgc = 1;
3188
    v8::Handle<Value> argv[kArgc] = { request };
3189
    v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
3190

    
3191
    // Get the response.
3192
    v8::Local<v8::String> response;
3193
    if (!try_catch.HasCaught()) {
3194
      // Get response string.
3195
      if (!response_val->IsUndefined()) {
3196
        response = v8::Local<v8::String>::Cast(response_val);
3197
      } else {
3198
        response = v8::String::New("");
3199
      }
3200

    
3201
      // Log the JSON request/response.
3202
      if (FLAG_trace_debug_json) {
3203
        PrintLn(request);
3204
        PrintLn(response);
3205
      }
3206

    
3207
      // Get the running state.
3208
      fun_name = v8::String::New("isRunning");
3209
      fun = v8::Local<v8::Function>::Cast(cmd_processor->Get(fun_name));
3210
      static const int kArgc = 1;
3211
      v8::Handle<Value> argv[kArgc] = { response };
3212
      v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv);
3213
      if (!try_catch.HasCaught()) {
3214
        running = running_val->ToBoolean()->Value();
3215
      }
3216
    } else {
3217
      // In case of failure the result text is the exception text.
3218
      response = try_catch.Exception()->ToString();
3219
    }
3220

    
3221
    // Return the result.
3222
    MessageImpl message = MessageImpl::NewResponse(
3223
        event,
3224
        running,
3225
        Handle<JSObject>::cast(exec_state),
3226
        Handle<JSObject>::cast(event_data),
3227
        Handle<String>(Utils::OpenHandle(*response)),
3228
        command.client_data());
3229
    InvokeMessageHandler(message);
3230
    command.Dispose();
3231

    
3232
    // Return from debug event processing if either the VM is put into the
3233
    // running state (through a continue command) or auto continue is active
3234
    // and there are no more commands queued.
3235
    if (running && !HasCommands()) {
3236
      return;
3237
    }
3238
  }
3239
}
3240

    
3241

    
3242
void Debugger::SetEventListener(Handle<Object> callback,
3243
                                Handle<Object> data) {
3244
  HandleScope scope(isolate_);
3245
  GlobalHandles* global_handles = isolate_->global_handles();
3246

    
3247
  // Clear the global handles for the event listener and the event listener data
3248
  // object.
3249
  if (!event_listener_.is_null()) {
3250
    global_handles->Destroy(
3251
        reinterpret_cast<Object**>(event_listener_.location()));
3252
    event_listener_ = Handle<Object>();
3253
  }
3254
  if (!event_listener_data_.is_null()) {
3255
    global_handles->Destroy(
3256
        reinterpret_cast<Object**>(event_listener_data_.location()));
3257
    event_listener_data_ = Handle<Object>();
3258
  }
3259

    
3260
  // If there is a new debug event listener register it together with its data
3261
  // object.
3262
  if (!callback->IsUndefined() && !callback->IsNull()) {
3263
    event_listener_ = Handle<Object>::cast(
3264
        global_handles->Create(*callback));
3265
    if (data.is_null()) {
3266
      data = isolate_->factory()->undefined_value();
3267
    }
3268
    event_listener_data_ = Handle<Object>::cast(
3269
        global_handles->Create(*data));
3270
  }
3271

    
3272
  ListenersChanged();
3273
}
3274

    
3275

    
3276
void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
3277
  LockGuard<RecursiveMutex> with(debugger_access_);
3278

    
3279
  message_handler_ = handler;
3280
  ListenersChanged();
3281
  if (handler == NULL) {
3282
    // Send an empty command to the debugger if in a break to make JavaScript
3283
    // run again if the debugger is closed.
3284
    if (isolate_->debug()->InDebugger()) {
3285
      ProcessCommand(Vector<const uint16_t>::empty());
3286
    }
3287
  }
3288
}
3289

    
3290

    
3291
void Debugger::ListenersChanged() {
3292
  if (IsDebuggerActive()) {
3293
    // Disable the compilation cache when the debugger is active.
3294
    isolate_->compilation_cache()->Disable();
3295
    debugger_unload_pending_ = false;
3296
  } else {
3297
    isolate_->compilation_cache()->Enable();
3298
    // Unload the debugger if event listener and message handler cleared.
3299
    // Schedule this for later, because we may be in non-V8 thread.
3300
    debugger_unload_pending_ = true;
3301
  }
3302
}
3303

    
3304

    
3305
void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
3306
                                      TimeDelta period) {
3307
  host_dispatch_handler_ = handler;
3308
  host_dispatch_period_ = period;
3309
}
3310

    
3311

    
3312
void Debugger::SetDebugMessageDispatchHandler(
3313
    v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) {
3314
  LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3315
  debug_message_dispatch_handler_ = handler;
3316

    
3317
  if (provide_locker && message_dispatch_helper_thread_ == NULL) {
3318
    message_dispatch_helper_thread_ = new MessageDispatchHelperThread(isolate_);
3319
    message_dispatch_helper_thread_->Start();
3320
  }
3321
}
3322

    
3323

    
3324
// Calls the registered debug message handler. This callback is part of the
3325
// public API.
3326
void Debugger::InvokeMessageHandler(MessageImpl message) {
3327
  LockGuard<RecursiveMutex> with(debugger_access_);
3328

    
3329
  if (message_handler_ != NULL) {
3330
    message_handler_(message);
3331
  }
3332
}
3333

    
3334

    
3335
// Puts a command coming from the public API on the queue.  Creates
3336
// a copy of the command string managed by the debugger.  Up to this
3337
// point, the command data was managed by the API client.  Called
3338
// by the API client thread.
3339
void Debugger::ProcessCommand(Vector<const uint16_t> command,
3340
                              v8::Debug::ClientData* client_data) {
3341
  // Need to cast away const.
3342
  CommandMessage message = CommandMessage::New(
3343
      Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
3344
                       command.length()),
3345
      client_data);
3346
  isolate_->logger()->DebugTag("Put command on command_queue.");
3347
  command_queue_.Put(message);
3348
  command_received_.Signal();
3349

    
3350
  // Set the debug command break flag to have the command processed.
3351
  if (!isolate_->debug()->InDebugger()) {
3352
    isolate_->stack_guard()->DebugCommand();
3353
  }
3354

    
3355
  MessageDispatchHelperThread* dispatch_thread;
3356
  {
3357
    LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3358
    dispatch_thread = message_dispatch_helper_thread_;
3359
  }
3360

    
3361
  if (dispatch_thread == NULL) {
3362
    CallMessageDispatchHandler();
3363
  } else {
3364
    dispatch_thread->Schedule();
3365
  }
3366
}
3367

    
3368

    
3369
bool Debugger::HasCommands() {
3370
  return !command_queue_.IsEmpty();
3371
}
3372

    
3373

    
3374
void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
3375
  CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
3376
  event_command_queue_.Put(message);
3377

    
3378
  // Set the debug command break flag to have the command processed.
3379
  if (!isolate_->debug()->InDebugger()) {
3380
    isolate_->stack_guard()->DebugCommand();
3381
  }
3382
}
3383

    
3384

    
3385
bool Debugger::IsDebuggerActive() {
3386
  LockGuard<RecursiveMutex> with(debugger_access_);
3387

    
3388
  return message_handler_ != NULL ||
3389
      !event_listener_.is_null() ||
3390
      force_debugger_active_;
3391
}
3392

    
3393

    
3394
Handle<Object> Debugger::Call(Handle<JSFunction> fun,
3395
                              Handle<Object> data,
3396
                              bool* pending_exception) {
3397
  // When calling functions in the debugger prevent it from beeing unloaded.
3398
  Debugger::never_unload_debugger_ = true;
3399

    
3400
  // Enter the debugger.
3401
  EnterDebugger debugger(isolate_);
3402
  if (debugger.FailedToEnter()) {
3403
    return isolate_->factory()->undefined_value();
3404
  }
3405

    
3406
  // Create the execution state.
3407
  bool caught_exception = false;
3408
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
3409
  if (caught_exception) {
3410
    return isolate_->factory()->undefined_value();
3411
  }
3412

    
3413
  Handle<Object> argv[] = { exec_state, data };
3414
  Handle<Object> result = Execution::Call(
3415
      isolate_,
3416
      fun,
3417
      Handle<Object>(isolate_->debug()->debug_context_->global_proxy(),
3418
                     isolate_),
3419
      ARRAY_SIZE(argv),
3420
      argv,
3421
      pending_exception);
3422
  return result;
3423
}
3424

    
3425

    
3426
static void StubMessageHandler2(const v8::Debug::Message& message) {
3427
  // Simply ignore message.
3428
}
3429

    
3430

    
3431
bool Debugger::StartAgent(const char* name, int port,
3432
                          bool wait_for_connection) {
3433
  if (wait_for_connection) {
3434
    // Suspend V8 if it is already running or set V8 to suspend whenever
3435
    // it starts.
3436
    // Provide stub message handler; V8 auto-continues each suspend
3437
    // when there is no message handler; we doesn't need it.
3438
    // Once become suspended, V8 will stay so indefinitely long, until remote
3439
    // debugger connects and issues "continue" command.
3440
    Debugger::message_handler_ = StubMessageHandler2;
3441
    v8::Debug::DebugBreak();
3442
  }
3443

    
3444
  if (agent_ == NULL) {
3445
    agent_ = new DebuggerAgent(isolate_, name, port);
3446
    agent_->Start();
3447
  }
3448
  return true;
3449
}
3450

    
3451

    
3452
void Debugger::StopAgent() {
3453
  if (agent_ != NULL) {
3454
    agent_->Shutdown();
3455
    agent_->Join();
3456
    delete agent_;
3457
    agent_ = NULL;
3458
  }
3459
}
3460

    
3461

    
3462
void Debugger::WaitForAgent() {
3463
  if (agent_ != NULL)
3464
    agent_->WaitUntilListening();
3465
}
3466

    
3467

    
3468
void Debugger::CallMessageDispatchHandler() {
3469
  v8::Debug::DebugMessageDispatchHandler handler;
3470
  {
3471
    LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3472
    handler = Debugger::debug_message_dispatch_handler_;
3473
  }
3474
  if (handler != NULL) {
3475
    handler();
3476
  }
3477
}
3478

    
3479

    
3480
EnterDebugger::EnterDebugger(Isolate* isolate)
3481
    : isolate_(isolate),
3482
      prev_(isolate_->debug()->debugger_entry()),
3483
      it_(isolate_),
3484
      has_js_frames_(!it_.done()),
3485
      save_(isolate_) {
3486
  Debug* debug = isolate_->debug();
3487
  ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT));
3488
  ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK));
3489

    
3490
  // Link recursive debugger entry.
3491
  debug->set_debugger_entry(this);
3492

    
3493
  // Store the previous break id and frame id.
3494
  break_id_ = debug->break_id();
3495
  break_frame_id_ = debug->break_frame_id();
3496

    
3497
  // Create the new break info. If there is no JavaScript frames there is no
3498
  // break frame id.
3499
  if (has_js_frames_) {
3500
    debug->NewBreak(it_.frame()->id());
3501
  } else {
3502
    debug->NewBreak(StackFrame::NO_ID);
3503
  }
3504

    
3505
  // Make sure that debugger is loaded and enter the debugger context.
3506
  load_failed_ = !debug->Load();
3507
  if (!load_failed_) {
3508
    // NOTE the member variable save which saves the previous context before
3509
    // this change.
3510
    isolate_->set_context(*debug->debug_context());
3511
  }
3512
}
3513

    
3514

    
3515
EnterDebugger::~EnterDebugger() {
3516
  Debug* debug = isolate_->debug();
3517

    
3518
  // Restore to the previous break state.
3519
  debug->SetBreak(break_frame_id_, break_id_);
3520

    
3521
  // Check for leaving the debugger.
3522
  if (!load_failed_ && prev_ == NULL) {
3523
    // Clear mirror cache when leaving the debugger. Skip this if there is a
3524
    // pending exception as clearing the mirror cache calls back into
3525
    // JavaScript. This can happen if the v8::Debug::Call is used in which
3526
    // case the exception should end up in the calling code.
3527
    if (!isolate_->has_pending_exception()) {
3528
      // Try to avoid any pending debug break breaking in the clear mirror
3529
      // cache JavaScript code.
3530
      if (isolate_->stack_guard()->IsDebugBreak()) {
3531
        debug->set_interrupts_pending(DEBUGBREAK);
3532
        isolate_->stack_guard()->Continue(DEBUGBREAK);
3533
      }
3534
      debug->ClearMirrorCache();
3535
    }
3536

    
3537
    // Request preemption and debug break when leaving the last debugger entry
3538
    // if any of these where recorded while debugging.
3539
    if (debug->is_interrupt_pending(PREEMPT)) {
3540
      // This re-scheduling of preemption is to avoid starvation in some
3541
      // debugging scenarios.
3542
      debug->clear_interrupt_pending(PREEMPT);
3543
      isolate_->stack_guard()->Preempt();
3544
    }
3545
    if (debug->is_interrupt_pending(DEBUGBREAK)) {
3546
      debug->clear_interrupt_pending(DEBUGBREAK);
3547
      isolate_->stack_guard()->DebugBreak();
3548
    }
3549

    
3550
    // If there are commands in the queue when leaving the debugger request
3551
    // that these commands are processed.
3552
    if (isolate_->debugger()->HasCommands()) {
3553
      isolate_->stack_guard()->DebugCommand();
3554
    }
3555

    
3556
    // If leaving the debugger with the debugger no longer active unload it.
3557
    if (!isolate_->debugger()->IsDebuggerActive()) {
3558
      isolate_->debugger()->UnloadDebugger();
3559
    }
3560
  }
3561

    
3562
  // Leaving this debugger entry.
3563
  debug->set_debugger_entry(prev_);
3564
}
3565

    
3566

    
3567
MessageImpl MessageImpl::NewEvent(DebugEvent event,
3568
                                  bool running,
3569
                                  Handle<JSObject> exec_state,
3570
                                  Handle<JSObject> event_data) {
3571
  MessageImpl message(true, event, running,
3572
                      exec_state, event_data, Handle<String>(), NULL);
3573
  return message;
3574
}
3575

    
3576

    
3577
MessageImpl MessageImpl::NewResponse(DebugEvent event,
3578
                                     bool running,
3579
                                     Handle<JSObject> exec_state,
3580
                                     Handle<JSObject> event_data,
3581
                                     Handle<String> response_json,
3582
                                     v8::Debug::ClientData* client_data) {
3583
  MessageImpl message(false, event, running,
3584
                      exec_state, event_data, response_json, client_data);
3585
  return message;
3586
}
3587

    
3588

    
3589
MessageImpl::MessageImpl(bool is_event,
3590
                         DebugEvent event,
3591
                         bool running,
3592
                         Handle<JSObject> exec_state,
3593
                         Handle<JSObject> event_data,
3594
                         Handle<String> response_json,
3595
                         v8::Debug::ClientData* client_data)
3596
    : is_event_(is_event),
3597
      event_(event),
3598
      running_(running),
3599
      exec_state_(exec_state),
3600
      event_data_(event_data),
3601
      response_json_(response_json),
3602
      client_data_(client_data) {}
3603

    
3604

    
3605
bool MessageImpl::IsEvent() const {
3606
  return is_event_;
3607
}
3608

    
3609

    
3610
bool MessageImpl::IsResponse() const {
3611
  return !is_event_;
3612
}
3613

    
3614

    
3615
DebugEvent MessageImpl::GetEvent() const {
3616
  return event_;
3617
}
3618

    
3619

    
3620
bool MessageImpl::WillStartRunning() const {
3621
  return running_;
3622
}
3623

    
3624

    
3625
v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
3626
  return v8::Utils::ToLocal(exec_state_);
3627
}
3628

    
3629

    
3630
v8::Isolate* MessageImpl::GetIsolate() const {
3631
  return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
3632
}
3633

    
3634

    
3635
v8::Handle<v8::Object> MessageImpl::GetEventData() const {
3636
  return v8::Utils::ToLocal(event_data_);
3637
}
3638

    
3639

    
3640
v8::Handle<v8::String> MessageImpl::GetJSON() const {
3641
  v8::HandleScope scope(
3642
      reinterpret_cast<v8::Isolate*>(event_data_->GetIsolate()));
3643

    
3644
  if (IsEvent()) {
3645
    // Call toJSONProtocol on the debug event object.
3646
    Handle<Object> fun = GetProperty(event_data_, "toJSONProtocol");
3647
    if (!fun->IsJSFunction()) {
3648
      return v8::Handle<v8::String>();
3649
    }
3650
    bool caught_exception;
3651
    Handle<Object> json = Execution::TryCall(Handle<JSFunction>::cast(fun),
3652
                                             event_data_,
3653
                                             0, NULL, &caught_exception);
3654
    if (caught_exception || !json->IsString()) {
3655
      return v8::Handle<v8::String>();
3656
    }
3657
    return scope.Close(v8::Utils::ToLocal(Handle<String>::cast(json)));
3658
  } else {
3659
    return v8::Utils::ToLocal(response_json_);
3660
  }
3661
}
3662

    
3663

    
3664
v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
3665
  Isolate* isolate = event_data_->GetIsolate();
3666
  v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
3667
  // Isolate::context() may be NULL when "script collected" event occures.
3668
  ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected);
3669
  return context;
3670
}
3671

    
3672

    
3673
v8::Debug::ClientData* MessageImpl::GetClientData() const {
3674
  return client_data_;
3675
}
3676

    
3677

    
3678
EventDetailsImpl::EventDetailsImpl(DebugEvent event,
3679
                                   Handle<JSObject> exec_state,
3680
                                   Handle<JSObject> event_data,
3681
                                   Handle<Object> callback_data,
3682
                                   v8::Debug::ClientData* client_data)
3683
    : event_(event),
3684
      exec_state_(exec_state),
3685
      event_data_(event_data),
3686
      callback_data_(callback_data),
3687
      client_data_(client_data) {}
3688

    
3689

    
3690
DebugEvent EventDetailsImpl::GetEvent() const {
3691
  return event_;
3692
}
3693

    
3694

    
3695
v8::Handle<v8::Object> EventDetailsImpl::GetExecutionState() const {
3696
  return v8::Utils::ToLocal(exec_state_);
3697
}
3698

    
3699

    
3700
v8::Handle<v8::Object> EventDetailsImpl::GetEventData() const {
3701
  return v8::Utils::ToLocal(event_data_);
3702
}
3703

    
3704

    
3705
v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const {
3706
  return GetDebugEventContext(exec_state_->GetIsolate());
3707
}
3708

    
3709

    
3710
v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const {
3711
  return v8::Utils::ToLocal(callback_data_);
3712
}
3713

    
3714

    
3715
v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
3716
  return client_data_;
3717
}
3718

    
3719

    
3720
CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
3721
                                   client_data_(NULL) {
3722
}
3723

    
3724

    
3725
CommandMessage::CommandMessage(const Vector<uint16_t>& text,
3726
                               v8::Debug::ClientData* data)
3727
    : text_(text),
3728
      client_data_(data) {
3729
}
3730

    
3731

    
3732
CommandMessage::~CommandMessage() {
3733
}
3734

    
3735

    
3736
void CommandMessage::Dispose() {
3737
  text_.Dispose();
3738
  delete client_data_;
3739
  client_data_ = NULL;
3740
}
3741

    
3742

    
3743
CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
3744
                                   v8::Debug::ClientData* data) {
3745
  return CommandMessage(command.Clone(), data);
3746
}
3747

    
3748

    
3749
CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
3750
                                                     size_(size) {
3751
  messages_ = NewArray<CommandMessage>(size);
3752
}
3753

    
3754

    
3755
CommandMessageQueue::~CommandMessageQueue() {
3756
  while (!IsEmpty()) {
3757
    CommandMessage m = Get();
3758
    m.Dispose();
3759
  }
3760
  DeleteArray(messages_);
3761
}
3762

    
3763

    
3764
CommandMessage CommandMessageQueue::Get() {
3765
  ASSERT(!IsEmpty());
3766
  int result = start_;
3767
  start_ = (start_ + 1) % size_;
3768
  return messages_[result];
3769
}
3770

    
3771

    
3772
void CommandMessageQueue::Put(const CommandMessage& message) {
3773
  if ((end_ + 1) % size_ == start_) {
3774
    Expand();
3775
  }
3776
  messages_[end_] = message;
3777
  end_ = (end_ + 1) % size_;
3778
}
3779

    
3780

    
3781
void CommandMessageQueue::Expand() {
3782
  CommandMessageQueue new_queue(size_ * 2);
3783
  while (!IsEmpty()) {
3784
    new_queue.Put(Get());
3785
  }
3786
  CommandMessage* array_to_free = messages_;
3787
  *this = new_queue;
3788
  new_queue.messages_ = array_to_free;
3789
  // Make the new_queue empty so that it doesn't call Dispose on any messages.
3790
  new_queue.start_ = new_queue.end_;
3791
  // Automatic destructor called on new_queue, freeing array_to_free.
3792
}
3793

    
3794

    
3795
LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
3796
    : logger_(logger), queue_(size) {}
3797

    
3798

    
3799
bool LockingCommandMessageQueue::IsEmpty() const {
3800
  LockGuard<Mutex> lock_guard(&mutex_);
3801
  return queue_.IsEmpty();
3802
}
3803

    
3804

    
3805
CommandMessage LockingCommandMessageQueue::Get() {
3806
  LockGuard<Mutex> lock_guard(&mutex_);
3807
  CommandMessage result = queue_.Get();
3808
  logger_->DebugEvent("Get", result.text());
3809
  return result;
3810
}
3811

    
3812

    
3813
void LockingCommandMessageQueue::Put(const CommandMessage& message) {
3814
  LockGuard<Mutex> lock_guard(&mutex_);
3815
  queue_.Put(message);
3816
  logger_->DebugEvent("Put", message.text());
3817
}
3818

    
3819

    
3820
void LockingCommandMessageQueue::Clear() {
3821
  LockGuard<Mutex> lock_guard(&mutex_);
3822
  queue_.Clear();
3823
}
3824

    
3825

    
3826
MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
3827
    : Thread("v8:MsgDispHelpr"),
3828
      isolate_(isolate), sem_(0),
3829
      already_signalled_(false) {
3830
}
3831

    
3832

    
3833
void MessageDispatchHelperThread::Schedule() {
3834
  {
3835
    LockGuard<Mutex> lock_guard(&mutex_);
3836
    if (already_signalled_) {
3837
      return;
3838
    }
3839
    already_signalled_ = true;
3840
  }
3841
  sem_.Signal();
3842
}
3843

    
3844

    
3845
void MessageDispatchHelperThread::Run() {
3846
  while (true) {
3847
    sem_.Wait();
3848
    {
3849
      LockGuard<Mutex> lock_guard(&mutex_);
3850
      already_signalled_ = false;
3851
    }
3852
    {
3853
      Locker locker(reinterpret_cast<v8::Isolate*>(isolate_));
3854
      isolate_->debugger()->CallMessageDispatchHandler();
3855
    }
3856
  }
3857
}
3858

    
3859
#endif  // ENABLE_DEBUGGER_SUPPORT
3860

    
3861
} }  // namespace v8::internal