debug.cc 87.1 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5 6
#include "src/debug/debug.h"

7 8 9 10 11 12 13 14 15
#include "src/api.h"
#include "src/arguments.h"
#include "src/bootstrapper.h"
#include "src/code-stubs.h"
#include "src/codegen.h"
#include "src/compilation-cache.h"
#include "src/compiler.h"
#include "src/deoptimizer.h"
#include "src/execution.h"
16
#include "src/frames-inl.h"
17
#include "src/full-codegen/full-codegen.h"
18 19
#include "src/global-handles.h"
#include "src/list.h"
20
#include "src/log.h"
21
#include "src/messages.h"
22
#include "src/snapshot/natives.h"
23

24
#include "include/v8-debug.h"
25

26 27
namespace v8 {
namespace internal {
28

29
Debug::Debug(Isolate* isolate)
30 31 32 33 34 35 36
    : debug_context_(Handle<Context>()),
      event_listener_(Handle<Object>()),
      event_listener_data_(Handle<Object>()),
      message_handler_(NULL),
      command_received_(0),
      command_queue_(isolate->logger(), kQueueInitialSize),
      is_active_(false),
37
      is_suppressed_(false),
38
      live_edit_enabled_(true),  // TODO(yangguo): set to false by default.
39
      break_disabled_(false),
40
      in_debug_event_listener_(false),
41 42
      break_on_exception_(false),
      break_on_uncaught_exception_(false),
43
      debug_info_list_(NULL),
44
      isolate_(isolate) {
45
  ThreadInit();
46 47 48
}


49
static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
50 51 52 53
  Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
  // Isolate::context() may have been NULL when "script collected" event
  // occured.
  if (context.is_null()) return v8::Local<v8::Context>();
54 55
  Handle<Context> native_context(context->native_context());
  return v8::Utils::ToLocal(native_context);
56 57 58
}


59
BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo,
60
                             int position, int statement_position)
61 62 63 64 65
    : debug_info_(debug_info),
      pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())),
      rmode_(rinfo->rmode()),
      data_(rinfo->data()),
      position_(position),
66
      statement_position_(statement_position) {}
67 68


69 70 71
BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
                                  BreakLocatorType type)
    : debug_info_(debug_info),
72
      reloc_iterator_(debug_info->code(), GetModeMask(type)),
73 74
      break_index_(-1),
      position_(1),
75
      statement_position_(1) {
76
  if (!Done()) Next();
77 78 79 80 81 82 83
}


int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) {
  int mask = 0;
  mask |= RelocInfo::ModeMask(RelocInfo::POSITION);
  mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION);
84
  mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
85 86 87 88 89 90 91
  mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
  mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CONSTRUCT_CALL);
  if (type == ALL_BREAK_LOCATIONS) {
    mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
    mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT);
  }
  return mask;
92 93 94
}


95
void BreakLocation::Iterator::Next() {
96
  DisallowHeapAllocation no_gc;
97
  DCHECK(!Done());
98 99 100

  // Iterate through reloc info for code and original code stopping at each
  // breakable code target.
101
  bool first = break_index_ == -1;
102 103
  while (!Done()) {
    if (!first) reloc_iterator_.next();
104
    first = false;
105
    if (Done()) return;
106

107 108
    // Whenever a statement position or (plain) position is passed update the
    // current value of these.
109 110
    if (RelocInfo::IsPosition(rmode())) {
      if (RelocInfo::IsStatementPosition(rmode())) {
111 112
        statement_position_ = static_cast<int>(
            rinfo()->data() - debug_info_->shared()->start_position());
113
      }
114 115
      // Always update the position as we don't want that to be before the
      // statement position.
116 117
      position_ = static_cast<int>(rinfo()->data() -
                                   debug_info_->shared()->start_position());
118 119
      DCHECK(position_ >= 0);
      DCHECK(statement_position_ >= 0);
120
      continue;
121 122
    }

123 124 125 126
    DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) ||
           RelocInfo::IsDebuggerStatement(rmode()));

    if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
127 128 129 130 131 132 133 134 135 136
      // Set the positions to the end of the function.
      if (debug_info_->shared()->HasSourceCode()) {
        position_ = debug_info_->shared()->end_position() -
                    debug_info_->shared()->start_position() - 1;
      } else {
        position_ = 0;
      }
      statement_position_ = position_;
    }

137
    break;
138
  }
139
  break_index_++;
140 141 142
}


143 144 145 146 147 148 149
// Find the break point at the supplied address, or the closest one before
// the address.
BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info,
                                         BreakLocatorType type, Address pc) {
  Iterator it(debug_info, type);
  it.SkipTo(BreakIndexFromAddress(debug_info, type, pc));
  return it.GetBreakLocation();
150 151 152
}


153 154
// Find the break point at the supplied address, or the closest one before
// the address.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info,
                                             BreakLocatorType type, Address pc,
                                             List<BreakLocation>* result_out) {
  int break_index = BreakIndexFromAddress(debug_info, type, pc);
  Iterator it(debug_info, type);
  it.SkipTo(break_index);
  int statement_position = it.statement_position();
  while (!it.Done() && it.statement_position() == statement_position) {
    result_out->Add(it.GetBreakLocation());
    it.Next();
  }
}


int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info,
                                         BreakLocatorType type, Address pc) {
171
  // Run through all break points to locate the one closest to the address.
172
  int closest_break = 0;
173
  int distance = kMaxInt;
174
  for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
175
    // Check if this break point is closer that what was previously found.
176 177 178
    if (it.pc() <= pc && pc - it.pc() < distance) {
      closest_break = it.break_index();
      distance = static_cast<int>(pc - it.pc());
179 180 181 182
      // Check whether we can't get any closer.
      if (distance == 0) break;
    }
  }
183
  return closest_break;
184 185 186
}


187 188 189
BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
                                          BreakLocatorType type, int position,
                                          BreakPositionAlignment alignment) {
190 191
  // Run through all break points to locate the one closest to the source
  // position.
192
  int closest_break = 0;
193
  int distance = kMaxInt;
194

195
  for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
196
    int next_position;
197 198 199 200 201
    if (alignment == STATEMENT_ALIGNED) {
      next_position = it.statement_position();
    } else {
      DCHECK(alignment == BREAK_POSITION_ALIGNED);
      next_position = it.position();
202 203
    }
    if (position <= next_position && next_position - position < distance) {
204
      closest_break = it.break_index();
205
      distance = next_position - position;
206 207 208 209 210
      // Check whether we can't get any closer.
      if (distance == 0) break;
    }
  }

211 212 213
  Iterator it(debug_info, type);
  it.SkipTo(closest_break);
  return it.GetBreakLocation();
214 215 216
}


217
void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) {
218 219
  // If there is not already a real break point here patch code with debug
  // break.
220
  if (!HasBreakPoint()) SetDebugBreak();
221
  DCHECK(IsDebugBreak() || IsDebuggerStatement());
222
  // Set the break point information.
223 224
  DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_,
                           statement_position_, break_point_object);
225 226 227
}


228
void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
229
  // Clear the break point information.
230
  DebugInfo::ClearBreakPoint(debug_info_, pc_offset_, break_point_object);
231 232 233
  // If there are no more break points here remove the debug break.
  if (!HasBreakPoint()) {
    ClearDebugBreak();
234
    DCHECK(!IsDebugBreak());
235 236 237 238
  }
}


239
void BreakLocation::SetOneShot() {
240
  // Debugger statement always calls debugger. No need to modify it.
241
  if (IsDebuggerStatement()) return;
242

243 244
  // If there is a real break point here no more to do.
  if (HasBreakPoint()) {
245
    DCHECK(IsDebugBreak());
246 247 248 249 250 251 252 253
    return;
  }

  // Patch code with debug break.
  SetDebugBreak();
}


254
void BreakLocation::ClearOneShot() {
255
  // Debugger statement always calls debugger. No need to modify it.
256
  if (IsDebuggerStatement()) return;
257

258 259
  // If there is a real break point here no more to do.
  if (HasBreakPoint()) {
260
    DCHECK(IsDebugBreak());
261 262 263 264 265
    return;
  }

  // Patch code removing debug break.
  ClearDebugBreak();
266
  DCHECK(!IsDebugBreak());
267 268 269
}


270
void BreakLocation::SetDebugBreak() {
271
  // Debugger statement always calls debugger. No need to modify it.
272
  if (IsDebuggerStatement()) return;
273

274
  // If there is already a break point here just return. This might happen if
275
  // the same code is flooded with break points twice. Flooding the same
276 277
  // function twice might happen when stepping in a function with an exception
  // handler as the handler and the function is the same.
278
  if (IsDebugBreak()) return;
279

280 281 282 283 284
  DCHECK(IsDebugBreakSlot());
  Builtins* builtins = debug_info_->GetIsolate()->builtins();
  Handle<Code> target =
      IsReturn() ? builtins->Return_DebugBreak() : builtins->Slot_DebugBreak();
  DebugCodegen::PatchDebugBreakSlot(pc(), target);
285
  DCHECK(IsDebugBreak());
286 287 288
}


289
void BreakLocation::ClearDebugBreak() {
290
  // Debugger statement always calls debugger. No need to modify it.
291
  if (IsDebuggerStatement()) return;
292

293 294
  DCHECK(IsDebugBreakSlot());
  DebugCodegen::ClearDebugBreakSlot(pc());
295
  DCHECK(!IsDebugBreak());
296 297 298
}


299
bool BreakLocation::IsStepInLocation() const {
300
  return IsConstructCall() || IsCall();
301 302 303
}


304
bool BreakLocation::IsDebugBreak() const {
305
  if (IsDebugBreakSlot()) {
306
    return rinfo().IsPatchedDebugBreakSlotSequence();
307
  }
308
  return false;
309 310 311
}


312 313
Handle<Object> BreakLocation::BreakPointObjects() const {
  return debug_info_->GetBreakPointObjects(pc_offset_);
314 315 316
}


317 318
// Threading support.
void Debug::ThreadInit() {
319 320 321
  thread_local_.break_count_ = 0;
  thread_local_.break_id_ = 0;
  thread_local_.break_frame_id_ = StackFrame::NO_ID;
322
  thread_local_.last_step_action_ = StepNone;
323
  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
324 325
  thread_local_.step_count_ = 0;
  thread_local_.last_fp_ = 0;
326
  thread_local_.queued_step_count_ = 0;
327
  thread_local_.step_into_fp_ = 0;
328
  thread_local_.step_out_fp_ = 0;
329
  // TODO(isolates): frames_are_dropped_?
330
  base::NoBarrier_Store(&thread_local_.current_debug_scope_,
331
                        static_cast<base::AtomicWord>(0));
332
  thread_local_.restarter_frame_function_pointer_ = NULL;
333 334 335 336 337
}


char* Debug::ArchiveDebug(char* storage) {
  char* to = storage;
338
  MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
339 340 341 342 343 344 345
  ThreadInit();
  return storage + ArchiveSpacePerThread();
}


char* Debug::RestoreDebug(char* storage) {
  char* from = storage;
346
  MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
347 348 349 350 351
  return storage + ArchiveSpacePerThread();
}


int Debug::ArchiveSpacePerThread() {
352
  return sizeof(ThreadLocal);
353 354 355
}


356 357
DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
  // Globalize the request debug info object and make it weak.
358
  GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
dcarney's avatar
dcarney committed
359 360
  debug_info_ =
      Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location();
361 362 363
}


364
DebugInfoListNode::~DebugInfoListNode() {
dcarney's avatar
dcarney committed
365 366 367
  if (debug_info_ == nullptr) return;
  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_));
  debug_info_ = nullptr;
368 369 370
}


371 372
bool Debug::Load() {
  // Return if debugger is already loaded.
373
  if (is_loaded()) return true;
374

375 376
  // Bail out if we're already in the process of compiling the native
  // JavaScript source code for the debugger.
377 378
  if (is_suppressed_) return false;
  SuppressDebug while_loading(this);
379 380 381

  // Disable breakpoints and interrupts while compiling and running the
  // debugger scripts including the context creation code.
382
  DisableBreak disable(this, true);
383
  PostponeInterruptsScope postpone(isolate_);
384

385
  // Create the debugger context.
386
  HandleScope scope(isolate_);
387
  ExtensionConfiguration no_extensions;
388
  Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
389 390
      MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
      DEBUG_CONTEXT);
391

392 393 394
  // Fail if no context could be created.
  if (context.is_null()) return false;

395 396
  debug_context_ = Handle<Context>::cast(
      isolate_->global_handles()->Create(*context));
397 398 399 400 401
  return true;
}


void Debug::Unload() {
402
  ClearAllBreakPoints();
403
  ClearStepping();
404

405
  // Return debugger is not loaded.
406
  if (!is_loaded()) return;
407 408

  // Clear debugger context global handle.
409
  GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
410 411 412 413
  debug_context_ = Handle<Context>();
}


414
void Debug::Break(Arguments args, JavaScriptFrame* frame) {
415 416
  Heap* heap = isolate_->heap();
  HandleScope scope(isolate_);
417
  DCHECK(args.length() == 0);
418

419 420
  // Initialize LiveEdit.
  LiveEdit::InitializeThreadLocal(this);
421 422

  // Just continue if breaks are disabled or debugger cannot be loaded.
423
  if (break_disabled()) return;
424

425
  // Enter the debugger.
426 427
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;
428

429
  // Postpone interrupt during breakpoint processing.
430
  PostponeInterruptsScope postpone(isolate_);
431 432

  // Get the debug info (create it if it does not exist).
433 434 435 436 437 438
  Handle<JSFunction> function(frame->function());
  Handle<SharedFunctionInfo> shared(function->shared());
  if (!EnsureDebugInfo(shared, function)) {
    // Return if we failed to retrieve the debug info.
    return;
  }
439
  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
440 441

  // Find the break point where execution has stopped.
442
  // PC points to the instruction after the current one, possibly a break
443
  // location as well. So the "- 1" to exclude it from the search.
444 445 446
  Address call_pc = frame->pc() - 1;
  BreakLocation break_location =
      BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
447 448

  // Check whether step next reached a new statement.
449
  if (!StepNextContinue(&break_location, frame)) {
450
    // Decrease steps left if performing multiple steps.
451 452
    if (thread_local_.step_count_ > 0) {
      thread_local_.step_count_--;
453 454 455 456 457
    }
  }

  // If there is one or more real break points check whether any of these are
  // triggered.
458
  Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
459 460
  if (break_location.HasBreakPoint()) {
    Handle<Object> break_point_objects = break_location.BreakPointObjects();
461
    break_points_hit = CheckBreakPoints(break_point_objects);
462 463
  }

464 465
  // If step out is active skip everything until the frame where we need to step
  // out to is reached, unless real breakpoint is hit.
466 467
  if (StepOutActive() &&
      frame->fp() != thread_local_.step_out_fp_ &&
468 469
      break_points_hit->IsUndefined() ) {
      // Step count should always be 0 for StepOut.
470
      DCHECK(thread_local_.step_count_ == 0);
471
  } else if (!break_points_hit->IsUndefined() ||
472 473
             (thread_local_.last_step_action_ != StepNone &&
              thread_local_.step_count_ == 0)) {
474 475 476
    // Notify debugger if a real break point is triggered or if performing
    // single stepping with no more steps to perform. Otherwise do another step.

477
    // Clear all current stepping setup.
478
    ClearStepping();
479

480 481 482 483 484 485 486
    if (thread_local_.queued_step_count_ > 0) {
      // Perform queued steps
      int step_count = thread_local_.queued_step_count_;

      // Clear queue
      thread_local_.queued_step_count_ = 0;

487
      PrepareStep(StepNext, step_count, StackFrame::NO_ID);
488 489
    } else {
      // Notify the debug event listeners.
490
      OnDebugBreak(break_points_hit, false);
491
    }
492
  } else if (thread_local_.last_step_action_ != StepNone) {
493 494
    // Hold on to last step action as it is cleared by the call to
    // ClearStepping.
495 496
    StepAction step_action = thread_local_.last_step_action_;
    int step_count = thread_local_.step_count_;
497

498 499 500 501 502 503
    // If StepNext goes deeper in code, StepOut until original frame
    // and keep step count queued up in the meantime.
    if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
      // Count frames until target frame
      int count = 0;
      JavaScriptFrameIterator it(isolate_);
504
      while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
505 506 507 508
        count++;
        it.Advance();
      }

509 510 511 512 513
      // Check that we indeed found the frame we are looking for.
      CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
      if (step_count > 1) {
        // Save old count and action to continue stepping after StepOut.
        thread_local_.queued_step_count_ = step_count - 1;
514 515
      }

516 517 518
      // Set up for StepOut to reach target frame.
      step_action = StepOut;
      step_count = count;
519 520
    }

521
    // Clear all current stepping setup.
522
    ClearStepping();
523 524

    // Set up for the remaining steps.
525
    PrepareStep(step_action, step_count, StackFrame::NO_ID);
526 527 528 529 530 531 532 533
  }
}


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

536 537 538
  // Count the number of break points hit. If there are multiple break points
  // they are in a FixedArray.
  Handle<FixedArray> break_points_hit;
539
  int break_points_hit_count = 0;
540
  DCHECK(!break_point_objects->IsUndefined());
541 542
  if (break_point_objects->IsFixedArray()) {
    Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
543
    break_points_hit = factory->NewFixedArray(array->length());
544
    for (int i = 0; i < array->length(); i++) {
545
      Handle<Object> o(array->get(i), isolate_);
546
      if (CheckBreakPoint(o)) {
547
        break_points_hit->set(break_points_hit_count++, *o);
548 549 550
      }
    }
  } else {
551
    break_points_hit = factory->NewFixedArray(1);
552
    if (CheckBreakPoint(break_point_objects)) {
553
      break_points_hit->set(break_points_hit_count++, *break_point_objects);
554 555 556
    }
  }

557
  // Return undefined if no break points were triggered.
558
  if (break_points_hit_count == 0) {
559
    return factory->undefined_value();
560
  }
561
  // Return break points hit as a JSArray.
562
  Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
563 564
  result->set_length(Smi::FromInt(break_points_hit_count));
  return result;
565 566 567
}


568 569 570 571 572 573 574 575 576 577 578 579
MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
                                        Handle<Object> args[]) {
  PostponeInterruptsScope no_interrupts(isolate_);
  AssertDebugContext();
  Handle<Object> holder = isolate_->natives_utils_object();
  Handle<JSFunction> fun = Handle<JSFunction>::cast(
      Object::GetProperty(isolate_, holder, name, STRICT).ToHandleChecked());
  Handle<Object> undefined = isolate_->factory()->undefined_value();
  return Execution::TryCall(fun, undefined, argc, args);
}


580 581
// Check whether a single break point object is triggered.
bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
582 583
  Factory* factory = isolate_->factory();
  HandleScope scope(isolate_);
584

585 586 587 588
  // Ignore check if break point object is not a JSObject.
  if (!break_point_object->IsJSObject()) return true;

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

591
  // Call IsBreakPointTriggered.
592
  Handle<Object> argv[] = { break_id, break_point_object };
593
  Handle<Object> result;
594 595
  if (!CallFunction("IsBreakPointTriggered", arraysize(argv), argv)
           .ToHandle(&result)) {
596 597
    return false;
  }
598 599

  // Return whether the break point is triggered.
600
  return result->IsTrue();
601 602 603
}


604
bool Debug::SetBreakPoint(Handle<JSFunction> function,
605 606
                          Handle<Object> break_point_object,
                          int* source_position) {
607
  HandleScope scope(isolate_);
608

609 610 611
  // Make sure the function is compiled and has set up the debug info.
  Handle<SharedFunctionInfo> shared(function->shared());
  if (!EnsureDebugInfo(shared, function)) {
612
    // Return if retrieving debug info failed.
613
    return true;
614 615
  }

616
  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
617
  // Source positions starts with zero.
618
  DCHECK(*source_position >= 0);
619 620

  // Find the break point and change it.
621
  BreakLocation location = BreakLocation::FromPosition(
622
      debug_info, ALL_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED);
623 624
  *source_position = location.statement_position();
  location.SetBreakPoint(break_point_object);
625

626
  // At least one active break point now.
627
  return debug_info->GetBreakPointCount() > 0;
628 629 630
}


631 632
bool Debug::SetBreakPointForScript(Handle<Script> script,
                                   Handle<Object> break_point_object,
633 634
                                   int* source_position,
                                   BreakPositionAlignment alignment) {
635 636
  HandleScope scope(isolate_);

637
  // Obtain shared function info for the function.
638 639
  Handle<Object> result =
      FindSharedFunctionInfoInScript(script, *source_position);
640 641 642
  if (result->IsUndefined()) return false;

  // Make sure the function has set up the debug info.
643
  Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
644 645 646 647 648 649 650 651 652 653 654 655 656 657
  if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
    // Return if retrieving debug info failed.
    return false;
  }

  // Find position within function. The script position might be before the
  // source position of the first function.
  int position;
  if (shared->start_position() > *source_position) {
    position = 0;
  } else {
    position = *source_position - shared->start_position();
  }

658
  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
659
  // Source positions starts with zero.
660
  DCHECK(position >= 0);
661 662

  // Find the break point and change it.
663
  BreakLocation location = BreakLocation::FromPosition(
664
      debug_info, ALL_BREAK_LOCATIONS, position, alignment);
665
  location.SetBreakPoint(break_point_object);
666

667 668
  position = (alignment == STATEMENT_ALIGNED) ? location.statement_position()
                                              : location.position();
669 670

  *source_position = position + shared->start_position();
671 672

  // At least one active break point now.
673
  DCHECK(debug_info->GetBreakPointCount() > 0);
674 675 676 677
  return true;
}


678
void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
679
  HandleScope scope(isolate_);
680

681 682
  DebugInfoListNode* node = debug_info_list_;
  while (node != NULL) {
683 684
    Handle<Object> result =
        DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
685 686
    if (!result->IsUndefined()) {
      // Get information in the break point.
687 688
      Handle<BreakPointInfo> break_point_info =
          Handle<BreakPointInfo>::cast(result);
689 690 691
      Handle<DebugInfo> debug_info = node->debug_info();

      // Find the break point and clear it.
692 693 694 695
      Address pc = debug_info->code()->entry() +
                   break_point_info->code_position()->value();

      BreakLocation location =
696
          BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, pc);
697
      location.ClearBreakPoint(break_point_object);
698 699 700 701

      // If there are no more break points left remove the debug info for this
      // function.
      if (debug_info->GetBreakPointCount() == 0) {
702
        RemoveDebugInfoAndClearFromShared(debug_info);
703 704 705 706 707 708 709 710 711
      }

      return;
    }
    node = node->next();
  }
}


712 713 714
// Clear out all the debug break code. This is ONLY supposed to be used when
// shutting down the debugger as it will leave the break point information in
// DebugInfo even though the code is patched back to the non break point state.
715
void Debug::ClearAllBreakPoints() {
716 717 718 719 720 721
  for (DebugInfoListNode* node = debug_info_list_; node != NULL;
       node = node->next()) {
    for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
         !it.Done(); it.Next()) {
      it.GetBreakLocation().ClearDebugBreak();
    }
722 723 724
  }
  // Remove all debug info.
  while (debug_info_list_ != NULL) {
725
    RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
726 727 728 729
  }
}


730 731
void Debug::FloodWithOneShot(Handle<JSFunction> function,
                             BreakLocatorType type) {
732 733 734
  // Make sure the function is compiled and has set up the debug info.
  Handle<SharedFunctionInfo> shared(function->shared());
  if (!EnsureDebugInfo(shared, function)) {
735 736 737
    // Return if we failed to retrieve the debug info.
    return;
  }
738 739

  // Flood the function with break points.
740 741
  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
  for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) {
742
    it.GetBreakLocation().SetOneShot();
743 744 745 746
  }
}


747 748
void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
  Handle<FixedArray> new_bindings(function->function_bindings());
749 750
  Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
                        isolate_);
751

752
  if (!bindee.is_null() && bindee->IsJSFunction()) {
753
    Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
    FloodWithOneShotGeneric(bindee_function);
  }
}


void Debug::FloodDefaultConstructorWithOneShot(Handle<JSFunction> function) {
  DCHECK(function->shared()->is_default_constructor());
  // Instead of stepping into the function we directly step into the super class
  // constructor.
  Isolate* isolate = function->GetIsolate();
  PrototypeIterator iter(isolate, function);
  Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
  if (!proto->IsJSFunction()) return;  // Object.prototype
  Handle<JSFunction> function_proto = Handle<JSFunction>::cast(proto);
  FloodWithOneShotGeneric(function_proto);
}


void Debug::FloodWithOneShotGeneric(Handle<JSFunction> function,
                                    Handle<Object> holder) {
  if (function->shared()->bound()) {
    FloodBoundFunctionWithOneShot(function);
  } else if (function->shared()->is_default_constructor()) {
    FloodDefaultConstructorWithOneShot(function);
778
  } else {
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
    Isolate* isolate = function->GetIsolate();
    // Don't allow step into functions in the native context.
    if (function->shared()->code() ==
            isolate->builtins()->builtin(Builtins::kFunctionApply) ||
        function->shared()->code() ==
            isolate->builtins()->builtin(Builtins::kFunctionCall)) {
      // Handle function.apply and function.call separately to flood the
      // function to be called and not the code for Builtins::FunctionApply or
      // Builtins::FunctionCall. The receiver of call/apply is the target
      // function.
      if (!holder.is_null() && holder->IsJSFunction()) {
        Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
        FloodWithOneShotGeneric(js_function);
      }
    } else {
      FloodWithOneShot(function);
    }
796 797 798 799
  }
}


800
void Debug::FloodHandlerWithOneShot() {
801
  // Iterate through the JavaScript stack looking for handlers.
802
  StackFrame::Id id = break_frame_id();
803 804 805 806
  if (id == StackFrame::NO_ID) {
    // If there is no JavaScript stack don't do anything.
    return;
  }
807
  for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
808
    JavaScriptFrame* frame = it.frame();
809
    int stack_slots = 0;  // The computed stack slot count is not used.
810
    if (frame->LookupExceptionHandlerInTable(&stack_slots, NULL) > 0) {
811
      // Flood the function with the catch/finally block with break points.
812
      FloodWithOneShot(Handle<JSFunction>(frame->function()));
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
      return;
    }
  }
}


void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
  if (type == BreakUncaughtException) {
    break_on_uncaught_exception_ = enable;
  } else {
    break_on_exception_ = enable;
  }
}


828 829 830 831 832 833 834 835 836
bool Debug::IsBreakOnException(ExceptionBreakType type) {
  if (type == BreakUncaughtException) {
    return break_on_uncaught_exception_;
  } else {
    return break_on_exception_;
  }
}


837 838 839 840 841 842 843
FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) {
  List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
  frame->Summarize(&frames);
  return frames.first();
}


844 845 846
void Debug::PrepareStep(StepAction step_action,
                        int step_count,
                        StackFrame::Id frame_id) {
847
  HandleScope scope(isolate_);
848

849
  DCHECK(in_debug_scope());
850 851 852

  // Remember this step action and count.
  thread_local_.last_step_action_ = step_action;
853 854 855 856 857 858 859
  if (step_action == StepOut) {
    // For step out target frame will be found on the stack so there is no need
    // to set step counter for it. It's expected to always be 0 for StepOut.
    thread_local_.step_count_ = 0;
  } else {
    thread_local_.step_count_ = step_count;
  }
860 861 862 863 864

  // Get the frame where the execution has stopped and skip the debug frame if
  // any. The debug frame will only be present if execution was stopped due to
  // hitting a break point. In other situations (e.g. unhandled exception) the
  // debug frame is not present.
865
  StackFrame::Id id = break_frame_id();
866 867 868 869
  if (id == StackFrame::NO_ID) {
    // If there is no JavaScript stack don't do anything.
    return;
  }
870 871 872
  if (frame_id != StackFrame::NO_ID) {
    id = frame_id;
  }
873
  JavaScriptFrameIterator frames_it(isolate_, id);
874 875 876 877 878 879 880
  JavaScriptFrame* frame = frames_it.frame();

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

  // If the function on the top frame is unresolved perform step out. This will
881
  // be the case when calling unknown function and having the debugger stopped
882 883 884 885 886 887
  // in an unhandled exception.
  if (!frame->function()->IsJSFunction()) {
    // Step out: Find the calling JavaScript frame and flood it with
    // breakpoints.
    frames_it.Advance();
    // Fill the function to return to with one-shot break points.
888
    JSFunction* function = frames_it.frame()->function();
889
    FloodWithOneShot(Handle<JSFunction>(function));
890 891 892 893
    return;
  }

  // Get the debug info (create it if it does not exist).
894
  FrameSummary summary = GetFirstFrameSummary(frame);
895
  Handle<JSFunction> function(summary.function());
896 897
  Handle<SharedFunctionInfo> shared(function->shared());
  if (!EnsureDebugInfo(shared, function)) {
898 899 900
    // Return if ensuring debug info failed.
    return;
  }
901

902 903 904
  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
  // Refresh frame summary if the code has been recompiled for debugging.
  if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame);
905

906 907
  // PC points to the instruction after the current one, possibly a break
  // location as well. So the "- 1" to exclude it from the search.
908
  Address call_pc = summary.pc() - 1;
909 910 911
  BreakLocation location =
      BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);

912
  // If this is the last break code target step out is the only possibility.
913
  if (location.IsReturn() || step_action == StepOut) {
914 915
    if (step_action == StepOut) {
      // Skip step_count frames starting with the current one.
ager@chromium.org's avatar
ager@chromium.org committed
916
      while (step_count-- > 0 && !frames_it.done()) {
917 918 919
        frames_it.Advance();
      }
    } else {
920
      DCHECK(location.IsReturn());
921 922
      frames_it.Advance();
    }
923
    // Skip native and extension functions on the stack.
924
    while (!frames_it.done() &&
925
           !frames_it.frame()->function()->IsSubjectToDebugging()) {
926 927
      frames_it.Advance();
    }
928 929 930 931
    // Step out: If there is a JavaScript caller frame, we need to
    // flood it with breakpoints.
    if (!frames_it.done()) {
      // Fill the function to return to with one-shot break points.
932
      JSFunction* function = frames_it.frame()->function();
933
      FloodWithOneShot(Handle<JSFunction>(function));
934 935
      // Set target frame pointer.
      ActivateStepOut(frames_it.frame());
936
    }
937 938 939 940
    return;
  }

  if (step_action != StepNext && step_action != StepMin) {
941 942
    // If there's restarter frame on top of the stack, just get the pointer
    // to function which is going to be restarted.
943
    if (thread_local_.restarter_frame_function_pointer_ != NULL) {
944 945
      Handle<JSFunction> restarted_function(
          JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
946
      FloodWithOneShot(restarted_function);
947
    } else if (location.IsCall()) {
948
      // Find target function on the expression stack.
949
      // Expression stack looks like this (top to bottom):
950 951 952 953 954
      // argN
      // ...
      // arg0
      // Receiver
      // Function to call
955 956 957 958
      int num_expressions_without_args =
          frame->ComputeExpressionsCount() - location.CallArgumentsCount();
      DCHECK(num_expressions_without_args >= 2);
      Object* fun = frame->GetExpression(num_expressions_without_args - 2);
verwaest@chromium.org's avatar
verwaest@chromium.org committed
959 960 961 962 963 964

      // Flood the actual target of call/apply.
      if (fun->IsJSFunction()) {
        Isolate* isolate = JSFunction::cast(fun)->GetIsolate();
        Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply);
        Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall);
965 966 967
        // Find target function on the expression stack for expression like
        // Function.call.call...apply(...)
        int i = 1;
verwaest@chromium.org's avatar
verwaest@chromium.org committed
968 969 970
        while (fun->IsJSFunction()) {
          Code* code = JSFunction::cast(fun)->shared()->code();
          if (code != apply && code != call) break;
971 972 973
          DCHECK(num_expressions_without_args >= i);
          fun = frame->GetExpression(num_expressions_without_args - i);
          i--;
verwaest@chromium.org's avatar
verwaest@chromium.org committed
974 975 976
        }
      }

977 978
      if (fun->IsJSFunction()) {
        Handle<JSFunction> js_function(JSFunction::cast(fun));
979
        FloodWithOneShotGeneric(js_function);
980 981 982
      }
    }

983
    ActivateStepIn(frame);
984
  }
985 986 987 988 989 990 991 992 993 994 995 996 997

  // Fill the current function with one-shot break points even for step in on
  // a call target as the function called might be a native function for
  // which step in will not stop. It also prepares for stepping in
  // getters/setters.
  // If we are stepping into another frame, only fill calls and returns.
  FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
                                                      : ALL_BREAK_LOCATIONS);

  // Remember source position and frame to handle step next.
  thread_local_.last_statement_position_ =
      debug_info->code()->SourceStatementPosition(summary.pc());
  thread_local_.last_fp_ = frame->UnpaddedFP();
998 999 1000 1001 1002 1003 1004
}


// Check whether the current debug break should be reported to the debugger. It
// is used to have step next and step in only report break back to the debugger
// if on a different frame or in a different statement. In some situations
// there will be several break points in the same statement when the code is
1005
// flooded with one-shot break points. This function helps to perform several
1006
// steps before reporting break back to the debugger.
1007
bool Debug::StepNextContinue(BreakLocation* break_location,
1008
                             JavaScriptFrame* frame) {
1009 1010
  // StepNext and StepOut shouldn't bring us deeper in code, so last frame
  // shouldn't be a parent of current frame.
1011 1012 1013
  StepAction step_action = thread_local_.last_step_action_;

  if (step_action == StepNext || step_action == StepOut) {
1014 1015 1016
    if (frame->fp() < thread_local_.last_fp_) return true;
  }

1017 1018 1019 1020 1021
  // We stepped into a new frame if the frame pointer changed.
  if (step_action == StepFrame) {
    return frame->UnpaddedFP() == thread_local_.last_fp_;
  }

1022 1023
  // If the step last action was step next or step in make sure that a new
  // statement is hit.
1024
  if (step_action == StepNext || step_action == StepIn) {
1025
    // Never continue if returning from function.
1026
    if (break_location->IsReturn()) return false;
1027 1028 1029

    // Continue if we are still on the same frame and in the same statement.
    int current_statement_position =
1030
        break_location->code()->SourceStatementPosition(frame->pc());
1031
    return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1032
        thread_local_.last_statement_position_ == current_statement_position;
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
  }

  // No step next action - don't continue.
  return false;
}


// Check whether the code object at the specified address is a debug break code
// object.
bool Debug::IsDebugBreak(Address addr) {
1043
  Code* code = Code::GetCodeFromTargetAddress(addr);
1044
  return code->is_debug_stub();
1045 1046 1047 1048 1049
}


// Simple function for returning the source positions for active break points.
Handle<Object> Debug::GetSourceBreakLocations(
1050 1051
    Handle<SharedFunctionInfo> shared,
    BreakPositionAlignment position_alignment) {
1052
  Isolate* isolate = shared->GetIsolate();
1053
  Heap* heap = isolate->heap();
1054
  if (!shared->HasDebugInfo()) {
1055 1056
    return Handle<Object>(heap->undefined_value(), isolate);
  }
1057
  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1058
  if (debug_info->GetBreakPointCount() == 0) {
1059
    return Handle<Object>(heap->undefined_value(), isolate);
1060 1061
  }
  Handle<FixedArray> locations =
1062
      isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1063
  int count = 0;
1064
  for (int i = 0; i < debug_info->break_points()->length(); ++i) {
1065 1066 1067
    if (!debug_info->break_points()->get(i)->IsUndefined()) {
      BreakPointInfo* break_point_info =
          BreakPointInfo::cast(debug_info->break_points()->get(i));
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
      int break_points = break_point_info->GetBreakPointCount();
      if (break_points == 0) continue;
      Smi* position = NULL;
      switch (position_alignment) {
        case STATEMENT_ALIGNED:
          position = break_point_info->statement_position();
          break;
        case BREAK_POSITION_ALIGNED:
          position = break_point_info->source_position();
          break;
1078
      }
1079
      for (int j = 0; j < break_points; ++j) locations->set(count++, position);
1080 1081 1082 1083 1084 1085
    }
  }
  return locations;
}


1086
// Handle stepping into a function.
1087
void Debug::HandleStepIn(Handle<Object> function_obj, bool is_constructor) {
1088 1089 1090 1091 1092
  // Flood getter/setter if we either step in or step to another frame.
  bool step_frame = thread_local_.last_step_action_ == StepFrame;
  if (!StepInActive() && !step_frame) return;
  if (!function_obj->IsJSFunction()) return;
  Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj);
1093
  Isolate* isolate = function->GetIsolate();
1094 1095 1096 1097 1098 1099

  StackFrameIterator it(isolate);
  it.Advance();
  // For constructor functions skip another frame.
  if (is_constructor) {
    DCHECK(it.frame()->is_construct());
1100 1101
    it.Advance();
  }
1102
  Address fp = it.frame()->fp();
1103 1104

  // Flood the function with one-shot break points if it is called from where
1105 1106
  // step into was requested, or when stepping into a new frame.
  if (fp == thread_local_.step_into_fp_ || step_frame) {
1107
    FloodWithOneShotGeneric(function, Handle<Object>());
erik.corry@gmail.com's avatar
erik.corry@gmail.com committed
1108
  }
1109 1110 1111
}


1112 1113 1114 1115
void Debug::ClearStepping() {
  // Clear the various stepping setup.
  ClearOneShot();
  ClearStepIn();
1116
  ClearStepOut();
1117 1118 1119 1120 1121 1122
  ClearStepNext();

  // Clear multiple step counter.
  thread_local_.step_count_ = 0;
}

1123

1124 1125 1126 1127 1128
// Clears all the one-shot break points that are currently set. Normally this
// function is called each time a break point is hit as one shot break points
// are used to support stepping.
void Debug::ClearOneShot() {
  // The current implementation just runs through all the breakpoints. When the
1129
  // last break point for a function is removed that function is automatically
1130
  // removed from the list.
1131 1132 1133 1134 1135
  for (DebugInfoListNode* node = debug_info_list_; node != NULL;
       node = node->next()) {
    for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
         !it.Done(); it.Next()) {
      it.GetBreakLocation().ClearOneShot();
1136 1137 1138 1139 1140
    }
  }
}


1141
void Debug::ActivateStepIn(StackFrame* frame) {
1142
  DCHECK(!StepOutActive());
1143
  thread_local_.step_into_fp_ = frame->UnpaddedFP();
1144 1145 1146 1147 1148 1149 1150 1151
}


void Debug::ClearStepIn() {
  thread_local_.step_into_fp_ = 0;
}


1152
void Debug::ActivateStepOut(StackFrame* frame) {
1153
  DCHECK(!StepInActive());
1154
  thread_local_.step_out_fp_ = frame->UnpaddedFP();
1155 1156 1157 1158 1159 1160 1161 1162
}


void Debug::ClearStepOut() {
  thread_local_.step_out_fp_ = 0;
}


1163 1164
void Debug::ClearStepNext() {
  thread_local_.last_step_action_ = StepNone;
1165
  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1166 1167 1168 1169
  thread_local_.last_fp_ = 0;
}


1170 1171 1172 1173
bool MatchingCodeTargets(Code* target1, Code* target2) {
  if (target1 == target2) return true;
  if (target1->kind() != target2->kind()) return false;
  return target1->is_handler() || target1->is_inline_cache_stub();
1174 1175 1176
}


1177 1178 1179 1180 1181 1182 1183
// Count the number of calls before the current frame PC to find the
// corresponding PC in the newly recompiled code.
static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code,
                                       Address old_pc) {
  DCHECK_EQ(old_code->kind(), Code::FUNCTION);
  DCHECK_EQ(new_code->kind(), Code::FUNCTION);
  DCHECK(new_code->has_debug_break_slots());
1184 1185 1186 1187
  static const int mask = RelocInfo::kCodeTargetMask;

  // Find the target of the current call.
  Code* target = NULL;
1188
  intptr_t delta = 0;
1189 1190
  for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
    RelocInfo* rinfo = it.rinfo();
1191 1192 1193 1194
    Address current_pc = rinfo->pc();
    // The frame PC is behind the call instruction by the call instruction size.
    if (current_pc > old_pc) break;
    delta = old_pc - current_pc;
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
    target = Code::GetCodeFromTargetAddress(rinfo->target_address());
  }

  // Count the number of calls to the same target before the current call.
  int index = 0;
  for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
    RelocInfo* rinfo = it.rinfo();
    Address current_pc = rinfo->pc();
    if (current_pc > old_pc) break;
    Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
    if (MatchingCodeTargets(target, current)) index++;
  }

  DCHECK(index > 0);

  // Repeat the count on the new code to find corresponding call.
  for (RelocIterator it(new_code, mask); !it.done(); it.next()) {
    RelocInfo* rinfo = it.rinfo();
    Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
    if (MatchingCodeTargets(target, current)) index--;
    if (index == 0) return rinfo->pc() + delta;
1216 1217
  }

1218 1219
  UNREACHABLE();
  return NULL;
1220 1221 1222
}


1223 1224
// Count the number of continuations at which the current pc offset is at.
static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) {
1225
  DCHECK_EQ(code->kind(), Code::FUNCTION);
1226 1227 1228
  Address pc = code->instruction_start() + pc_offset;
  int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
  int index = 0;
1229
  for (RelocIterator it(code, mask); !it.done(); it.next()) {
1230 1231 1232 1233 1234
    index++;
    RelocInfo* rinfo = it.rinfo();
    Address current_pc = rinfo->pc();
    if (current_pc == pc) break;
    DCHECK(current_pc < pc);
1235
  }
1236 1237
  return index;
}
1238 1239


1240 1241 1242 1243 1244 1245 1246 1247
// Find the pc offset for the given continuation index.
static int ComputePcOffsetFromContinuationIndex(Code* code, int index) {
  DCHECK_EQ(code->kind(), Code::FUNCTION);
  DCHECK(code->has_debug_break_slots());
  int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
  RelocIterator it(code, mask);
  for (int i = 1; i < index; i++) it.next();
  return static_cast<int>(it.rinfo()->pc() - code->instruction_start());
1248 1249 1250
}


1251 1252 1253 1254 1255
class RedirectActiveFunctions : public ThreadVisitor {
 public:
  explicit RedirectActiveFunctions(SharedFunctionInfo* shared)
      : shared_(shared) {
    DCHECK(shared->HasDebugCode());
1256 1257
  }

1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
    for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
      JavaScriptFrame* frame = it.frame();
      JSFunction* function = frame->function();
      if (frame->is_optimized()) continue;
      if (!function->Inlines(shared_)) continue;

      Code* frame_code = frame->LookupCode();
      DCHECK(frame_code->kind() == Code::FUNCTION);
      if (frame_code->has_debug_break_slots()) continue;

      Code* new_code = function->shared()->code();
      Address old_pc = frame->pc();
      Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc);

      if (FLAG_trace_deopt) {
        PrintF("Replacing pc for debugging: %08" V8PRIxPTR " => %08" V8PRIxPTR
               "\n",
               reinterpret_cast<intptr_t>(old_pc),
               reinterpret_cast<intptr_t>(new_pc));
      }
1279

1280 1281 1282 1283
      if (FLAG_enable_embedded_constant_pool) {
        // Update constant pool pointer for new code.
        frame->set_constant_pool(new_code->constant_pool());
      }
1284

1285 1286 1287 1288
      // Patch the return address to return into the code with
      // debug break slots.
      frame->set_pc(new_pc);
    }
1289 1290 1291
  }

 private:
1292 1293
  SharedFunctionInfo* shared_;
  DisallowHeapAllocation no_gc_;
1294 1295 1296
};


1297 1298
bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
  DCHECK(shared->is_compiled());
1299

1300 1301
  if (isolate_->concurrent_recompilation_enabled()) {
    isolate_->optimizing_compile_dispatcher()->Flush();
1302
  }
1303

1304 1305
  List<Handle<JSFunction> > functions;
  List<Handle<JSGeneratorObject> > suspended_generators;
1306

1307 1308
  if (!shared->optimized_code_map()->IsSmi()) {
    shared->ClearOptimizedCodeMap();
1309
  }
1310

1311 1312 1313
  // Make sure we abort incremental marking.
  isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
                                      "prepare for break points");
1314

1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
  {
    HeapIterator iterator(isolate_->heap());
    HeapObject* obj;
    bool include_generators = shared->is_generator();

    while ((obj = iterator.next())) {
      if (obj->IsJSFunction()) {
        JSFunction* function = JSFunction::cast(obj);
        if (!function->Inlines(*shared)) continue;
        if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) {
          Deoptimizer::DeoptimizeFunction(function);
1326
        }
1327
        if (function->shared() == *shared) functions.Add(handle(function));
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337
      } else if (include_generators && obj->IsJSGeneratorObject()) {
        JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj);
        if (!generator_obj->is_suspended()) continue;
        JSFunction* function = generator_obj->function();
        if (!function->Inlines(*shared)) continue;
        int pc_offset = generator_obj->continuation();
        int index =
            ComputeContinuationIndexFromPcOffset(function->code(), pc_offset);
        generator_obj->set_continuation(index);
        suspended_generators.Add(handle(generator_obj));
1338 1339
      }
    }
1340
  }
1341

1342 1343
  if (!shared->HasDebugCode()) {
    DCHECK(functions.length() > 0);
1344
    if (!Compiler::CompileDebugCode(functions.first())) return false;
1345
  }
1346

1347 1348 1349
  for (Handle<JSFunction> const function : functions) {
    function->ReplaceCode(shared->code());
  }
1350

1351 1352 1353 1354 1355
  for (Handle<JSGeneratorObject> const generator_obj : suspended_generators) {
    int index = generator_obj->continuation();
    int pc_offset = ComputePcOffsetFromContinuationIndex(shared->code(), index);
    generator_obj->set_continuation(pc_offset);
  }
1356

1357 1358 1359 1360
  // Update PCs on the stack to point to recompiled code.
  RedirectActiveFunctions redirect_visitor(*shared);
  redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top());
  isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor);
1361

1362
  return true;
1363 1364 1365
}


1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
class SharedFunctionInfoFinder {
 public:
  explicit SharedFunctionInfoFinder(int target_position)
      : current_candidate_(NULL),
        current_candidate_closure_(NULL),
        current_start_position_(RelocInfo::kNoPosition),
        target_position_(target_position) {}

  void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) {
    int start_position = shared->function_token_position();
    if (start_position == RelocInfo::kNoPosition) {
      start_position = shared->start_position();
    }
1379

1380 1381 1382 1383 1384 1385
    if (start_position > target_position_) return;
    if (target_position_ > shared->end_position()) return;

    if (current_candidate_ != NULL) {
      if (current_start_position_ == start_position &&
          shared->end_position() == current_candidate_->end_position()) {
1386 1387
        // If we already have a matching closure, do not throw it away.
        if (current_candidate_closure_ != NULL && closure == NULL) return;
1388 1389 1390
        // If a top-level function contains only one function
        // declaration the source for the top-level and the function
        // is the same. In that case prefer the non top-level function.
1391
        if (!current_candidate_->is_toplevel() && shared->is_toplevel()) return;
1392 1393 1394 1395 1396
      } else if (start_position < current_start_position_ ||
                 current_candidate_->end_position() < shared->end_position()) {
        return;
      }
    }
1397

1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
    current_start_position_ = start_position;
    current_candidate_ = shared;
    current_candidate_closure_ = closure;
  }

  SharedFunctionInfo* Result() { return current_candidate_; }

  JSFunction* ResultClosure() { return current_candidate_closure_; }

 private:
  SharedFunctionInfo* current_candidate_;
  JSFunction* current_candidate_closure_;
  int current_start_position_;
  int target_position_;
  DisallowHeapAllocation no_gc_;
};
1414

1415

1416 1417 1418 1419 1420 1421
// We need to find a SFI for a literal that may not yet have been compiled yet,
// and there may not be a JSFunction referencing it. Find the SFI closest to
// the given position, compile it to reveal possible inner SFIs and repeat.
// While we are at this, also ensure code with debug break slots so that we do
// not have to compile a SFI without JSFunction, which is paifu for those that
// cannot be compiled without context (need to find outer compilable SFI etc.)
1422 1423 1424 1425 1426
Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
                                                     int position) {
  while (true) {
    // Go through all shared function infos associated with this script to
    // find the inner most function containing this position.
1427 1428
    // If there is no shared function info for this script at all, there is
    // no point in looking for it by walking the heap.
1429 1430 1431 1432 1433
    if (!script->shared_function_infos()->IsWeakFixedArray()) break;

    SharedFunctionInfo* shared;
    {
      SharedFunctionInfoFinder finder(position);
1434 1435 1436 1437
      WeakFixedArray::Iterator iterator(script->shared_function_infos());
      SharedFunctionInfo* candidate;
      while ((candidate = iterator.Next<SharedFunctionInfo>())) {
        finder.NewCandidate(candidate);
1438 1439 1440
      }
      shared = finder.Result();
      if (shared == NULL) break;
1441 1442
      // We found it if it's already compiled and has debug code.
      if (shared->HasDebugCode()) return handle(shared);
1443
    }
1444 1445
    // If not, compile to reveal inner functions, if possible.
    if (shared->allows_lazy_compilation_without_context()) {
1446
      HandleScope scope(isolate_);
1447
      if (!Compiler::CompileDebugCode(handle(shared))) break;
1448
      continue;
1449
    }
1450

1451 1452 1453
    // If not possible, comb the heap for the best suitable compile target.
    JSFunction* closure;
    {
1454
      HeapIterator it(isolate_->heap());
1455 1456
      SharedFunctionInfoFinder finder(position);
      while (HeapObject* object = it.next()) {
1457 1458
        JSFunction* candidate_closure = NULL;
        SharedFunctionInfo* candidate = NULL;
1459
        if (object->IsJSFunction()) {
1460 1461
          candidate_closure = JSFunction::cast(object);
          candidate = candidate_closure->shared();
1462
        } else if (object->IsSharedFunctionInfo()) {
1463 1464
          candidate = SharedFunctionInfo::cast(object);
          if (!candidate->allows_lazy_compilation_without_context()) continue;
1465 1466 1467
        } else {
          continue;
        }
1468 1469 1470
        if (candidate->script() == *script) {
          finder.NewCandidate(candidate, candidate_closure);
        }
1471 1472 1473 1474
      }
      closure = finder.ResultClosure();
      shared = finder.Result();
    }
1475 1476
    HandleScope scope(isolate_);
    if (closure == NULL) {
1477
      if (!Compiler::CompileDebugCode(handle(shared))) break;
1478
    } else {
1479
      if (!Compiler::CompileDebugCode(handle(closure))) break;
1480 1481 1482
    }
  }
  return isolate_->factory()->undefined_value();
1483 1484 1485
}


1486
// Ensures the debug information is present for shared.
1487 1488
bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
                            Handle<JSFunction> function) {
1489
  if (!shared->IsSubjectToDebugging()) return false;
1490

1491
  // Return if we already have the debug info for shared.
1492
  if (shared->HasDebugInfo()) return true;
1493

1494
  if (function.is_null()) {
1495
    DCHECK(shared->HasDebugCode());
1496
  } else if (!Compiler::Compile(function, CLEAR_EXCEPTION)) {
1497 1498
    return false;
  }
1499

1500 1501
  if (!PrepareFunctionForBreakPoints(shared)) return false;

1502 1503 1504 1505 1506
  // Make sure IC state is clean. This is so that we correctly flood
  // accessor pairs when stepping in.
  shared->code()->ClearInlineCaches();
  shared->feedback_vector()->ClearICSlots(*shared);

1507
  // Create the debug info object.
1508
  DCHECK(shared->HasDebugCode());
1509
  Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared);
1510 1511 1512 1513 1514 1515

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

1516
  return true;
1517 1518 1519
}


1520 1521 1522
void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) {
  HandleScope scope(isolate_);
  Handle<SharedFunctionInfo> shared(debug_info->shared());
1523

1524
  DCHECK_NOT_NULL(debug_info_list_);
1525 1526 1527 1528
  // Run through the debug info objects to find this one and remove it.
  DebugInfoListNode* prev = NULL;
  DebugInfoListNode* current = debug_info_list_;
  while (current != NULL) {
1529 1530 1531 1532 1533 1534 1535 1536 1537
    if (current->debug_info().is_identical_to(debug_info)) {
      // Unlink from list. If prev is NULL we are looking at the first element.
      if (prev == NULL) {
        debug_info_list_ = current->next();
      } else {
        prev->set_next(current->next());
      }
      delete current;
      shared->set_debug_info(isolate_->heap()->undefined_value());
1538 1539 1540 1541 1542 1543
      return;
    }
    // Move to next in list.
    prev = current;
    current = current->next();
  }
1544 1545 1546 1547 1548 1549

  UNREACHABLE();
}


void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
1550 1551 1552
  after_break_target_ = NULL;

  if (LiveEdit::SetAfterBreakTarget(this)) return;  // LiveEdit did the job.
1553

1554 1555
  // Continue just after the slot.
  after_break_target_ = frame->pc();
1556 1557 1558
}


1559
bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
1560
  HandleScope scope(isolate_);
1561 1562

  // Get the executing function in which the debug break occurred.
1563 1564
  Handle<JSFunction> function(JSFunction::cast(frame->function()));
  Handle<SharedFunctionInfo> shared(function->shared());
1565 1566 1567 1568

  // With no debug info there are no break points, so we can't be at a return.
  if (!shared->HasDebugInfo()) return false;
  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1569 1570 1571
  Handle<Code> code(debug_info->code());
#ifdef DEBUG
  // Get the code which is actually executing.
1572
  Handle<Code> frame_code(frame->LookupCode());
1573
  DCHECK(frame_code.is_identical_to(code));
1574 1575
#endif

1576 1577 1578
  // Find the reloc info matching the start of the debug break slot.
  Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength;
  int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
1579
  for (RelocIterator it(*code, mask); !it.done(); it.next()) {
1580
    if (it.rinfo()->pc() == slot_pc) return true;
1581 1582 1583 1584 1585
  }
  return false;
}


1586
void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
1587
                                  LiveEdit::FrameDropMode mode,
1588
                                  Object** restarter_frame_function_pointer) {
1589
  if (mode != LiveEdit::CURRENTLY_SET_MODE) {
1590 1591
    thread_local_.frame_drop_mode_ = mode;
  }
1592
  thread_local_.break_frame_id_ = new_break_frame_id;
1593 1594
  thread_local_.restarter_frame_function_pointer_ =
      restarter_frame_function_pointer;
1595 1596 1597
}


1598
bool Debug::IsDebugGlobal(GlobalObject* global) {
1599
  return is_loaded() && global == debug_context()->global_object();
1600 1601 1602
}


1603
void Debug::ClearMirrorCache() {
1604
  PostponeInterruptsScope postpone(isolate_);
1605
  HandleScope scope(isolate_);
1606
  CallFunction("ClearMirrorCache", 0, NULL);
1607 1608 1609
}


1610
Handle<FixedArray> Debug::GetLoadedScripts() {
1611
  isolate_->heap()->CollectAllGarbage();
1612 1613 1614 1615 1616 1617 1618 1619
  Factory* factory = isolate_->factory();
  if (!factory->script_list()->IsWeakFixedArray()) {
    return factory->empty_fixed_array();
  }
  Handle<WeakFixedArray> array =
      Handle<WeakFixedArray>::cast(factory->script_list());
  Handle<FixedArray> results = factory->NewFixedArray(array->Length());
  int length = 0;
1620 1621 1622 1623 1624
  {
    Script::Iterator iterator(isolate_);
    Script* script;
    while ((script = iterator.Next())) {
      if (script->HasValidSource()) results->set(length++, script);
1625 1626 1627 1628
    }
  }
  results->Shrink(length);
  return results;
1629 1630 1631
}


1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669
void Debug::GetStepinPositions(JavaScriptFrame* frame, StackFrame::Id frame_id,
                               List<int>* results_out) {
  FrameSummary summary = GetFirstFrameSummary(frame);

  Handle<JSFunction> fun = Handle<JSFunction>(summary.function());
  Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared());

  if (!EnsureDebugInfo(shared, fun)) return;

  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
  // Refresh frame summary if the code has been recompiled for debugging.
  if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame);

  // Find range of break points starting from the break point where execution
  // has stopped.
  Address call_pc = summary.pc() - 1;
  List<BreakLocation> locations;
  BreakLocation::FromAddressSameStatement(debug_info, ALL_BREAK_LOCATIONS,
                                          call_pc, &locations);

  for (BreakLocation location : locations) {
    if (location.pc() <= summary.pc()) {
      // The break point is near our pc. Could be a step-in possibility,
      // that is currently taken by active debugger call.
      if (break_frame_id() == StackFrame::NO_ID) {
        continue;  // We are not stepping.
      } else {
        JavaScriptFrameIterator frame_it(isolate_, break_frame_id());
        // If our frame is a top frame and we are stepping, we can do step-in
        // at this place.
        if (frame_it.frame()->id() != frame_id) continue;
      }
    }
    if (location.IsStepInLocation()) results_out->Add(location.position());
  }
}


1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684
void Debug::RecordEvalCaller(Handle<Script> script) {
  script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
  // For eval scripts add information on the function from which eval was
  // called.
  StackTraceFrameIterator it(script->GetIsolate());
  if (!it.done()) {
    script->set_eval_from_shared(it.frame()->function()->shared());
    Code* code = it.frame()->LookupCode();
    int offset = static_cast<int>(
        it.frame()->pc() - code->instruction_start());
    script->set_eval_from_instructions_offset(Smi::FromInt(offset));
  }
}


1685
MaybeHandle<Object> Debug::MakeExecutionState() {
1686
  // Create the execution state object.
1687
  Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
1688
  return CallFunction("MakeExecutionState", arraysize(argv), argv);
1689 1690 1691
}


1692
MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
1693
  // Create the new break event object.
1694 1695
  Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
                            break_points_hit };
1696
  return CallFunction("MakeBreakEvent", arraysize(argv), argv);
1697 1698 1699
}


1700
MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
1701 1702
                                              bool uncaught,
                                              Handle<Object> promise) {
1703
  // Create the new exception event object.
1704
  Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
1705
                            exception,
1706 1707
                            isolate_->factory()->ToBoolean(uncaught),
                            promise };
1708
  return CallFunction("MakeExceptionEvent", arraysize(argv), argv);
1709 1710 1711
}


1712
MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
1713
                                            v8::DebugEvent type) {
1714
  // Create the compile event object.
1715
  Handle<Object> script_wrapper = Script::GetWrapper(script);
1716
  Handle<Object> argv[] = { script_wrapper,
1717
                            isolate_->factory()->NewNumberFromInt(type) };
1718
  return CallFunction("MakeCompileEvent", arraysize(argv), argv);
1719 1720 1721
}


1722 1723 1724
MaybeHandle<Object> Debug::MakePromiseEvent(Handle<JSObject> event_data) {
  // Create the promise event object.
  Handle<Object> argv[] = { event_data };
1725
  return CallFunction("MakePromiseEvent", arraysize(argv), argv);
1726 1727 1728
}


1729 1730 1731
MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
  // Create the async task event object.
  Handle<Object> argv[] = { task_event };
1732
  return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv);
1733 1734 1735
}


1736
void Debug::OnThrow(Handle<Object> exception) {
1737
  if (in_debug_scope() || ignore_events()) return;
1738 1739
  // Temporarily clear any scheduled_exception to allow evaluating
  // JavaScript from the debug event handler.
1740
  HandleScope scope(isolate_);
1741 1742 1743 1744 1745
  Handle<Object> scheduled_exception;
  if (isolate_->has_scheduled_exception()) {
    scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
    isolate_->clear_scheduled_exception();
  }
1746
  OnException(exception, isolate_->GetPromiseOnStackOnThrow());
1747 1748 1749
  if (!scheduled_exception.is_null()) {
    isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
  }
1750 1751
}

1752

1753 1754
void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
  if (in_debug_scope() || ignore_events()) return;
1755
  HandleScope scope(isolate_);
1756 1757
  // Check whether the promise has been marked as having triggered a message.
  Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1758
  if (JSReceiver::GetDataProperty(promise, key)->IsUndefined()) {
1759
    OnException(value, promise);
1760 1761 1762 1763 1764 1765
  }
}


MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler(
    Handle<JSObject> promise) {
1766
  Handle<JSFunction> fun = isolate_->promise_has_user_defined_reject_handler();
1767
  return Execution::Call(isolate_, fun, promise, 0, NULL);
1768
}
1769

1770

1771
void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
1772
  // In our prediction, try-finally is not considered to catch.
1773 1774
  Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
  bool uncaught = (catch_type == Isolate::NOT_CAUGHT);
1775
  if (promise->IsJSObject()) {
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785
    Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
    // Mark the promise as already having triggered a message.
    Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
    JSObject::SetProperty(jspromise, key, key, STRICT).Assert();
    // Check whether the promise reject is considered an uncaught exception.
    Handle<Object> has_reject_handler;
    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
        isolate_, has_reject_handler,
        PromiseHasUserDefinedRejectHandler(jspromise), /* void */);
    uncaught = has_reject_handler->IsFalse();
1786
  }
1787 1788 1789
  // Bail out if exception breaks are not active
  if (uncaught) {
    // Uncaught exceptions are reported by either flags.
1790
    if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
1791 1792
  } else {
    // Caught exceptions are reported is activated.
1793
    if (!break_on_exception_) return;
1794 1795
  }

1796 1797
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;
1798 1799

  // Clear all current stepping setup.
1800
  ClearStepping();
1801

1802 1803 1804
  // Create the event data object.
  Handle<Object> event_data;
  // Bail out and don't call debugger if exception.
1805 1806 1807 1808
  if (!MakeExceptionEvent(
          exception, uncaught, promise).ToHandle(&event_data)) {
    return;
  }
1809

1810
  // Process debug event.
1811
  ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
1812 1813 1814 1815
  // Return to continue execution from where the exception was thrown.
}


1816
void Debug::OnCompileError(Handle<Script> script) {
1817 1818 1819 1820 1821 1822
  if (ignore_events()) return;

  if (in_debug_scope()) {
    ProcessCompileEventInDebugScope(v8::CompileError, script);
    return;
  }
1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837

  HandleScope scope(isolate_);
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;

  // Create the compile state object.
  Handle<Object> event_data;
  // Bail out and don't call debugger if exception.
  if (!MakeCompileEvent(script, v8::CompileError).ToHandle(&event_data)) return;

  // Process debug event.
  ProcessDebugEvent(v8::CompileError, Handle<JSObject>::cast(event_data), true);
}


1838 1839
void Debug::OnDebugBreak(Handle<Object> break_points_hit,
                            bool auto_continue) {
1840 1841
  // The caller provided for DebugScope.
  AssertDebugContext();
1842
  // Bail out if there is no listener for this event
1843
  if (ignore_events()) return;
1844

1845
  HandleScope scope(isolate_);
1846 1847 1848
  // Create the event data object.
  Handle<Object> event_data;
  // Bail out and don't call debugger if exception.
1849
  if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
1850

1851 1852 1853 1854
  // Process debug event.
  ProcessDebugEvent(v8::Break,
                    Handle<JSObject>::cast(event_data),
                    auto_continue);
1855 1856 1857
}


1858
void Debug::OnBeforeCompile(Handle<Script> script) {
1859
  if (in_debug_scope() || ignore_events()) return;
1860

1861
  HandleScope scope(isolate_);
1862 1863
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;
1864 1865

  // Create the event data object.
1866
  Handle<Object> event_data;
1867
  // Bail out and don't call debugger if exception.
1868 1869
  if (!MakeCompileEvent(script, v8::BeforeCompile).ToHandle(&event_data))
    return;
1870

1871 1872 1873 1874
  // Process debug event.
  ProcessDebugEvent(v8::BeforeCompile,
                    Handle<JSObject>::cast(event_data),
                    true);
1875 1876 1877 1878
}


// Handle debugger actions when a new script is compiled.
1879
void Debug::OnAfterCompile(Handle<Script> script) {
1880 1881 1882 1883 1884 1885
  if (ignore_events()) return;

  if (in_debug_scope()) {
    ProcessCompileEventInDebugScope(v8::AfterCompile, script);
    return;
  }
1886

1887
  HandleScope scope(isolate_);
1888 1889
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;
1890 1891 1892

  // If debugging there might be script break points registered for this
  // script. Make sure that these break points are set.
1893 1894 1895
  Handle<Object> argv[] = {Script::GetWrapper(script)};
  if (CallFunction("UpdateScriptBreakPoints", arraysize(argv), argv)
          .is_null()) {
1896 1897 1898 1899
    return;
  }

  // Create the compile state object.
1900
  Handle<Object> event_data;
1901
  // Bail out and don't call debugger if exception.
1902
  if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return;
1903

1904
  // Process debug event.
1905
  ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
1906 1907 1908
}


1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927
void Debug::OnPromiseEvent(Handle<JSObject> data) {
  if (in_debug_scope() || ignore_events()) return;

  HandleScope scope(isolate_);
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;

  // Create the script collected state object.
  Handle<Object> event_data;
  // Bail out and don't call debugger if exception.
  if (!MakePromiseEvent(data).ToHandle(&event_data)) return;

  // Process debug event.
  ProcessDebugEvent(v8::PromiseEvent,
                    Handle<JSObject>::cast(event_data),
                    true);
}


1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946
void Debug::OnAsyncTaskEvent(Handle<JSObject> data) {
  if (in_debug_scope() || ignore_events()) return;

  HandleScope scope(isolate_);
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;

  // Create the script collected state object.
  Handle<Object> event_data;
  // Bail out and don't call debugger if exception.
  if (!MakeAsyncTaskEvent(data).ToHandle(&event_data)) return;

  // Process debug event.
  ProcessDebugEvent(v8::AsyncTaskEvent,
                    Handle<JSObject>::cast(event_data),
                    true);
}


1947 1948 1949
void Debug::ProcessDebugEvent(v8::DebugEvent event,
                              Handle<JSObject> event_data,
                              bool auto_continue) {
1950
  HandleScope scope(isolate_);
1951

1952
  // Create the execution state.
1953 1954
  Handle<Object> exec_state;
  // Bail out and don't call debugger if exception.
1955 1956
  if (!MakeExecutionState().ToHandle(&exec_state)) return;

1957 1958
  // First notify the message handler if any.
  if (message_handler_ != NULL) {
1959 1960 1961 1962
    NotifyMessageHandler(event,
                         Handle<JSObject>::cast(exec_state),
                         event_data,
                         auto_continue);
1963
  }
1964 1965 1966 1967 1968 1969
  // Notify registered debug event listener. This can be either a C or
  // a JavaScript function. Don't call event listener for v8::Break
  // here, if it's only a debug command -- they will be processed later.
  if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
    CallEventCallback(event, exec_state, event_data, NULL);
  }
1970 1971 1972
}


1973 1974 1975 1976
void Debug::CallEventCallback(v8::DebugEvent event,
                              Handle<Object> exec_state,
                              Handle<Object> event_data,
                              v8::Debug::ClientData* client_data) {
1977 1978
  bool previous = in_debug_event_listener_;
  in_debug_event_listener_ = true;
1979
  if (event_listener_->IsForeign()) {
1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
    // Invoke the C debug event listener.
    v8::Debug::EventCallback callback =
        FUNCTION_CAST<v8::Debug::EventCallback>(
            Handle<Foreign>::cast(event_listener_)->foreign_address());
    EventDetailsImpl event_details(event,
                                   Handle<JSObject>::cast(exec_state),
                                   Handle<JSObject>::cast(event_data),
                                   event_listener_data_,
                                   client_data);
    callback(event_details);
1990
    DCHECK(!isolate_->has_scheduled_exception());
1991
  } else {
1992
    // Invoke the JavaScript debug event listener.
1993
    DCHECK(event_listener_->IsJSFunction());
1994 1995 1996 1997
    Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
                              exec_state,
                              event_data,
                              event_listener_data_ };
1998
    Handle<JSReceiver> global(isolate_->global_proxy());
1999
    Execution::TryCall(Handle<JSFunction>::cast(event_listener_),
2000
                       global, arraysize(argv), argv);
2001
  }
2002
  in_debug_event_listener_ = previous;
2003 2004 2005
}


2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026
void Debug::ProcessCompileEventInDebugScope(v8::DebugEvent event,
                                            Handle<Script> script) {
  if (event_listener_.is_null()) return;

  SuppressDebug while_processing(this);
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;

  Handle<Object> event_data;
  // Bail out and don't call debugger if exception.
  if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;

  // Create the execution state.
  Handle<Object> exec_state;
  // Bail out and don't call debugger if exception.
  if (!MakeExecutionState().ToHandle(&exec_state)) return;

  CallEventCallback(event, exec_state, event_data, NULL);
}


2027
Handle<Context> Debug::GetDebugContext() {
2028
  if (!is_loaded()) return Handle<Context>();
2029
  DebugScope debug_scope(this);
2030
  if (debug_scope.failed()) return Handle<Context>();
2031
  // The global handle may be destroyed soon after.  Return it reboxed.
2032
  return handle(*debug_context(), isolate_);
2033 2034 2035
}


2036 2037 2038 2039
void Debug::NotifyMessageHandler(v8::DebugEvent event,
                                 Handle<JSObject> exec_state,
                                 Handle<JSObject> event_data,
                                 bool auto_continue) {
2040 2041 2042
  // Prevent other interrupts from triggering, for example API callbacks,
  // while dispatching message handler callbacks.
  PostponeInterruptsScope no_interrupts(isolate_);
2043
  DCHECK(is_active_);
2044
  HandleScope scope(isolate_);
2045
  // Process the individual events.
2046
  bool sendEventMessage = false;
2047 2048
  switch (event) {
    case v8::Break:
2049
      sendEventMessage = !auto_continue;
2050
      break;
2051
    case v8::NewFunction:
2052
    case v8::BeforeCompile:
2053 2054 2055
    case v8::CompileError:
    case v8::PromiseEvent:
    case v8::AsyncTaskEvent:
2056
      break;
2057
    case v8::Exception:
2058
    case v8::AfterCompile:
2059
      sendEventMessage = true;
2060 2061 2062
      break;
  }

2063 2064 2065
  // The debug command interrupt flag might have been set when the command was
  // added. It should be enough to clear the flag only once while we are in the
  // debugger.
2066
  DCHECK(in_debug_scope());
2067
  isolate_->stack_guard()->ClearDebugCommand();
2068 2069 2070 2071

  // Notify the debugger that a debug event has occurred unless auto continue is
  // active in which case no event is send.
  if (sendEventMessage) {
2072 2073 2074 2075 2076 2077
    MessageImpl message = MessageImpl::NewEvent(
        event,
        auto_continue,
        Handle<JSObject>::cast(exec_state),
        Handle<JSObject>::cast(event_data));
    InvokeMessageHandler(message);
2078
  }
2079 2080 2081 2082 2083

  // If auto continue don't make the event cause a break, but process messages
  // in the queue if any. For script collected events don't even process
  // messages in the queue as the execution state might not be what is expected
  // by the client.
2084
  if (auto_continue && !has_commands()) return;
2085

2086 2087 2088
  // DebugCommandProcessor goes here.
  bool running = auto_continue;

2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099
  Handle<Object> cmd_processor_ctor = Object::GetProperty(
      isolate_, exec_state, "debugCommandProcessor").ToHandleChecked();
  Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
  Handle<Object> cmd_processor = Execution::Call(
      isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked();
  Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
      Object::GetProperty(
          isolate_, cmd_processor, "processDebugRequest").ToHandleChecked());
  Handle<Object> is_running = Object::GetProperty(
      isolate_, cmd_processor, "isRunning").ToHandleChecked();

2100
  // Process requests from the debugger.
2101
  do {
2102
    // Wait for new command in the queue.
2103
    command_received_.Wait();
2104 2105

    // Get the command from the queue.
2106
    CommandMessage command = command_queue_.Get();
2107 2108
    isolate_->logger()->DebugTag(
        "Got request from command queue, in interactive loop.");
2109
    if (!is_active()) {
2110 2111
      // Delete command text and user data.
      command.Dispose();
2112 2113 2114
      return;
    }

2115 2116 2117 2118 2119 2120 2121 2122
    Vector<const uc16> command_text(
        const_cast<const uc16*>(command.text().start()),
        command.text().length());
    Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
        command_text).ToHandleChecked();
    Handle<Object> request_args[] = { request_text };
    Handle<Object> answer_value;
    Handle<String> answer;
2123 2124 2125 2126
    MaybeHandle<Object> maybe_exception;
    MaybeHandle<Object> maybe_result =
        Execution::TryCall(process_debug_request, cmd_processor, 1,
                           request_args, &maybe_exception);
2127 2128 2129 2130

    if (maybe_result.ToHandle(&answer_value)) {
      if (answer_value->IsUndefined()) {
        answer = isolate_->factory()->empty_string();
2131
      } else {
2132
        answer = Handle<String>::cast(answer_value);
2133
      }
2134 2135 2136

      // Log the JSON request/response.
      if (FLAG_trace_debug_json) {
2137 2138
        PrintF("%s\n", request_text->ToCString().get());
        PrintF("%s\n", answer->ToCString().get());
2139 2140
      }

2141 2142 2143
      Handle<Object> is_running_args[] = { answer };
      maybe_result = Execution::Call(
          isolate_, is_running, cmd_processor, 1, is_running_args);
2144 2145 2146
      Handle<Object> result;
      if (!maybe_result.ToHandle(&result)) break;
      running = result->IsTrue();
2147
    } else {
2148 2149 2150 2151 2152
      Handle<Object> exception;
      if (!maybe_exception.ToHandle(&exception)) break;
      Handle<Object> result;
      if (!Execution::ToString(isolate_, exception).ToHandle(&result)) break;
      answer = Handle<String>::cast(result);
2153 2154 2155
    }

    // Return the result.
2156
    MessageImpl message = MessageImpl::NewResponse(
2157
        event, running, exec_state, event_data, answer, command.client_data());
2158 2159
    InvokeMessageHandler(message);
    command.Dispose();
2160

2161
    // Return from debug event processing if either the VM is put into the
2162
    // running state (through a continue command) or auto continue is active
2163
    // and there are no more commands queued.
2164
  } while (!running || has_commands());
2165
  command_queue_.Clear();
2166 2167 2168
}


2169 2170
void Debug::SetEventListener(Handle<Object> callback,
                             Handle<Object> data) {
2171
  GlobalHandles* global_handles = isolate_->global_handles();
2172

2173 2174 2175 2176 2177
  // Remove existing entry.
  GlobalHandles::Destroy(event_listener_.location());
  event_listener_ = Handle<Object>();
  GlobalHandles::Destroy(event_listener_data_.location());
  event_listener_data_ = Handle<Object>();
2178

2179
  // Set new entry.
2180
  if (!callback->IsUndefined() && !callback->IsNull()) {
2181 2182 2183
    event_listener_ = global_handles->Create(*callback);
    if (data.is_null()) data = isolate_->factory()->undefined_value();
    event_listener_data_ = global_handles->Create(*data);
2184 2185
  }

2186
  UpdateState();
2187 2188 2189
}


2190
void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
2191
  message_handler_ = handler;
2192
  UpdateState();
2193
  if (handler == NULL && in_debug_scope()) {
2194 2195
    // Send an empty command to the debugger if in a break to make JavaScript
    // run again if the debugger is closed.
2196
    EnqueueCommandMessage(Vector<const uint16_t>::empty());
2197
  }
2198
}
2199

2200

2201 2202

void Debug::UpdateState() {
2203 2204
  bool is_active = message_handler_ != NULL || !event_listener_.is_null();
  if (is_active || in_debug_scope()) {
2205 2206
    // Note that the debug context could have already been loaded to
    // bootstrap test cases.
2207
    isolate_->compilation_cache()->Disable();
2208
    is_active = Load();
2209
  } else if (is_loaded()) {
2210
    isolate_->compilation_cache()->Enable();
2211
    Unload();
2212
  }
2213
  is_active_ = is_active;
2214 2215 2216 2217
}


// Calls the registered debug message handler. This callback is part of the
2218
// public API.
2219
void Debug::InvokeMessageHandler(MessageImpl message) {
2220
  if (message_handler_ != NULL) message_handler_(message);
2221 2222 2223
}


2224 2225 2226
// Puts a command coming from the public API on the queue.  Creates
// a copy of the command string managed by the debugger.  Up to this
// point, the command data was managed by the API client.  Called
2227
// by the API client thread.
2228 2229
void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
                                  v8::Debug::ClientData* client_data) {
2230
  // Need to cast away const.
2231
  CommandMessage message = CommandMessage::New(
2232
      Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
2233 2234
                       command.length()),
      client_data);
2235
  isolate_->logger()->DebugTag("Put command on command_queue.");
2236
  command_queue_.Put(message);
2237
  command_received_.Signal();
2238 2239

  // Set the debug command break flag to have the command processed.
2240
  if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
2241 2242 2243
}


2244
MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) {
2245 2246
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return isolate_->factory()->undefined_value();
2247 2248

  // Create the execution state.
2249
  Handle<Object> exec_state;
2250 2251 2252
  if (!MakeExecutionState().ToHandle(&exec_state)) {
    return isolate_->factory()->undefined_value();
  }
2253

2254
  Handle<Object> argv[] = { exec_state, data };
2255
  return Execution::Call(
2256
      isolate_,
2257
      fun,
2258
      Handle<Object>(debug_context()->global_proxy(), isolate_),
2259
      arraysize(argv),
2260
      argv);
2261 2262 2263
}


2264
void Debug::HandleDebugBreak() {
2265 2266 2267
  // Ignore debug break during bootstrapping.
  if (isolate_->bootstrapper()->IsActive()) return;
  // Just continue if breaks are disabled.
2268
  if (break_disabled()) return;
2269 2270 2271 2272 2273 2274 2275
  // Ignore debug break if debugger is not active.
  if (!is_active()) return;

  StackLimitCheck check(isolate_);
  if (check.HasOverflowed()) return;

  { JavaScriptFrameIterator it(isolate_);
2276
    DCHECK(!it.done());
2277 2278 2279
    Object* fun = it.frame()->function();
    if (fun && fun->IsJSFunction()) {
      // Don't stop in builtin functions.
2280
      if (!JSFunction::cast(fun)->IsSubjectToDebugging()) return;
2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303
      GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
      // Don't stop in debugger functions.
      if (IsDebugGlobal(global)) return;
    }
  }

  // Collect the break state before clearing the flags.
  bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
                            !isolate_->stack_guard()->CheckDebugBreak();

  isolate_->stack_guard()->ClearDebugBreak();

  ProcessDebugMessages(debug_command_only);
}


void Debug::ProcessDebugMessages(bool debug_command_only) {
  isolate_->stack_guard()->ClearDebugCommand();

  StackLimitCheck check(isolate_);
  if (check.HasOverflowed()) return;

  HandleScope scope(isolate_);
2304 2305
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;
2306 2307 2308 2309 2310 2311 2312

  // Notify the debug event listeners. Indicate auto continue if the break was
  // a debug command break.
  OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
}


2313 2314 2315 2316 2317 2318
DebugScope::DebugScope(Debug* debug)
    : debug_(debug),
      prev_(debug->debugger_entry()),
      save_(debug_->isolate_),
      no_termination_exceptons_(debug_->isolate_,
                                StackGuard::TERMINATE_EXECUTION) {
2319
  // Link recursive debugger entry.
2320 2321
  base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
                        reinterpret_cast<base::AtomicWord>(this));
2322 2323

  // Store the previous break id and frame id.
2324 2325
  break_id_ = debug_->break_id();
  break_frame_id_ = debug_->break_frame_id();
2326 2327 2328

  // Create the new break info. If there is no JavaScript frames there is no
  // break frame id.
2329
  JavaScriptFrameIterator it(isolate());
2330
  bool has_js_frames = !it.done();
2331 2332 2333
  debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
                                                        : StackFrame::NO_ID;
  debug_->SetNextBreakId();
2334

2335
  debug_->UpdateState();
2336
  // Make sure that debugger is loaded and enter the debugger context.
2337
  // The previous context is kept in save_.
2338 2339
  failed_ = !debug_->is_loaded();
  if (!failed_) isolate()->set_context(*debug->debug_context());
2340 2341 2342 2343
}



2344 2345
DebugScope::~DebugScope() {
  if (!failed_ && prev_ == NULL) {
2346 2347 2348 2349
    // Clear mirror cache when leaving the debugger. Skip this if there is a
    // pending exception as clearing the mirror cache calls back into
    // JavaScript. This can happen if the v8::Debug::Call is used in which
    // case the exception should end up in the calling code.
2350
    if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
2351 2352 2353

    // If there are commands in the queue when leaving the debugger request
    // that these commands are processed.
2354
    if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
2355 2356
  }

2357
  // Leaving this debugger entry.
2358 2359
  base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
                        reinterpret_cast<base::AtomicWord>(prev_));
2360 2361 2362 2363

  // Restore to the previous break state.
  debug_->thread_local_.break_frame_id_ = break_frame_id_;
  debug_->thread_local_.break_id_ = break_id_;
2364

2365
  debug_->UpdateState();
2366 2367 2368
}


2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426
MessageImpl MessageImpl::NewEvent(DebugEvent event,
                                  bool running,
                                  Handle<JSObject> exec_state,
                                  Handle<JSObject> event_data) {
  MessageImpl message(true, event, running,
                      exec_state, event_data, Handle<String>(), NULL);
  return message;
}


MessageImpl MessageImpl::NewResponse(DebugEvent event,
                                     bool running,
                                     Handle<JSObject> exec_state,
                                     Handle<JSObject> event_data,
                                     Handle<String> response_json,
                                     v8::Debug::ClientData* client_data) {
  MessageImpl message(false, event, running,
                      exec_state, event_data, response_json, client_data);
  return message;
}


MessageImpl::MessageImpl(bool is_event,
                         DebugEvent event,
                         bool running,
                         Handle<JSObject> exec_state,
                         Handle<JSObject> event_data,
                         Handle<String> response_json,
                         v8::Debug::ClientData* client_data)
    : is_event_(is_event),
      event_(event),
      running_(running),
      exec_state_(exec_state),
      event_data_(event_data),
      response_json_(response_json),
      client_data_(client_data) {}


bool MessageImpl::IsEvent() const {
  return is_event_;
}


bool MessageImpl::IsResponse() const {
  return !is_event_;
}


DebugEvent MessageImpl::GetEvent() const {
  return event_;
}


bool MessageImpl::WillStartRunning() const {
  return running_;
}


2427
v8::Local<v8::Object> MessageImpl::GetExecutionState() const {
2428 2429 2430 2431
  return v8::Utils::ToLocal(exec_state_);
}


2432 2433 2434 2435 2436
v8::Isolate* MessageImpl::GetIsolate() const {
  return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
}


2437
v8::Local<v8::Object> MessageImpl::GetEventData() const {
2438 2439 2440 2441
  return v8::Utils::ToLocal(event_data_);
}


2442
v8::Local<v8::String> MessageImpl::GetJSON() const {
2443 2444
  Isolate* isolate = event_data_->GetIsolate();
  v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
2445 2446 2447

  if (IsEvent()) {
    // Call toJSONProtocol on the debug event object.
2448 2449
    Handle<Object> fun = Object::GetProperty(
        isolate, event_data_, "toJSONProtocol").ToHandleChecked();
2450
    if (!fun->IsJSFunction()) {
2451
      return v8::Local<v8::String>();
2452
    }
2453 2454 2455 2456 2457

    MaybeHandle<Object> maybe_json =
        Execution::TryCall(Handle<JSFunction>::cast(fun), event_data_, 0, NULL);
    Handle<Object> json;
    if (!maybe_json.ToHandle(&json) || !json->IsString()) {
2458
      return v8::Local<v8::String>();
2459
    }
2460
    return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
2461 2462 2463 2464 2465 2466
  } else {
    return v8::Utils::ToLocal(response_json_);
  }
}


2467
v8::Local<v8::Context> MessageImpl::GetEventContext() const {
2468
  Isolate* isolate = event_data_->GetIsolate();
2469
  v8::Local<v8::Context> context = GetDebugEventContext(isolate);
2470
  // Isolate::context() may be NULL when "script collected" event occurs.
2471
  DCHECK(!context.IsEmpty());
2472
  return context;
2473 2474 2475 2476 2477 2478 2479 2480
}


v8::Debug::ClientData* MessageImpl::GetClientData() const {
  return client_data_;
}


2481 2482 2483
EventDetailsImpl::EventDetailsImpl(DebugEvent event,
                                   Handle<JSObject> exec_state,
                                   Handle<JSObject> event_data,
2484 2485
                                   Handle<Object> callback_data,
                                   v8::Debug::ClientData* client_data)
2486 2487 2488
    : event_(event),
      exec_state_(exec_state),
      event_data_(event_data),
2489 2490
      callback_data_(callback_data),
      client_data_(client_data) {}
2491 2492 2493 2494 2495 2496 2497


DebugEvent EventDetailsImpl::GetEvent() const {
  return event_;
}


2498
v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const {
2499 2500 2501 2502
  return v8::Utils::ToLocal(exec_state_);
}


2503
v8::Local<v8::Object> EventDetailsImpl::GetEventData() const {
2504 2505 2506 2507
  return v8::Utils::ToLocal(event_data_);
}


2508
v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const {
2509
  return GetDebugEventContext(exec_state_->GetIsolate());
2510 2511 2512
}


2513
v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const {
2514 2515 2516 2517
  return v8::Utils::ToLocal(callback_data_);
}


2518 2519 2520 2521 2522
v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
  return client_data_;
}


2523 2524
CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
                                   client_data_(NULL) {
2525 2526 2527
}


2528 2529
CommandMessage::CommandMessage(const Vector<uint16_t>& text,
                               v8::Debug::ClientData* data)
2530
    : text_(text),
2531
      client_data_(data) {
2532 2533 2534
}


2535
void CommandMessage::Dispose() {
2536 2537 2538 2539 2540 2541
  text_.Dispose();
  delete client_data_;
  client_data_ = NULL;
}


2542 2543 2544
CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
                                   v8::Debug::ClientData* data) {
  return CommandMessage(command.Clone(), data);
2545 2546 2547
}


2548 2549 2550
CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
                                                     size_(size) {
  messages_ = NewArray<CommandMessage>(size);
2551 2552 2553
}


2554
CommandMessageQueue::~CommandMessageQueue() {
2555
  while (!IsEmpty()) Get().Dispose();
2556 2557 2558 2559
  DeleteArray(messages_);
}


2560
CommandMessage CommandMessageQueue::Get() {
2561
  DCHECK(!IsEmpty());
2562 2563 2564 2565 2566 2567
  int result = start_;
  start_ = (start_ + 1) % size_;
  return messages_[result];
}


2568
void CommandMessageQueue::Put(const CommandMessage& message) {
2569 2570 2571 2572 2573 2574 2575 2576
  if ((end_ + 1) % size_ == start_) {
    Expand();
  }
  messages_[end_] = message;
  end_ = (end_ + 1) % size_;
}


2577 2578
void CommandMessageQueue::Expand() {
  CommandMessageQueue new_queue(size_ * 2);
2579 2580
  while (!IsEmpty()) {
    new_queue.Put(Get());
2581
  }
2582
  CommandMessage* array_to_free = messages_;
2583 2584
  *this = new_queue;
  new_queue.messages_ = array_to_free;
2585 2586
  // Make the new_queue empty so that it doesn't call Dispose on any messages.
  new_queue.start_ = new_queue.end_;
2587 2588 2589 2590
  // Automatic destructor called on new_queue, freeing array_to_free.
}


2591
LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
2592
    : logger_(logger), queue_(size) {}
2593 2594


2595
bool LockingCommandMessageQueue::IsEmpty() const {
2596
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
2597
  return queue_.IsEmpty();
2598 2599
}

2600

2601
CommandMessage LockingCommandMessageQueue::Get() {
2602
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
2603
  CommandMessage result = queue_.Get();
2604
  logger_->DebugEvent("Get", result.text());
2605 2606 2607 2608
  return result;
}


2609
void LockingCommandMessageQueue::Put(const CommandMessage& message) {
2610
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
2611
  queue_.Put(message);
2612
  logger_->DebugEvent("Put", message.text());
2613 2614 2615
}


2616
void LockingCommandMessageQueue::Clear() {
2617
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
2618 2619 2620
  queue_.Clear();
}

2621 2622
}  // namespace internal
}  // namespace v8