v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
debug.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "api.h"
31 #include "arguments.h"
32 #include "bootstrapper.h"
33 #include "code-stubs.h"
34 #include "codegen.h"
35 #include "compilation-cache.h"
36 #include "compiler.h"
37 #include "debug.h"
38 #include "deoptimizer.h"
39 #include "execution.h"
40 #include "full-codegen.h"
41 #include "global-handles.h"
42 #include "ic.h"
43 #include "ic-inl.h"
44 #include "isolate-inl.h"
45 #include "list.h"
46 #include "messages.h"
47 #include "natives.h"
48 #include "stub-cache.h"
49 #include "log.h"
50 
51 #include "../include/v8-debug.h"
52 
53 namespace v8 {
54 namespace internal {
55 
56 #ifdef ENABLE_DEBUGGER_SUPPORT
57 
58 
59 Debug::Debug(Isolate* isolate)
60  : has_break_points_(false),
61  script_cache_(NULL),
62  debug_info_list_(NULL),
63  disable_break_(false),
64  break_on_exception_(false),
65  break_on_uncaught_exception_(false),
66  debug_break_return_(NULL),
67  debug_break_slot_(NULL),
68  isolate_(isolate) {
69  memset(registers_, 0, sizeof(JSCallerSavedBuffer));
70 }
71 
72 
73 Debug::~Debug() {
74 }
75 
76 
77 static void PrintLn(v8::Local<v8::Value> value) {
78  v8::Local<v8::String> s = value->ToString();
79  ScopedVector<char> data(s->Utf8Length() + 1);
80  if (data.start() == NULL) {
81  V8::FatalProcessOutOfMemory("PrintLn");
82  return;
83  }
84  s->WriteUtf8(data.start());
85  PrintF("%s\n", data.start());
86 }
87 
88 
89 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
90  Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
91  // Isolate::context() may have been NULL when "script collected" event
92  // occured.
93  if (context.is_null()) return v8::Local<v8::Context>();
94  Handle<Context> native_context(context->native_context());
95  return v8::Utils::ToLocal(native_context);
96 }
97 
98 
99 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
100  BreakLocatorType type) {
101  debug_info_ = debug_info;
102  type_ = type;
103  reloc_iterator_ = NULL;
104  reloc_iterator_original_ = NULL;
105  Reset(); // Initialize the rest of the member variables.
106 }
107 
108 
109 BreakLocationIterator::~BreakLocationIterator() {
110  ASSERT(reloc_iterator_ != NULL);
111  ASSERT(reloc_iterator_original_ != NULL);
112  delete reloc_iterator_;
113  delete reloc_iterator_original_;
114 }
115 
116 
117 void BreakLocationIterator::Next() {
119  ASSERT(!RinfoDone());
120 
121  // Iterate through reloc info for code and original code stopping at each
122  // breakable code target.
123  bool first = break_point_ == -1;
124  while (!RinfoDone()) {
125  if (!first) RinfoNext();
126  first = false;
127  if (RinfoDone()) return;
128 
129  // Whenever a statement position or (plain) position is passed update the
130  // current value of these.
131  if (RelocInfo::IsPosition(rmode())) {
132  if (RelocInfo::IsStatementPosition(rmode())) {
133  statement_position_ = static_cast<int>(
134  rinfo()->data() - debug_info_->shared()->start_position());
135  }
136  // Always update the position as we don't want that to be before the
137  // statement position.
138  position_ = static_cast<int>(
139  rinfo()->data() - debug_info_->shared()->start_position());
140  ASSERT(position_ >= 0);
141  ASSERT(statement_position_ >= 0);
142  }
143 
144  if (IsDebugBreakSlot()) {
145  // There is always a possible break point at a debug break slot.
146  break_point_++;
147  return;
148  } else if (RelocInfo::IsCodeTarget(rmode())) {
149  // Check for breakable code target. Look in the original code as setting
150  // break points can cause the code targets in the running (debugged) code
151  // to be of a different kind than in the original code.
152  Address target = original_rinfo()->target_address();
153  Code* code = Code::GetCodeFromTargetAddress(target);
154  if ((code->is_inline_cache_stub() &&
155  !code->is_binary_op_stub() &&
156  !code->is_compare_ic_stub() &&
157  !code->is_to_boolean_ic_stub()) ||
158  RelocInfo::IsConstructCall(rmode())) {
159  break_point_++;
160  return;
161  }
162  if (code->kind() == Code::STUB) {
163  if (IsDebuggerStatement()) {
164  break_point_++;
165  return;
166  }
167  if (type_ == ALL_BREAK_LOCATIONS) {
168  if (Debug::IsBreakStub(code)) {
169  break_point_++;
170  return;
171  }
172  } else {
173  ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
174  if (Debug::IsSourceBreakStub(code)) {
175  break_point_++;
176  return;
177  }
178  }
179  }
180  }
181 
182  // Check for break at return.
183  if (RelocInfo::IsJSReturn(rmode())) {
184  // Set the positions to the end of the function.
185  if (debug_info_->shared()->HasSourceCode()) {
186  position_ = debug_info_->shared()->end_position() -
187  debug_info_->shared()->start_position() - 1;
188  } else {
189  position_ = 0;
190  }
191  statement_position_ = position_;
192  break_point_++;
193  return;
194  }
195  }
196 }
197 
198 
199 void BreakLocationIterator::Next(int count) {
200  while (count > 0) {
201  Next();
202  count--;
203  }
204 }
205 
206 
207 // Find the break point at the supplied address, or the closest one before
208 // the address.
209 void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
210  // Run through all break points to locate the one closest to the address.
211  int closest_break_point = 0;
212  int distance = kMaxInt;
213  while (!Done()) {
214  // Check if this break point is closer that what was previously found.
215  if (this->pc() <= pc && pc - this->pc() < distance) {
216  closest_break_point = break_point();
217  distance = static_cast<int>(pc - this->pc());
218  // Check whether we can't get any closer.
219  if (distance == 0) break;
220  }
221  Next();
222  }
223 
224  // Move to the break point found.
225  Reset();
226  Next(closest_break_point);
227 }
228 
229 
230 // Find the break point closest to the supplied source position.
231 void BreakLocationIterator::FindBreakLocationFromPosition(int position,
232  BreakPositionAlignment alignment) {
233  // Run through all break points to locate the one closest to the source
234  // position.
235  int closest_break_point = 0;
236  int distance = kMaxInt;
237 
238  while (!Done()) {
239  int next_position;
240  switch (alignment) {
241  case STATEMENT_ALIGNED:
242  next_position = this->statement_position();
243  break;
244  case BREAK_POSITION_ALIGNED:
245  next_position = this->position();
246  break;
247  default:
248  UNREACHABLE();
249  next_position = this->statement_position();
250  }
251  // Check if this break point is closer that what was previously found.
252  if (position <= next_position && next_position - position < distance) {
253  closest_break_point = break_point();
254  distance = next_position - position;
255  // Check whether we can't get any closer.
256  if (distance == 0) break;
257  }
258  Next();
259  }
260 
261  // Move to the break point found.
262  Reset();
263  Next(closest_break_point);
264 }
265 
266 
267 void BreakLocationIterator::Reset() {
268  // Create relocation iterators for the two code objects.
269  if (reloc_iterator_ != NULL) delete reloc_iterator_;
270  if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
271  reloc_iterator_ = new RelocIterator(
272  debug_info_->code(),
273  ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
274  reloc_iterator_original_ = new RelocIterator(
275  debug_info_->original_code(),
276  ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
277 
278  // Position at the first break point.
279  break_point_ = -1;
280  position_ = 1;
281  statement_position_ = 1;
282  Next();
283 }
284 
285 
286 bool BreakLocationIterator::Done() const {
287  return RinfoDone();
288 }
289 
290 
291 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
292  // If there is not already a real break point here patch code with debug
293  // break.
294  if (!HasBreakPoint()) {
295  SetDebugBreak();
296  }
297  ASSERT(IsDebugBreak() || IsDebuggerStatement());
298  // Set the break point information.
299  DebugInfo::SetBreakPoint(debug_info_, code_position(),
300  position(), statement_position(),
301  break_point_object);
302 }
303 
304 
305 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
306  // Clear the break point information.
307  DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
308  // If there are no more break points here remove the debug break.
309  if (!HasBreakPoint()) {
310  ClearDebugBreak();
311  ASSERT(!IsDebugBreak());
312  }
313 }
314 
315 
316 void BreakLocationIterator::SetOneShot() {
317  // Debugger statement always calls debugger. No need to modify it.
318  if (IsDebuggerStatement()) {
319  return;
320  }
321 
322  // If there is a real break point here no more to do.
323  if (HasBreakPoint()) {
324  ASSERT(IsDebugBreak());
325  return;
326  }
327 
328  // Patch code with debug break.
329  SetDebugBreak();
330 }
331 
332 
333 void BreakLocationIterator::ClearOneShot() {
334  // Debugger statement always calls debugger. No need to modify it.
335  if (IsDebuggerStatement()) {
336  return;
337  }
338 
339  // If there is a real break point here no more to do.
340  if (HasBreakPoint()) {
341  ASSERT(IsDebugBreak());
342  return;
343  }
344 
345  // Patch code removing debug break.
346  ClearDebugBreak();
347  ASSERT(!IsDebugBreak());
348 }
349 
350 
351 void BreakLocationIterator::SetDebugBreak() {
352  // Debugger statement always calls debugger. No need to modify it.
353  if (IsDebuggerStatement()) {
354  return;
355  }
356 
357  // If there is already a break point here just return. This might happen if
358  // the same code is flooded with break points twice. Flooding the same
359  // function twice might happen when stepping in a function with an exception
360  // handler as the handler and the function is the same.
361  if (IsDebugBreak()) {
362  return;
363  }
364 
365  if (RelocInfo::IsJSReturn(rmode())) {
366  // Patch the frame exit code with a break point.
367  SetDebugBreakAtReturn();
368  } else if (IsDebugBreakSlot()) {
369  // Patch the code in the break slot.
370  SetDebugBreakAtSlot();
371  } else {
372  // Patch the IC call.
373  SetDebugBreakAtIC();
374  }
375  ASSERT(IsDebugBreak());
376 }
377 
378 
379 void BreakLocationIterator::ClearDebugBreak() {
380  // Debugger statement always calls debugger. No need to modify it.
381  if (IsDebuggerStatement()) {
382  return;
383  }
384 
385  if (RelocInfo::IsJSReturn(rmode())) {
386  // Restore the frame exit code.
387  ClearDebugBreakAtReturn();
388  } else if (IsDebugBreakSlot()) {
389  // Restore the code in the break slot.
390  ClearDebugBreakAtSlot();
391  } else {
392  // Patch the IC call.
393  ClearDebugBreakAtIC();
394  }
395  ASSERT(!IsDebugBreak());
396 }
397 
398 
399 bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
400  if (RelocInfo::IsConstructCall(original_rmode())) {
401  return true;
402  } else if (RelocInfo::IsCodeTarget(rmode())) {
403  HandleScope scope(debug_info_->GetIsolate());
404  Address target = original_rinfo()->target_address();
405  Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
406  if (target_code->kind() == Code::STUB) {
407  return target_code->major_key() == CodeStub::CallFunction;
408  }
409  }
410  return false;
411 }
412 
413 
414 void BreakLocationIterator::PrepareStepIn(Isolate* isolate) {
415 #ifdef DEBUG
416  HandleScope scope(isolate);
417  // Step in can only be prepared if currently positioned on an IC call,
418  // construct call or CallFunction stub call.
419  Address target = rinfo()->target_address();
420  Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
421  // All the following stuff is needed only for assertion checks so the code
422  // is wrapped in ifdef.
423  Handle<Code> maybe_call_function_stub = target_code;
424  if (IsDebugBreak()) {
425  Address original_target = original_rinfo()->target_address();
426  maybe_call_function_stub =
427  Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
428  }
429  bool is_call_function_stub =
430  (maybe_call_function_stub->kind() == Code::STUB &&
431  maybe_call_function_stub->major_key() == CodeStub::CallFunction);
432 
433  // Step in through construct call requires no changes to the running code.
434  // Step in through getters/setters should already be prepared as well
435  // because caller of this function (Debug::PrepareStep) is expected to
436  // flood the top frame's function with one shot breakpoints.
437  // Step in through CallFunction stub should also be prepared by caller of
438  // this function (Debug::PrepareStep) which should flood target function
439  // with breakpoints.
440  ASSERT(RelocInfo::IsConstructCall(rmode()) ||
441  target_code->is_inline_cache_stub() ||
442  is_call_function_stub);
443 #endif
444 }
445 
446 
447 // Check whether the break point is at a position which will exit the function.
448 bool BreakLocationIterator::IsExit() const {
449  return (RelocInfo::IsJSReturn(rmode()));
450 }
451 
452 
453 bool BreakLocationIterator::HasBreakPoint() {
454  return debug_info_->HasBreakPoint(code_position());
455 }
456 
457 
458 // Check whether there is a debug break at the current position.
459 bool BreakLocationIterator::IsDebugBreak() {
460  if (RelocInfo::IsJSReturn(rmode())) {
461  return IsDebugBreakAtReturn();
462  } else if (IsDebugBreakSlot()) {
463  return IsDebugBreakAtSlot();
464  } else {
465  return Debug::IsDebugBreak(rinfo()->target_address());
466  }
467 }
468 
469 
470 void BreakLocationIterator::SetDebugBreakAtIC() {
471  // Patch the original code with the current address as the current address
472  // might have changed by the inline caching since the code was copied.
473  original_rinfo()->set_target_address(rinfo()->target_address());
474 
475  RelocInfo::Mode mode = rmode();
476  if (RelocInfo::IsCodeTarget(mode)) {
477  Address target = rinfo()->target_address();
478  Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
479 
480  // Patch the code to invoke the builtin debug break function matching the
481  // calling convention used by the call site.
482  Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode));
483  rinfo()->set_target_address(dbgbrk_code->entry());
484  }
485 }
486 
487 
488 void BreakLocationIterator::ClearDebugBreakAtIC() {
489  // Patch the code to the original invoke.
490  rinfo()->set_target_address(original_rinfo()->target_address());
491 }
492 
493 
494 bool BreakLocationIterator::IsDebuggerStatement() {
495  return RelocInfo::DEBUG_BREAK == rmode();
496 }
497 
498 
499 bool BreakLocationIterator::IsDebugBreakSlot() {
500  return RelocInfo::DEBUG_BREAK_SLOT == rmode();
501 }
502 
503 
504 Object* BreakLocationIterator::BreakPointObjects() {
505  return debug_info_->GetBreakPointObjects(code_position());
506 }
507 
508 
509 // Clear out all the debug break code. This is ONLY supposed to be used when
510 // shutting down the debugger as it will leave the break point information in
511 // DebugInfo even though the code is patched back to the non break point state.
512 void BreakLocationIterator::ClearAllDebugBreak() {
513  while (!Done()) {
514  ClearDebugBreak();
515  Next();
516  }
517 }
518 
519 
520 bool BreakLocationIterator::RinfoDone() const {
521  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
522  return reloc_iterator_->done();
523 }
524 
525 
526 void BreakLocationIterator::RinfoNext() {
527  reloc_iterator_->next();
528  reloc_iterator_original_->next();
529 #ifdef DEBUG
530  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
531  if (!reloc_iterator_->done()) {
532  ASSERT(rmode() == original_rmode());
533  }
534 #endif
535 }
536 
537 
538 // Threading support.
539 void Debug::ThreadInit() {
540  thread_local_.break_count_ = 0;
541  thread_local_.break_id_ = 0;
542  thread_local_.break_frame_id_ = StackFrame::NO_ID;
543  thread_local_.last_step_action_ = StepNone;
544  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
545  thread_local_.step_count_ = 0;
546  thread_local_.last_fp_ = 0;
547  thread_local_.queued_step_count_ = 0;
548  thread_local_.step_into_fp_ = 0;
549  thread_local_.step_out_fp_ = 0;
550  thread_local_.after_break_target_ = 0;
551  // TODO(isolates): frames_are_dropped_?
552  thread_local_.debugger_entry_ = NULL;
553  thread_local_.pending_interrupts_ = 0;
554  thread_local_.restarter_frame_function_pointer_ = NULL;
555 }
556 
557 
558 char* Debug::ArchiveDebug(char* storage) {
559  char* to = storage;
560  OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
561  to += sizeof(ThreadLocal);
562  OS::MemCopy(to, reinterpret_cast<char*>(&registers_), sizeof(registers_));
563  ThreadInit();
564  ASSERT(to <= storage + ArchiveSpacePerThread());
565  return storage + ArchiveSpacePerThread();
566 }
567 
568 
569 char* Debug::RestoreDebug(char* storage) {
570  char* from = storage;
571  OS::MemCopy(
572  reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
573  from += sizeof(ThreadLocal);
574  OS::MemCopy(reinterpret_cast<char*>(&registers_), from, sizeof(registers_));
575  ASSERT(from <= storage + ArchiveSpacePerThread());
576  return storage + ArchiveSpacePerThread();
577 }
578 
579 
580 int Debug::ArchiveSpacePerThread() {
581  return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer);
582 }
583 
584 
585 // Frame structure (conforms InternalFrame structure):
586 // -- code
587 // -- SMI maker
588 // -- function (slot is called "context")
589 // -- frame base
590 Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
591  Handle<Code> code) {
592  ASSERT(bottom_js_frame->is_java_script());
593 
594  Address fp = bottom_js_frame->fp();
595 
596  // Move function pointer into "context" slot.
599 
603 
604  return reinterpret_cast<Object**>(&Memory::Object_at(
606 }
607 
608 const int Debug::kFrameDropperFrameSize = 4;
609 
610 
611 void ScriptCache::Add(Handle<Script> script) {
612  GlobalHandles* global_handles = isolate_->global_handles();
613  // Create an entry in the hash map for the script.
614  int id = script->id()->value();
615  HashMap::Entry* entry =
616  HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
617  if (entry->value != NULL) {
618  ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
619  return;
620  }
621  // Globalize the script object, make it weak and use the location of the
622  // global handle as the value in the hash map.
623  Handle<Script> script_ =
624  Handle<Script>::cast(global_handles->Create(*script));
625  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
626  this,
627  ScriptCache::HandleWeakScript);
628  entry->value = script_.location();
629 }
630 
631 
632 Handle<FixedArray> ScriptCache::GetScripts() {
633  Factory* factory = isolate_->factory();
634  Handle<FixedArray> instances = factory->NewFixedArray(occupancy());
635  int count = 0;
636  for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
637  ASSERT(entry->value != NULL);
638  if (entry->value != NULL) {
639  instances->set(count, *reinterpret_cast<Script**>(entry->value));
640  count++;
641  }
642  }
643  return instances;
644 }
645 
646 
647 void ScriptCache::ProcessCollectedScripts() {
648  Debugger* debugger = isolate_->debugger();
649  for (int i = 0; i < collected_scripts_.length(); i++) {
650  debugger->OnScriptCollected(collected_scripts_[i]);
651  }
652  collected_scripts_.Clear();
653 }
654 
655 
656 void ScriptCache::Clear() {
657  // Iterate the script cache to get rid of all the weak handles.
658  for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
659  ASSERT(entry != NULL);
660  Object** location = reinterpret_cast<Object**>(entry->value);
661  ASSERT((*location)->IsScript());
663  GlobalHandles::Destroy(location);
664  }
665  // Clear the content of the hash map.
666  HashMap::Clear();
667 }
668 
669 
670 void ScriptCache::HandleWeakScript(
672  // Retrieve the script identifier.
673  Handle<Object> object = Utils::OpenHandle(*data.GetValue());
674  int id = Handle<Script>::cast(object)->id()->value();
675  void* key = reinterpret_cast<void*>(id);
676  uint32_t hash = Hash(id);
677 
678  // Remove the corresponding entry from the cache.
679  ScriptCache* script_cache =
680  reinterpret_cast<ScriptCache*>(data.GetParameter());
681  HashMap::Entry* entry = script_cache->Lookup(key, hash, false);
682  Object** location = reinterpret_cast<Object**>(entry->value);
683  script_cache->Remove(key, hash);
684  script_cache->collected_scripts_.Add(id);
685 
686  // Clear the weak handle.
687  GlobalHandles::Destroy(location);
688 }
689 
690 
691 void Debug::SetUp(bool create_heap_objects) {
692  ThreadInit();
693  if (create_heap_objects) {
694  // Get code to handle debug break on return.
695  debug_break_return_ =
696  isolate_->builtins()->builtin(Builtins::kReturn_DebugBreak);
697  ASSERT(debug_break_return_->IsCode());
698  // Get code to handle debug break in debug break slots.
699  debug_break_slot_ =
700  isolate_->builtins()->builtin(Builtins::kSlot_DebugBreak);
701  ASSERT(debug_break_slot_->IsCode());
702  }
703 }
704 
705 
706 void Debug::HandleWeakDebugInfo(
708  Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug();
709  DebugInfoListNode* node =
710  reinterpret_cast<DebugInfoListNode*>(data.GetParameter());
711  // We need to clear all breakpoints associated with the function to restore
712  // original code and avoid patching the code twice later because
713  // the function will live in the heap until next gc, and can be found by
714  // Debug::FindSharedFunctionInfoInScript.
715  BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
716  it.ClearAllDebugBreak();
717  debug->RemoveDebugInfo(node->debug_info());
718 #ifdef DEBUG
719  for (DebugInfoListNode* n = debug->debug_info_list_;
720  n != NULL;
721  n = n->next()) {
722  ASSERT(n != node);
723  }
724 #endif
725 }
726 
727 
728 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
729  // Globalize the request debug info object and make it weak.
730  GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
731  debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info));
732  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
733  this,
734  Debug::HandleWeakDebugInfo);
735 }
736 
737 
738 DebugInfoListNode::~DebugInfoListNode() {
739  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
740 }
741 
742 
743 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
744  Factory* factory = isolate->factory();
745  HandleScope scope(isolate);
746 
747  // Bail out if the index is invalid.
748  if (index == -1) {
749  return false;
750  }
751 
752  // Find source and name for the requested script.
753  Handle<String> source_code =
754  isolate->bootstrapper()->NativesSourceLookup(index);
755  Vector<const char> name = Natives::GetScriptName(index);
756  Handle<String> script_name = factory->NewStringFromAscii(name);
757  ASSERT(!script_name.is_null());
758  Handle<Context> context = isolate->native_context();
759 
760  // Compile the script.
761  Handle<SharedFunctionInfo> function_info;
762  function_info = Compiler::CompileScript(source_code,
763  script_name, 0, 0,
764  false,
765  context,
767  NATIVES_CODE);
768 
769  // Silently ignore stack overflows during compilation.
770  if (function_info.is_null()) {
771  ASSERT(isolate->has_pending_exception());
772  isolate->clear_pending_exception();
773  return false;
774  }
775 
776  // Execute the shared function in the debugger context.
777  bool caught_exception;
778  Handle<JSFunction> function =
779  factory->NewFunctionFromSharedFunctionInfo(function_info, context);
780 
781  Handle<Object> exception =
782  Execution::TryCall(function,
783  Handle<Object>(context->global_object(), isolate),
784  0,
785  NULL,
786  &caught_exception);
787 
788  // Check for caught exceptions.
789  if (caught_exception) {
790  ASSERT(!isolate->has_pending_exception());
791  MessageLocation computed_location;
792  isolate->ComputeLocation(&computed_location);
794  isolate, "error_loading_debugger", &computed_location,
795  Vector<Handle<Object> >::empty(), Handle<JSArray>());
796  ASSERT(!isolate->has_pending_exception());
797  if (!exception.is_null()) {
798  isolate->set_pending_exception(*exception);
799  MessageHandler::ReportMessage(isolate, NULL, message);
800  isolate->clear_pending_exception();
801  }
802  return false;
803  }
804 
805  // Mark this script as native and return successfully.
806  Handle<Script> script(Script::cast(function->shared()->script()));
807  script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
808  return true;
809 }
810 
811 
812 bool Debug::Load() {
813  // Return if debugger is already loaded.
814  if (IsLoaded()) return true;
815 
816  Debugger* debugger = isolate_->debugger();
817 
818  // Bail out if we're already in the process of compiling the native
819  // JavaScript source code for the debugger.
820  if (debugger->compiling_natives() ||
821  debugger->is_loading_debugger())
822  return false;
823  debugger->set_loading_debugger(true);
824 
825  // Disable breakpoints and interrupts while compiling and running the
826  // debugger scripts including the context creation code.
827  DisableBreak disable(isolate_, true);
828  PostponeInterruptsScope postpone(isolate_);
829 
830  // Create the debugger context.
831  HandleScope scope(isolate_);
832  ExtensionConfiguration no_extensions;
833  Handle<Context> context =
834  isolate_->bootstrapper()->CreateEnvironment(
835  Handle<Object>::null(),
837  &no_extensions);
838 
839  // Fail if no context could be created.
840  if (context.is_null()) return false;
841 
842  // Use the debugger context.
843  SaveContext save(isolate_);
844  isolate_->set_context(*context);
845 
846  // Expose the builtins object in the debugger context.
847  Handle<String> key = isolate_->factory()->InternalizeOneByteString(
848  STATIC_ASCII_VECTOR("builtins"));
849  Handle<GlobalObject> global = Handle<GlobalObject>(context->global_object());
851  isolate_,
853  key,
854  Handle<Object>(global->builtins(), isolate_),
855  NONE,
856  SLOPPY),
857  false);
858 
859  // Compile the JavaScript for the debugger in the debugger context.
860  debugger->set_compiling_natives(true);
861  bool caught_exception =
862  !CompileDebuggerScript(isolate_, Natives::GetIndex("mirror")) ||
863  !CompileDebuggerScript(isolate_, Natives::GetIndex("debug"));
864 
865  if (FLAG_enable_liveedit) {
866  caught_exception = caught_exception ||
867  !CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit"));
868  }
869 
870  debugger->set_compiling_natives(false);
871 
872  // Make sure we mark the debugger as not loading before we might
873  // return.
874  debugger->set_loading_debugger(false);
875 
876  // Check for caught exceptions.
877  if (caught_exception) return false;
878 
879  // Debugger loaded, create debugger context global handle.
880  debug_context_ = Handle<Context>::cast(
881  isolate_->global_handles()->Create(*context));
882 
883  return true;
884 }
885 
886 
887 void Debug::Unload() {
888  // Return debugger is not loaded.
889  if (!IsLoaded()) {
890  return;
891  }
892 
893  // Clear the script cache.
894  DestroyScriptCache();
895 
896  // Clear debugger context global handle.
897  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
898  debug_context_ = Handle<Context>();
899 }
900 
901 
902 // Set the flag indicating that preemption happened during debugging.
903 void Debug::PreemptionWhileInDebugger() {
904  ASSERT(InDebugger());
905  Debug::set_interrupts_pending(PREEMPT);
906 }
907 
908 
909 void Debug::Iterate(ObjectVisitor* v) {
910  v->VisitPointer(BitCast<Object**>(&(debug_break_return_)));
911  v->VisitPointer(BitCast<Object**>(&(debug_break_slot_)));
912 }
913 
914 
915 Object* Debug::Break(Arguments args) {
916  Heap* heap = isolate_->heap();
917  HandleScope scope(isolate_);
918  ASSERT(args.length() == 0);
919 
920  thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED;
921 
922  // Get the top-most JavaScript frame.
923  JavaScriptFrameIterator it(isolate_);
924  JavaScriptFrame* frame = it.frame();
925 
926  // Just continue if breaks are disabled or debugger cannot be loaded.
927  if (disable_break() || !Load()) {
928  SetAfterBreakTarget(frame);
929  return heap->undefined_value();
930  }
931 
932  // Enter the debugger.
933  EnterDebugger debugger(isolate_);
934  if (debugger.FailedToEnter()) {
935  return heap->undefined_value();
936  }
937 
938  // Postpone interrupt during breakpoint processing.
939  PostponeInterruptsScope postpone(isolate_);
940 
941  // Get the debug info (create it if it does not exist).
942  Handle<SharedFunctionInfo> shared =
943  Handle<SharedFunctionInfo>(frame->function()->shared());
944  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
945 
946  // Find the break point where execution has stopped.
947  BreakLocationIterator break_location_iterator(debug_info,
948  ALL_BREAK_LOCATIONS);
949  // pc points to the instruction after the current one, possibly a break
950  // location as well. So the "- 1" to exclude it from the search.
951  break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
952 
953  // Check whether step next reached a new statement.
954  if (!StepNextContinue(&break_location_iterator, frame)) {
955  // Decrease steps left if performing multiple steps.
956  if (thread_local_.step_count_ > 0) {
957  thread_local_.step_count_--;
958  }
959  }
960 
961  // If there is one or more real break points check whether any of these are
962  // triggered.
963  Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
964  if (break_location_iterator.HasBreakPoint()) {
965  Handle<Object> break_point_objects =
966  Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_);
967  break_points_hit = CheckBreakPoints(break_point_objects);
968  }
969 
970  // If step out is active skip everything until the frame where we need to step
971  // out to is reached, unless real breakpoint is hit.
972  if (StepOutActive() && frame->fp() != step_out_fp() &&
973  break_points_hit->IsUndefined() ) {
974  // Step count should always be 0 for StepOut.
975  ASSERT(thread_local_.step_count_ == 0);
976  } else if (!break_points_hit->IsUndefined() ||
977  (thread_local_.last_step_action_ != StepNone &&
978  thread_local_.step_count_ == 0)) {
979  // Notify debugger if a real break point is triggered or if performing
980  // single stepping with no more steps to perform. Otherwise do another step.
981 
982  // Clear all current stepping setup.
983  ClearStepping();
984 
985  if (thread_local_.queued_step_count_ > 0) {
986  // Perform queued steps
987  int step_count = thread_local_.queued_step_count_;
988 
989  // Clear queue
990  thread_local_.queued_step_count_ = 0;
991 
992  PrepareStep(StepNext, step_count, StackFrame::NO_ID);
993  } else {
994  // Notify the debug event listeners.
995  isolate_->debugger()->OnDebugBreak(break_points_hit, false);
996  }
997  } else if (thread_local_.last_step_action_ != StepNone) {
998  // Hold on to last step action as it is cleared by the call to
999  // ClearStepping.
1000  StepAction step_action = thread_local_.last_step_action_;
1001  int step_count = thread_local_.step_count_;
1002 
1003  // If StepNext goes deeper in code, StepOut until original frame
1004  // and keep step count queued up in the meantime.
1005  if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
1006  // Count frames until target frame
1007  int count = 0;
1008  JavaScriptFrameIterator it(isolate_);
1009  while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
1010  count++;
1011  it.Advance();
1012  }
1013 
1014  // Check that we indeed found the frame we are looking for.
1015  CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
1016  if (step_count > 1) {
1017  // Save old count and action to continue stepping after StepOut.
1018  thread_local_.queued_step_count_ = step_count - 1;
1019  }
1020 
1021  // Set up for StepOut to reach target frame.
1022  step_action = StepOut;
1023  step_count = count;
1024  }
1025 
1026  // Clear all current stepping setup.
1027  ClearStepping();
1028 
1029  // Set up for the remaining steps.
1030  PrepareStep(step_action, step_count, StackFrame::NO_ID);
1031  }
1032 
1033  if (thread_local_.frame_drop_mode_ == FRAMES_UNTOUCHED) {
1034  SetAfterBreakTarget(frame);
1035  } else if (thread_local_.frame_drop_mode_ ==
1036  FRAME_DROPPED_IN_IC_CALL) {
1037  // We must have been calling IC stub. Do not go there anymore.
1038  Code* plain_return = isolate_->builtins()->builtin(
1039  Builtins::kPlainReturn_LiveEdit);
1040  thread_local_.after_break_target_ = plain_return->entry();
1041  } else if (thread_local_.frame_drop_mode_ ==
1042  FRAME_DROPPED_IN_DEBUG_SLOT_CALL) {
1043  // Debug break slot stub does not return normally, instead it manually
1044  // cleans the stack and jumps. We should patch the jump address.
1045  Code* plain_return = isolate_->builtins()->builtin(
1046  Builtins::kFrameDropper_LiveEdit);
1047  thread_local_.after_break_target_ = plain_return->entry();
1048  } else if (thread_local_.frame_drop_mode_ ==
1049  FRAME_DROPPED_IN_DIRECT_CALL) {
1050  // Nothing to do, after_break_target is not used here.
1051  } else if (thread_local_.frame_drop_mode_ ==
1052  FRAME_DROPPED_IN_RETURN_CALL) {
1053  Code* plain_return = isolate_->builtins()->builtin(
1054  Builtins::kFrameDropper_LiveEdit);
1055  thread_local_.after_break_target_ = plain_return->entry();
1056  } else {
1057  UNREACHABLE();
1058  }
1059 
1060  return heap->undefined_value();
1061 }
1062 
1063 
1064 RUNTIME_FUNCTION(Object*, Debug_Break) {
1065  return isolate->debug()->Break(args);
1066 }
1067 
1068 
1069 // Check the break point objects for whether one or more are actually
1070 // triggered. This function returns a JSArray with the break point objects
1071 // which is triggered.
1072 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
1073  Factory* factory = isolate_->factory();
1074 
1075  // Count the number of break points hit. If there are multiple break points
1076  // they are in a FixedArray.
1077  Handle<FixedArray> break_points_hit;
1078  int break_points_hit_count = 0;
1079  ASSERT(!break_point_objects->IsUndefined());
1080  if (break_point_objects->IsFixedArray()) {
1081  Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
1082  break_points_hit = factory->NewFixedArray(array->length());
1083  for (int i = 0; i < array->length(); i++) {
1084  Handle<Object> o(array->get(i), isolate_);
1085  if (CheckBreakPoint(o)) {
1086  break_points_hit->set(break_points_hit_count++, *o);
1087  }
1088  }
1089  } else {
1090  break_points_hit = factory->NewFixedArray(1);
1091  if (CheckBreakPoint(break_point_objects)) {
1092  break_points_hit->set(break_points_hit_count++, *break_point_objects);
1093  }
1094  }
1095 
1096  // Return undefined if no break points were triggered.
1097  if (break_points_hit_count == 0) {
1098  return factory->undefined_value();
1099  }
1100  // Return break points hit as a JSArray.
1101  Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
1102  result->set_length(Smi::FromInt(break_points_hit_count));
1103  return result;
1104 }
1105 
1106 
1107 // Check whether a single break point object is triggered.
1108 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
1109  Factory* factory = isolate_->factory();
1110  HandleScope scope(isolate_);
1111 
1112  // Ignore check if break point object is not a JSObject.
1113  if (!break_point_object->IsJSObject()) return true;
1114 
1115  // Get the function IsBreakPointTriggered (defined in debug-debugger.js).
1116  Handle<String> is_break_point_triggered_string =
1117  factory->InternalizeOneByteString(
1118  STATIC_ASCII_VECTOR("IsBreakPointTriggered"));
1119  Handle<JSFunction> check_break_point =
1120  Handle<JSFunction>(JSFunction::cast(
1121  debug_context()->global_object()->GetPropertyNoExceptionThrown(
1122  *is_break_point_triggered_string)));
1123 
1124  // Get the break id as an object.
1125  Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
1126 
1127  // Call HandleBreakPointx.
1128  bool caught_exception;
1129  Handle<Object> argv[] = { break_id, break_point_object };
1130  Handle<Object> result = Execution::TryCall(check_break_point,
1131  isolate_->js_builtins_object(),
1132  ARRAY_SIZE(argv),
1133  argv,
1134  &caught_exception);
1135 
1136  // If exception or non boolean result handle as not triggered
1137  if (caught_exception || !result->IsBoolean()) {
1138  return false;
1139  }
1140 
1141  // Return whether the break point is triggered.
1142  ASSERT(!result.is_null());
1143  return (*result)->IsTrue();
1144 }
1145 
1146 
1147 // Check whether the function has debug information.
1148 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
1149  return !shared->debug_info()->IsUndefined();
1150 }
1151 
1152 
1153 // Return the debug info for this function. EnsureDebugInfo must be called
1154 // prior to ensure the debug info has been generated for shared.
1155 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
1156  ASSERT(HasDebugInfo(shared));
1157  return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
1158 }
1159 
1160 
1161 void Debug::SetBreakPoint(Handle<JSFunction> function,
1162  Handle<Object> break_point_object,
1163  int* source_position) {
1164  HandleScope scope(isolate_);
1165 
1166  PrepareForBreakPoints();
1167 
1168  // Make sure the function is compiled and has set up the debug info.
1169  Handle<SharedFunctionInfo> shared(function->shared());
1170  if (!EnsureDebugInfo(shared, function)) {
1171  // Return if retrieving debug info failed.
1172  return;
1173  }
1174 
1175  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1176  // Source positions starts with zero.
1177  ASSERT(*source_position >= 0);
1178 
1179  // Find the break point and change it.
1180  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1181  it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED);
1182  it.SetBreakPoint(break_point_object);
1183 
1184  *source_position = it.position();
1185 
1186  // At least one active break point now.
1187  ASSERT(debug_info->GetBreakPointCount() > 0);
1188 }
1189 
1190 
1191 bool Debug::SetBreakPointForScript(Handle<Script> script,
1192  Handle<Object> break_point_object,
1193  int* source_position,
1194  BreakPositionAlignment alignment) {
1195  HandleScope scope(isolate_);
1196 
1197  PrepareForBreakPoints();
1198 
1199  // Obtain shared function info for the function.
1200  Object* result = FindSharedFunctionInfoInScript(script, *source_position);
1201  if (result->IsUndefined()) return false;
1202 
1203  // Make sure the function has set up the debug info.
1204  Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
1205  if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1206  // Return if retrieving debug info failed.
1207  return false;
1208  }
1209 
1210  // Find position within function. The script position might be before the
1211  // source position of the first function.
1212  int position;
1213  if (shared->start_position() > *source_position) {
1214  position = 0;
1215  } else {
1216  position = *source_position - shared->start_position();
1217  }
1218 
1219  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1220  // Source positions starts with zero.
1221  ASSERT(position >= 0);
1222 
1223  // Find the break point and change it.
1224  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1225  it.FindBreakLocationFromPosition(position, alignment);
1226  it.SetBreakPoint(break_point_object);
1227 
1228  *source_position = it.position() + shared->start_position();
1229 
1230  // At least one active break point now.
1231  ASSERT(debug_info->GetBreakPointCount() > 0);
1232  return true;
1233 }
1234 
1235 
1236 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1237  HandleScope scope(isolate_);
1238 
1239  DebugInfoListNode* node = debug_info_list_;
1240  while (node != NULL) {
1241  Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
1242  break_point_object);
1243  if (!result->IsUndefined()) {
1244  // Get information in the break point.
1245  BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
1246  Handle<DebugInfo> debug_info = node->debug_info();
1247 
1248  // Find the break point and clear it.
1249  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1250  it.FindBreakLocationFromAddress(debug_info->code()->entry() +
1251  break_point_info->code_position()->value());
1252  it.ClearBreakPoint(break_point_object);
1253 
1254  // If there are no more break points left remove the debug info for this
1255  // function.
1256  if (debug_info->GetBreakPointCount() == 0) {
1257  RemoveDebugInfo(debug_info);
1258  }
1259 
1260  return;
1261  }
1262  node = node->next();
1263  }
1264 }
1265 
1266 
1267 void Debug::ClearAllBreakPoints() {
1268  DebugInfoListNode* node = debug_info_list_;
1269  while (node != NULL) {
1270  // Remove all debug break code.
1271  BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1272  it.ClearAllDebugBreak();
1273  node = node->next();
1274  }
1275 
1276  // Remove all debug info.
1277  while (debug_info_list_ != NULL) {
1278  RemoveDebugInfo(debug_info_list_->debug_info());
1279  }
1280 }
1281 
1282 
1283 void Debug::FloodWithOneShot(Handle<JSFunction> function) {
1284  PrepareForBreakPoints();
1285 
1286  // Make sure the function is compiled and has set up the debug info.
1287  Handle<SharedFunctionInfo> shared(function->shared());
1288  if (!EnsureDebugInfo(shared, function)) {
1289  // Return if we failed to retrieve the debug info.
1290  return;
1291  }
1292 
1293  // Flood the function with break points.
1294  BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
1295  while (!it.Done()) {
1296  it.SetOneShot();
1297  it.Next();
1298  }
1299 }
1300 
1301 
1302 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
1303  Handle<FixedArray> new_bindings(function->function_bindings());
1304  Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
1305  isolate_);
1306 
1307  if (!bindee.is_null() && bindee->IsJSFunction() &&
1308  !JSFunction::cast(*bindee)->IsBuiltin()) {
1309  Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
1310  Debug::FloodWithOneShot(bindee_function);
1311  }
1312 }
1313 
1314 
1315 void Debug::FloodHandlerWithOneShot() {
1316  // Iterate through the JavaScript stack looking for handlers.
1317  StackFrame::Id id = break_frame_id();
1318  if (id == StackFrame::NO_ID) {
1319  // If there is no JavaScript stack don't do anything.
1320  return;
1321  }
1322  for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
1323  JavaScriptFrame* frame = it.frame();
1324  if (frame->HasHandler()) {
1325  // Flood the function with the catch block with break points
1326  FloodWithOneShot(Handle<JSFunction>(frame->function()));
1327  return;
1328  }
1329  }
1330 }
1331 
1332 
1333 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
1334  if (type == BreakUncaughtException) {
1335  break_on_uncaught_exception_ = enable;
1336  } else {
1337  break_on_exception_ = enable;
1338  }
1339 }
1340 
1341 
1342 bool Debug::IsBreakOnException(ExceptionBreakType type) {
1343  if (type == BreakUncaughtException) {
1344  return break_on_uncaught_exception_;
1345  } else {
1346  return break_on_exception_;
1347  }
1348 }
1349 
1350 
1351 void Debug::PrepareStep(StepAction step_action,
1352  int step_count,
1353  StackFrame::Id frame_id) {
1354  HandleScope scope(isolate_);
1355 
1356  PrepareForBreakPoints();
1357 
1358  ASSERT(Debug::InDebugger());
1359 
1360  // Remember this step action and count.
1361  thread_local_.last_step_action_ = step_action;
1362  if (step_action == StepOut) {
1363  // For step out target frame will be found on the stack so there is no need
1364  // to set step counter for it. It's expected to always be 0 for StepOut.
1365  thread_local_.step_count_ = 0;
1366  } else {
1367  thread_local_.step_count_ = step_count;
1368  }
1369 
1370  // Get the frame where the execution has stopped and skip the debug frame if
1371  // any. The debug frame will only be present if execution was stopped due to
1372  // hitting a break point. In other situations (e.g. unhandled exception) the
1373  // debug frame is not present.
1374  StackFrame::Id id = break_frame_id();
1375  if (id == StackFrame::NO_ID) {
1376  // If there is no JavaScript stack don't do anything.
1377  return;
1378  }
1379  if (frame_id != StackFrame::NO_ID) {
1380  id = frame_id;
1381  }
1382  JavaScriptFrameIterator frames_it(isolate_, id);
1383  JavaScriptFrame* frame = frames_it.frame();
1384 
1385  // First of all ensure there is one-shot break points in the top handler
1386  // if any.
1387  FloodHandlerWithOneShot();
1388 
1389  // If the function on the top frame is unresolved perform step out. This will
1390  // be the case when calling unknown functions and having the debugger stopped
1391  // in an unhandled exception.
1392  if (!frame->function()->IsJSFunction()) {
1393  // Step out: Find the calling JavaScript frame and flood it with
1394  // breakpoints.
1395  frames_it.Advance();
1396  // Fill the function to return to with one-shot break points.
1397  JSFunction* function = frames_it.frame()->function();
1398  FloodWithOneShot(Handle<JSFunction>(function));
1399  return;
1400  }
1401 
1402  // Get the debug info (create it if it does not exist).
1403  Handle<JSFunction> function(frame->function());
1404  Handle<SharedFunctionInfo> shared(function->shared());
1405  if (!EnsureDebugInfo(shared, function)) {
1406  // Return if ensuring debug info failed.
1407  return;
1408  }
1409  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1410 
1411  // Find the break location where execution has stopped.
1412  BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1413  // pc points to the instruction after the current one, possibly a break
1414  // location as well. So the "- 1" to exclude it from the search.
1415  it.FindBreakLocationFromAddress(frame->pc() - 1);
1416 
1417  // Compute whether or not the target is a call target.
1418  bool is_load_or_store = false;
1419  bool is_inline_cache_stub = false;
1420  bool is_at_restarted_function = false;
1421  Handle<Code> call_function_stub;
1422 
1423  if (thread_local_.restarter_frame_function_pointer_ == NULL) {
1424  if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1425  bool is_call_target = false;
1426  Address target = it.rinfo()->target_address();
1427  Code* code = Code::GetCodeFromTargetAddress(target);
1428  if (code->is_inline_cache_stub()) {
1429  is_inline_cache_stub = true;
1430  is_load_or_store = !is_call_target;
1431  }
1432 
1433  // Check if target code is CallFunction stub.
1434  Code* maybe_call_function_stub = code;
1435  // If there is a breakpoint at this line look at the original code to
1436  // check if it is a CallFunction stub.
1437  if (it.IsDebugBreak()) {
1438  Address original_target = it.original_rinfo()->target_address();
1439  maybe_call_function_stub =
1440  Code::GetCodeFromTargetAddress(original_target);
1441  }
1442  if (maybe_call_function_stub->kind() == Code::STUB &&
1443  maybe_call_function_stub->major_key() == CodeStub::CallFunction) {
1444  // Save reference to the code as we may need it to find out arguments
1445  // count for 'step in' later.
1446  call_function_stub = Handle<Code>(maybe_call_function_stub);
1447  }
1448  }
1449  } else {
1450  is_at_restarted_function = true;
1451  }
1452 
1453  // If this is the last break code target step out is the only possibility.
1454  if (it.IsExit() || step_action == StepOut) {
1455  if (step_action == StepOut) {
1456  // Skip step_count frames starting with the current one.
1457  while (step_count-- > 0 && !frames_it.done()) {
1458  frames_it.Advance();
1459  }
1460  } else {
1461  ASSERT(it.IsExit());
1462  frames_it.Advance();
1463  }
1464  // Skip builtin functions on the stack.
1465  while (!frames_it.done() && frames_it.frame()->function()->IsBuiltin()) {
1466  frames_it.Advance();
1467  }
1468  // Step out: If there is a JavaScript caller frame, we need to
1469  // flood it with breakpoints.
1470  if (!frames_it.done()) {
1471  // Fill the function to return to with one-shot break points.
1472  JSFunction* function = frames_it.frame()->function();
1473  FloodWithOneShot(Handle<JSFunction>(function));
1474  // Set target frame pointer.
1475  ActivateStepOut(frames_it.frame());
1476  }
1477  } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
1478  !call_function_stub.is_null() || is_at_restarted_function)
1479  || step_action == StepNext || step_action == StepMin) {
1480  // Step next or step min.
1481 
1482  // Fill the current function with one-shot break points.
1483  FloodWithOneShot(function);
1484 
1485  // Remember source position and frame to handle step next.
1486  thread_local_.last_statement_position_ =
1487  debug_info->code()->SourceStatementPosition(frame->pc());
1488  thread_local_.last_fp_ = frame->UnpaddedFP();
1489  } else {
1490  // If there's restarter frame on top of the stack, just get the pointer
1491  // to function which is going to be restarted.
1492  if (is_at_restarted_function) {
1493  Handle<JSFunction> restarted_function(
1494  JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
1495  FloodWithOneShot(restarted_function);
1496  } else if (!call_function_stub.is_null()) {
1497  // If it's CallFunction stub ensure target function is compiled and flood
1498  // it with one shot breakpoints.
1499 
1500  // Find out number of arguments from the stub minor key.
1501  // Reverse lookup required as the minor key cannot be retrieved
1502  // from the code object.
1503  Handle<Object> obj(
1504  isolate_->heap()->code_stubs()->SlowReverseLookup(
1505  *call_function_stub),
1506  isolate_);
1507  ASSERT(!obj.is_null());
1508  ASSERT(!(*obj)->IsUndefined());
1509  ASSERT(obj->IsSmi());
1510  // Get the STUB key and extract major and minor key.
1511  uint32_t key = Smi::cast(*obj)->value();
1512  // Argc in the stub is the number of arguments passed - not the
1513  // expected arguments of the called function.
1514  int call_function_arg_count =
1516  CodeStub::MinorKeyFromKey(key));
1517  ASSERT(call_function_stub->major_key() ==
1518  CodeStub::MajorKeyFromKey(key));
1519 
1520  // Find target function on the expression stack.
1521  // Expression stack looks like this (top to bottom):
1522  // argN
1523  // ...
1524  // arg0
1525  // Receiver
1526  // Function to call
1527  int expressions_count = frame->ComputeExpressionsCount();
1528  ASSERT(expressions_count - 2 - call_function_arg_count >= 0);
1529  Object* fun = frame->GetExpression(
1530  expressions_count - 2 - call_function_arg_count);
1531 
1532  // Flood the actual target of call/apply.
1533  if (fun->IsJSFunction()) {
1534  Isolate* isolate = JSFunction::cast(fun)->GetIsolate();
1535  Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply);
1536  Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall);
1537  while (fun->IsJSFunction()) {
1538  Code* code = JSFunction::cast(fun)->shared()->code();
1539  if (code != apply && code != call) break;
1540  fun = frame->GetExpression(
1541  expressions_count - 1 - call_function_arg_count);
1542  }
1543  }
1544 
1545  if (fun->IsJSFunction()) {
1546  Handle<JSFunction> js_function(JSFunction::cast(fun));
1547  if (js_function->shared()->bound()) {
1548  Debug::FloodBoundFunctionWithOneShot(js_function);
1549  } else if (!js_function->IsBuiltin()) {
1550  // Don't step into builtins.
1551  // It will also compile target function if it's not compiled yet.
1552  FloodWithOneShot(js_function);
1553  }
1554  }
1555  }
1556 
1557  // Fill the current function with one-shot break points even for step in on
1558  // a call target as the function called might be a native function for
1559  // which step in will not stop. It also prepares for stepping in
1560  // getters/setters.
1561  FloodWithOneShot(function);
1562 
1563  if (is_load_or_store) {
1564  // Remember source position and frame to handle step in getter/setter. If
1565  // there is a custom getter/setter it will be handled in
1566  // Object::Get/SetPropertyWithCallback, otherwise the step action will be
1567  // propagated on the next Debug::Break.
1568  thread_local_.last_statement_position_ =
1569  debug_info->code()->SourceStatementPosition(frame->pc());
1570  thread_local_.last_fp_ = frame->UnpaddedFP();
1571  }
1572 
1573  // Step in or Step in min
1574  it.PrepareStepIn(isolate_);
1575  ActivateStepIn(frame);
1576  }
1577 }
1578 
1579 
1580 // Check whether the current debug break should be reported to the debugger. It
1581 // is used to have step next and step in only report break back to the debugger
1582 // if on a different frame or in a different statement. In some situations
1583 // there will be several break points in the same statement when the code is
1584 // flooded with one-shot break points. This function helps to perform several
1585 // steps before reporting break back to the debugger.
1586 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1587  JavaScriptFrame* frame) {
1588  // StepNext and StepOut shouldn't bring us deeper in code, so last frame
1589  // shouldn't be a parent of current frame.
1590  if (thread_local_.last_step_action_ == StepNext ||
1591  thread_local_.last_step_action_ == StepOut) {
1592  if (frame->fp() < thread_local_.last_fp_) return true;
1593  }
1594 
1595  // If the step last action was step next or step in make sure that a new
1596  // statement is hit.
1597  if (thread_local_.last_step_action_ == StepNext ||
1598  thread_local_.last_step_action_ == StepIn) {
1599  // Never continue if returning from function.
1600  if (break_location_iterator->IsExit()) return false;
1601 
1602  // Continue if we are still on the same frame and in the same statement.
1603  int current_statement_position =
1604  break_location_iterator->code()->SourceStatementPosition(frame->pc());
1605  return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1606  thread_local_.last_statement_position_ == current_statement_position;
1607  }
1608 
1609  // No step next action - don't continue.
1610  return false;
1611 }
1612 
1613 
1614 // Check whether the code object at the specified address is a debug break code
1615 // object.
1616 bool Debug::IsDebugBreak(Address addr) {
1617  Code* code = Code::GetCodeFromTargetAddress(addr);
1618  return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK;
1619 }
1620 
1621 
1622 // Check whether a code stub with the specified major key is a possible break
1623 // point location when looking for source break locations.
1624 bool Debug::IsSourceBreakStub(Code* code) {
1625  CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1626  return major_key == CodeStub::CallFunction;
1627 }
1628 
1629 
1630 // Check whether a code stub with the specified major key is a possible break
1631 // location.
1632 bool Debug::IsBreakStub(Code* code) {
1633  CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1634  return major_key == CodeStub::CallFunction;
1635 }
1636 
1637 
1638 // Find the builtin to use for invoking the debug break
1639 Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
1640  Isolate* isolate = code->GetIsolate();
1641 
1642  // Find the builtin debug break function matching the calling convention
1643  // used by the call site.
1644  if (code->is_inline_cache_stub()) {
1645  switch (code->kind()) {
1646  case Code::LOAD_IC:
1647  return isolate->builtins()->LoadIC_DebugBreak();
1648 
1649  case Code::STORE_IC:
1650  return isolate->builtins()->StoreIC_DebugBreak();
1651 
1652  case Code::KEYED_LOAD_IC:
1653  return isolate->builtins()->KeyedLoadIC_DebugBreak();
1654 
1655  case Code::KEYED_STORE_IC:
1656  return isolate->builtins()->KeyedStoreIC_DebugBreak();
1657 
1658  case Code::COMPARE_NIL_IC:
1659  return isolate->builtins()->CompareNilIC_DebugBreak();
1660 
1661  default:
1662  UNREACHABLE();
1663  }
1664  }
1665  if (RelocInfo::IsConstructCall(mode)) {
1666  if (code->has_function_cache()) {
1667  return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
1668  } else {
1669  return isolate->builtins()->CallConstructStub_DebugBreak();
1670  }
1671  }
1672  if (code->kind() == Code::STUB) {
1673  ASSERT(code->major_key() == CodeStub::CallFunction);
1674  if (code->has_function_cache()) {
1675  return isolate->builtins()->CallFunctionStub_Recording_DebugBreak();
1676  } else {
1677  return isolate->builtins()->CallFunctionStub_DebugBreak();
1678  }
1679  }
1680 
1681  UNREACHABLE();
1682  return Handle<Code>::null();
1683 }
1684 
1685 
1686 // Simple function for returning the source positions for active break points.
1687 Handle<Object> Debug::GetSourceBreakLocations(
1688  Handle<SharedFunctionInfo> shared,
1689  BreakPositionAlignment position_alignment) {
1690  Isolate* isolate = shared->GetIsolate();
1691  Heap* heap = isolate->heap();
1692  if (!HasDebugInfo(shared)) {
1693  return Handle<Object>(heap->undefined_value(), isolate);
1694  }
1695  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1696  if (debug_info->GetBreakPointCount() == 0) {
1697  return Handle<Object>(heap->undefined_value(), isolate);
1698  }
1699  Handle<FixedArray> locations =
1700  isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1701  int count = 0;
1702  for (int i = 0; i < debug_info->break_points()->length(); i++) {
1703  if (!debug_info->break_points()->get(i)->IsUndefined()) {
1704  BreakPointInfo* break_point_info =
1705  BreakPointInfo::cast(debug_info->break_points()->get(i));
1706  if (break_point_info->GetBreakPointCount() > 0) {
1707  Smi* position;
1708  switch (position_alignment) {
1709  case STATEMENT_ALIGNED:
1710  position = break_point_info->statement_position();
1711  break;
1712  case BREAK_POSITION_ALIGNED:
1713  position = break_point_info->source_position();
1714  break;
1715  default:
1716  UNREACHABLE();
1717  position = break_point_info->statement_position();
1718  }
1719 
1720  locations->set(count++, position);
1721  }
1722  }
1723  }
1724  return locations;
1725 }
1726 
1727 
1728 void Debug::NewBreak(StackFrame::Id break_frame_id) {
1729  thread_local_.break_frame_id_ = break_frame_id;
1730  thread_local_.break_id_ = ++thread_local_.break_count_;
1731 }
1732 
1733 
1734 void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) {
1735  thread_local_.break_frame_id_ = break_frame_id;
1736  thread_local_.break_id_ = break_id;
1737 }
1738 
1739 
1740 // Handle stepping into a function.
1741 void Debug::HandleStepIn(Handle<JSFunction> function,
1742  Handle<Object> holder,
1743  Address fp,
1744  bool is_constructor) {
1745  Isolate* isolate = function->GetIsolate();
1746  // If the frame pointer is not supplied by the caller find it.
1747  if (fp == 0) {
1748  StackFrameIterator it(isolate);
1749  it.Advance();
1750  // For constructor functions skip another frame.
1751  if (is_constructor) {
1752  ASSERT(it.frame()->is_construct());
1753  it.Advance();
1754  }
1755  fp = it.frame()->fp();
1756  }
1757 
1758  // Flood the function with one-shot break points if it is called from where
1759  // step into was requested.
1760  if (fp == step_in_fp()) {
1761  if (function->shared()->bound()) {
1762  // Handle Function.prototype.bind
1763  Debug::FloodBoundFunctionWithOneShot(function);
1764  } else if (!function->IsBuiltin()) {
1765  // Don't allow step into functions in the native context.
1766  if (function->shared()->code() ==
1767  isolate->builtins()->builtin(Builtins::kFunctionApply) ||
1768  function->shared()->code() ==
1769  isolate->builtins()->builtin(Builtins::kFunctionCall)) {
1770  // Handle function.apply and function.call separately to flood the
1771  // function to be called and not the code for Builtins::FunctionApply or
1772  // Builtins::FunctionCall. The receiver of call/apply is the target
1773  // function.
1774  if (!holder.is_null() && holder->IsJSFunction()) {
1775  Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
1776  if (!js_function->IsBuiltin()) {
1777  Debug::FloodWithOneShot(js_function);
1778  } else if (js_function->shared()->bound()) {
1779  // Handle Function.prototype.bind
1780  Debug::FloodBoundFunctionWithOneShot(js_function);
1781  }
1782  }
1783  } else {
1784  Debug::FloodWithOneShot(function);
1785  }
1786  }
1787  }
1788 }
1789 
1790 
1791 void Debug::ClearStepping() {
1792  // Clear the various stepping setup.
1793  ClearOneShot();
1794  ClearStepIn();
1795  ClearStepOut();
1796  ClearStepNext();
1797 
1798  // Clear multiple step counter.
1799  thread_local_.step_count_ = 0;
1800 }
1801 
1802 
1803 // Clears all the one-shot break points that are currently set. Normally this
1804 // function is called each time a break point is hit as one shot break points
1805 // are used to support stepping.
1806 void Debug::ClearOneShot() {
1807  // The current implementation just runs through all the breakpoints. When the
1808  // last break point for a function is removed that function is automatically
1809  // removed from the list.
1810 
1811  DebugInfoListNode* node = debug_info_list_;
1812  while (node != NULL) {
1813  BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1814  while (!it.Done()) {
1815  it.ClearOneShot();
1816  it.Next();
1817  }
1818  node = node->next();
1819  }
1820 }
1821 
1822 
1823 void Debug::ActivateStepIn(StackFrame* frame) {
1824  ASSERT(!StepOutActive());
1825  thread_local_.step_into_fp_ = frame->UnpaddedFP();
1826 }
1827 
1828 
1829 void Debug::ClearStepIn() {
1830  thread_local_.step_into_fp_ = 0;
1831 }
1832 
1833 
1834 void Debug::ActivateStepOut(StackFrame* frame) {
1835  ASSERT(!StepInActive());
1836  thread_local_.step_out_fp_ = frame->UnpaddedFP();
1837 }
1838 
1839 
1840 void Debug::ClearStepOut() {
1841  thread_local_.step_out_fp_ = 0;
1842 }
1843 
1844 
1845 void Debug::ClearStepNext() {
1846  thread_local_.last_step_action_ = StepNone;
1847  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1848  thread_local_.last_fp_ = 0;
1849 }
1850 
1851 
1852 static void CollectActiveFunctionsFromThread(
1853  Isolate* isolate,
1854  ThreadLocalTop* top,
1855  List<Handle<JSFunction> >* active_functions,
1856  Object* active_code_marker) {
1857  // Find all non-optimized code functions with activation frames
1858  // on the stack. This includes functions which have optimized
1859  // activations (including inlined functions) on the stack as the
1860  // non-optimized code is needed for the lazy deoptimization.
1861  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1862  JavaScriptFrame* frame = it.frame();
1863  if (frame->is_optimized()) {
1864  List<JSFunction*> functions(FLAG_max_inlining_levels + 1);
1865  frame->GetFunctions(&functions);
1866  for (int i = 0; i < functions.length(); i++) {
1867  JSFunction* function = functions[i];
1868  active_functions->Add(Handle<JSFunction>(function));
1869  function->shared()->code()->set_gc_metadata(active_code_marker);
1870  }
1871  } else if (frame->function()->IsJSFunction()) {
1872  JSFunction* function = frame->function();
1873  ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1874  active_functions->Add(Handle<JSFunction>(function));
1875  function->shared()->code()->set_gc_metadata(active_code_marker);
1876  }
1877  }
1878 }
1879 
1880 
1881 static void RedirectActivationsToRecompiledCodeOnThread(
1882  Isolate* isolate,
1883  ThreadLocalTop* top) {
1884  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1885  JavaScriptFrame* frame = it.frame();
1886 
1887  if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue;
1888 
1889  JSFunction* function = frame->function();
1890 
1891  ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1892 
1893  Handle<Code> frame_code(frame->LookupCode());
1894  if (frame_code->has_debug_break_slots()) continue;
1895 
1896  Handle<Code> new_code(function->shared()->code());
1897  if (new_code->kind() != Code::FUNCTION ||
1898  !new_code->has_debug_break_slots()) {
1899  continue;
1900  }
1901 
1902  // Iterate over the RelocInfo in the original code to compute the sum of the
1903  // constant pools and veneer pools sizes. (See Assembler::CheckConstPool()
1904  // and Assembler::CheckVeneerPool())
1905  // Note that this is only useful for architectures using constant pools or
1906  // veneer pools.
1907  int pool_mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1908  RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1909  int frame_pool_size = 0;
1910  for (RelocIterator it(*frame_code, pool_mask); !it.done(); it.next()) {
1911  RelocInfo* info = it.rinfo();
1912  if (info->pc() >= frame->pc()) break;
1913  frame_pool_size += static_cast<int>(info->data());
1914  }
1915  intptr_t frame_offset =
1916  frame->pc() - frame_code->instruction_start() - frame_pool_size;
1917 
1918  // Iterate over the RelocInfo for new code to find the number of bytes
1919  // generated for debug slots and constant pools.
1920  int debug_break_slot_bytes = 0;
1921  int new_code_pool_size = 0;
1922  int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
1923  RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1924  RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1925  for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
1926  // Check if the pc in the new code with debug break
1927  // slots is before this slot.
1928  RelocInfo* info = it.rinfo();
1929  intptr_t new_offset = info->pc() - new_code->instruction_start() -
1930  new_code_pool_size - debug_break_slot_bytes;
1931  if (new_offset >= frame_offset) {
1932  break;
1933  }
1934 
1935  if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
1936  debug_break_slot_bytes += Assembler::kDebugBreakSlotLength;
1937  } else {
1938  ASSERT(RelocInfo::IsConstPool(info->rmode()));
1939  // The size of the pools is encoded in the data.
1940  new_code_pool_size += static_cast<int>(info->data());
1941  }
1942  }
1943 
1944  // Compute the equivalent pc in the new code.
1945  byte* new_pc = new_code->instruction_start() + frame_offset +
1946  debug_break_slot_bytes + new_code_pool_size;
1947 
1948  if (FLAG_trace_deopt) {
1949  PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1950  "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1951  "for debugging, "
1952  "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
1953  reinterpret_cast<intptr_t>(
1954  frame_code->instruction_start()),
1955  reinterpret_cast<intptr_t>(
1956  frame_code->instruction_start()) +
1957  frame_code->instruction_size(),
1958  frame_code->instruction_size(),
1959  reinterpret_cast<intptr_t>(new_code->instruction_start()),
1960  reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1961  new_code->instruction_size(),
1962  new_code->instruction_size(),
1963  reinterpret_cast<intptr_t>(frame->pc()),
1964  reinterpret_cast<intptr_t>(new_pc));
1965  }
1966 
1967  // Patch the return address to return into the code with
1968  // debug break slots.
1969  frame->set_pc(new_pc);
1970  }
1971 }
1972 
1973 
1974 class ActiveFunctionsCollector : public ThreadVisitor {
1975  public:
1976  explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
1977  Object* active_code_marker)
1978  : active_functions_(active_functions),
1979  active_code_marker_(active_code_marker) { }
1980 
1981  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1982  CollectActiveFunctionsFromThread(isolate,
1983  top,
1984  active_functions_,
1985  active_code_marker_);
1986  }
1987 
1988  private:
1989  List<Handle<JSFunction> >* active_functions_;
1990  Object* active_code_marker_;
1991 };
1992 
1993 
1994 class ActiveFunctionsRedirector : public ThreadVisitor {
1995  public:
1996  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1997  RedirectActivationsToRecompiledCodeOnThread(isolate, top);
1998  }
1999 };
2000 
2001 
2002 void Debug::PrepareForBreakPoints() {
2003  // If preparing for the first break point make sure to deoptimize all
2004  // functions as debugging does not work with optimized code.
2005  if (!has_break_points_) {
2006  if (isolate_->concurrent_recompilation_enabled()) {
2007  isolate_->optimizing_compiler_thread()->Flush();
2008  }
2009 
2010  Deoptimizer::DeoptimizeAll(isolate_);
2011 
2012  Handle<Code> lazy_compile = isolate_->builtins()->CompileUnoptimized();
2013 
2014  // There will be at least one break point when we are done.
2015  has_break_points_ = true;
2016 
2017  // Keep the list of activated functions in a handlified list as it
2018  // is used both in GC and non-GC code.
2019  List<Handle<JSFunction> > active_functions(100);
2020 
2021  {
2022  // We are going to iterate heap to find all functions without
2023  // debug break slots.
2024  Heap* heap = isolate_->heap();
2025  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
2026  "preparing for breakpoints");
2027 
2028  // Ensure no GC in this scope as we are going to use gc_metadata
2029  // field in the Code object to mark active functions.
2030  DisallowHeapAllocation no_allocation;
2031 
2032  Object* active_code_marker = heap->the_hole_value();
2033 
2034  CollectActiveFunctionsFromThread(isolate_,
2035  isolate_->thread_local_top(),
2036  &active_functions,
2037  active_code_marker);
2038  ActiveFunctionsCollector active_functions_collector(&active_functions,
2039  active_code_marker);
2040  isolate_->thread_manager()->IterateArchivedThreads(
2041  &active_functions_collector);
2042 
2043  // Scan the heap for all non-optimized functions which have no
2044  // debug break slots and are not active or inlined into an active
2045  // function and mark them for lazy compilation.
2046  HeapIterator iterator(heap);
2047  HeapObject* obj = NULL;
2048  while (((obj = iterator.next()) != NULL)) {
2049  if (obj->IsJSFunction()) {
2050  JSFunction* function = JSFunction::cast(obj);
2051  SharedFunctionInfo* shared = function->shared();
2052 
2053  if (!shared->allows_lazy_compilation()) continue;
2054  if (!shared->script()->IsScript()) continue;
2055  if (function->IsBuiltin()) continue;
2056  if (shared->code()->gc_metadata() == active_code_marker) continue;
2057 
2058  Code::Kind kind = function->code()->kind();
2059  if (kind == Code::FUNCTION &&
2060  !function->code()->has_debug_break_slots()) {
2061  function->set_code(*lazy_compile);
2062  function->shared()->set_code(*lazy_compile);
2063  } else if (kind == Code::BUILTIN &&
2064  (function->IsInOptimizationQueue() ||
2065  function->IsMarkedForOptimization() ||
2066  function->IsMarkedForConcurrentOptimization())) {
2067  // Abort in-flight compilation.
2068  Code* shared_code = function->shared()->code();
2069  if (shared_code->kind() == Code::FUNCTION &&
2070  shared_code->has_debug_break_slots()) {
2071  function->set_code(shared_code);
2072  } else {
2073  function->set_code(*lazy_compile);
2074  function->shared()->set_code(*lazy_compile);
2075  }
2076  }
2077  }
2078  }
2079 
2080  // Clear gc_metadata field.
2081  for (int i = 0; i < active_functions.length(); i++) {
2082  Handle<JSFunction> function = active_functions[i];
2083  function->shared()->code()->set_gc_metadata(Smi::FromInt(0));
2084  }
2085  }
2086 
2087  // Now recompile all functions with activation frames and and
2088  // patch the return address to run in the new compiled code.
2089  for (int i = 0; i < active_functions.length(); i++) {
2090  Handle<JSFunction> function = active_functions[i];
2091  Handle<SharedFunctionInfo> shared(function->shared());
2092 
2093  if (function->code()->kind() == Code::FUNCTION &&
2094  function->code()->has_debug_break_slots()) {
2095  // Nothing to do. Function code already had debug break slots.
2096  continue;
2097  }
2098 
2099  // If recompilation is not possible just skip it.
2100  if (shared->is_toplevel() ||
2101  !shared->allows_lazy_compilation() ||
2102  shared->code()->kind() == Code::BUILTIN) {
2103  continue;
2104  }
2105 
2106  // Make sure that the shared full code is compiled with debug
2107  // break slots.
2108  if (!shared->code()->has_debug_break_slots()) {
2109  // Try to compile the full code with debug break slots. If it
2110  // fails just keep the current code.
2111  bool prev_force_debugger_active =
2112  isolate_->debugger()->force_debugger_active();
2113  isolate_->debugger()->set_force_debugger_active(true);
2114  Handle<Code> code = Compiler::GetCodeForDebugging(function);
2115  function->ReplaceCode(*code);
2116  isolate_->debugger()->set_force_debugger_active(
2117  prev_force_debugger_active);
2118  }
2119 
2120  // Keep function code in sync with shared function info.
2121  function->set_code(shared->code());
2122  }
2123 
2124  RedirectActivationsToRecompiledCodeOnThread(isolate_,
2125  isolate_->thread_local_top());
2126 
2127  ActiveFunctionsRedirector active_functions_redirector;
2128  isolate_->thread_manager()->IterateArchivedThreads(
2129  &active_functions_redirector);
2130  }
2131 }
2132 
2133 
2134 Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2135  int position) {
2136  // Iterate the heap looking for SharedFunctionInfo generated from the
2137  // script. The inner most SharedFunctionInfo containing the source position
2138  // for the requested break point is found.
2139  // NOTE: This might require several heap iterations. If the SharedFunctionInfo
2140  // which is found is not compiled it is compiled and the heap is iterated
2141  // again as the compilation might create inner functions from the newly
2142  // compiled function and the actual requested break point might be in one of
2143  // these functions.
2144  // NOTE: The below fix-point iteration depends on all functions that cannot be
2145  // compiled lazily without a context to not be compiled at all. Compilation
2146  // will be triggered at points where we do not need a context.
2147  bool done = false;
2148  // The current candidate for the source position:
2149  int target_start_position = RelocInfo::kNoPosition;
2150  Handle<JSFunction> target_function;
2151  Handle<SharedFunctionInfo> target;
2152  Heap* heap = isolate_->heap();
2153  while (!done) {
2154  { // Extra scope for iterator and no-allocation.
2155  heap->EnsureHeapIsIterable();
2156  DisallowHeapAllocation no_alloc_during_heap_iteration;
2157  HeapIterator iterator(heap);
2158  for (HeapObject* obj = iterator.next();
2159  obj != NULL; obj = iterator.next()) {
2160  bool found_next_candidate = false;
2161  Handle<JSFunction> function;
2162  Handle<SharedFunctionInfo> shared;
2163  if (obj->IsJSFunction()) {
2164  function = Handle<JSFunction>(JSFunction::cast(obj));
2165  shared = Handle<SharedFunctionInfo>(function->shared());
2166  ASSERT(shared->allows_lazy_compilation() || shared->is_compiled());
2167  found_next_candidate = true;
2168  } else if (obj->IsSharedFunctionInfo()) {
2169  shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj));
2170  // Skip functions that we cannot compile lazily without a context,
2171  // which is not available here, because there is no closure.
2172  found_next_candidate = shared->is_compiled() ||
2173  shared->allows_lazy_compilation_without_context();
2174  }
2175  if (!found_next_candidate) continue;
2176  if (shared->script() == *script) {
2177  // If the SharedFunctionInfo found has the requested script data and
2178  // contains the source position it is a candidate.
2179  int start_position = shared->function_token_position();
2180  if (start_position == RelocInfo::kNoPosition) {
2181  start_position = shared->start_position();
2182  }
2183  if (start_position <= position &&
2184  position <= shared->end_position()) {
2185  // If there is no candidate or this function is within the current
2186  // candidate this is the new candidate.
2187  if (target.is_null()) {
2188  target_start_position = start_position;
2189  target_function = function;
2190  target = shared;
2191  } else {
2192  if (target_start_position == start_position &&
2193  shared->end_position() == target->end_position()) {
2194  // If a top-level function contains only one function
2195  // declaration the source for the top-level and the function
2196  // is the same. In that case prefer the non top-level function.
2197  if (!shared->is_toplevel()) {
2198  target_start_position = start_position;
2199  target_function = function;
2200  target = shared;
2201  }
2202  } else if (target_start_position <= start_position &&
2203  shared->end_position() <= target->end_position()) {
2204  // This containment check includes equality as a function
2205  // inside a top-level function can share either start or end
2206  // position with the top-level function.
2207  target_start_position = start_position;
2208  target_function = function;
2209  target = shared;
2210  }
2211  }
2212  }
2213  }
2214  } // End for loop.
2215  } // End no-allocation scope.
2216 
2217  if (target.is_null()) return heap->undefined_value();
2218 
2219  // There will be at least one break point when we are done.
2220  has_break_points_ = true;
2221 
2222  // If the candidate found is compiled we are done.
2223  done = target->is_compiled();
2224  if (!done) {
2225  // If the candidate is not compiled, compile it to reveal any inner
2226  // functions which might contain the requested source position. This
2227  // will compile all inner functions that cannot be compiled without a
2228  // context, because Compiler::BuildFunctionInfo checks whether the
2229  // debugger is active.
2230  Handle<Code> result = target_function.is_null()
2232  : Compiler::GetUnoptimizedCode(target_function);
2233  if (result.is_null()) return isolate_->heap()->undefined_value();
2234  }
2235  } // End while loop.
2236 
2237  return *target;
2238 }
2239 
2240 
2241 // Ensures the debug information is present for shared.
2242 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2243  Handle<JSFunction> function) {
2244  Isolate* isolate = shared->GetIsolate();
2245 
2246  // Return if we already have the debug info for shared.
2247  if (HasDebugInfo(shared)) {
2248  ASSERT(shared->is_compiled());
2249  return true;
2250  }
2251 
2252  // There will be at least one break point when we are done.
2253  has_break_points_ = true;
2254 
2255  // Ensure function is compiled. Return false if this failed.
2256  if (!function.is_null() &&
2258  return false;
2259  }
2260 
2261  // Create the debug info object.
2262  Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared);
2263 
2264  // Add debug info to the list.
2265  DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
2266  node->set_next(debug_info_list_);
2267  debug_info_list_ = node;
2268 
2269  return true;
2270 }
2271 
2272 
2273 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
2274  ASSERT(debug_info_list_ != NULL);
2275  // Run through the debug info objects to find this one and remove it.
2276  DebugInfoListNode* prev = NULL;
2277  DebugInfoListNode* current = debug_info_list_;
2278  while (current != NULL) {
2279  if (*current->debug_info() == *debug_info) {
2280  // Unlink from list. If prev is NULL we are looking at the first element.
2281  if (prev == NULL) {
2282  debug_info_list_ = current->next();
2283  } else {
2284  prev->set_next(current->next());
2285  }
2286  current->debug_info()->shared()->set_debug_info(
2287  isolate_->heap()->undefined_value());
2288  delete current;
2289 
2290  // If there are no more debug info objects there are not more break
2291  // points.
2292  has_break_points_ = debug_info_list_ != NULL;
2293 
2294  return;
2295  }
2296  // Move to next in list.
2297  prev = current;
2298  current = current->next();
2299  }
2300  UNREACHABLE();
2301 }
2302 
2303 
2304 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
2305  HandleScope scope(isolate_);
2306 
2307  PrepareForBreakPoints();
2308 
2309  // Get the executing function in which the debug break occurred.
2310  Handle<JSFunction> function(JSFunction::cast(frame->function()));
2311  Handle<SharedFunctionInfo> shared(function->shared());
2312  if (!EnsureDebugInfo(shared, function)) {
2313  // Return if we failed to retrieve the debug info.
2314  return;
2315  }
2316  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2317  Handle<Code> code(debug_info->code());
2318  Handle<Code> original_code(debug_info->original_code());
2319 #ifdef DEBUG
2320  // Get the code which is actually executing.
2321  Handle<Code> frame_code(frame->LookupCode());
2322  ASSERT(frame_code.is_identical_to(code));
2323 #endif
2324 
2325  // Find the call address in the running code. This address holds the call to
2326  // either a DebugBreakXXX or to the debug break return entry code if the
2327  // break point is still active after processing the break point.
2329 
2330  // Check if the location is at JS exit or debug break slot.
2331  bool at_js_return = false;
2332  bool break_at_js_return_active = false;
2333  bool at_debug_break_slot = false;
2334  RelocIterator it(debug_info->code());
2335  while (!it.done() && !at_js_return && !at_debug_break_slot) {
2336  if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2337  at_js_return = (it.rinfo()->pc() ==
2339  break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
2340  }
2341  if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2342  at_debug_break_slot = (it.rinfo()->pc() ==
2344  }
2345  it.next();
2346  }
2347 
2348  // Handle the jump to continue execution after break point depending on the
2349  // break location.
2350  if (at_js_return) {
2351  // If the break point as return is still active jump to the corresponding
2352  // place in the original code. If not the break point was removed during
2353  // break point processing.
2354  if (break_at_js_return_active) {
2355  addr += original_code->instruction_start() - code->instruction_start();
2356  }
2357 
2358  // Move back to where the call instruction sequence started.
2359  thread_local_.after_break_target_ =
2361  } else if (at_debug_break_slot) {
2362  // Address of where the debug break slot starts.
2364 
2365  // Continue just after the slot.
2366  thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
2367  } else if (IsDebugBreak(Assembler::target_address_at(addr, *code))) {
2368  // We now know that there is still a debug break call at the target address,
2369  // so the break point is still there and the original code will hold the
2370  // address to jump to in order to complete the call which is replaced by a
2371  // call to DebugBreakXXX.
2372 
2373  // Find the corresponding address in the original code.
2374  addr += original_code->instruction_start() - code->instruction_start();
2375 
2376  // Install jump to the call address in the original code. This will be the
2377  // call which was overwritten by the call to DebugBreakXXX.
2378  thread_local_.after_break_target_ =
2379  Assembler::target_address_at(addr, *original_code);
2380  } else {
2381  // There is no longer a break point present. Don't try to look in the
2382  // original code as the running code will have the right address. This takes
2383  // care of the case where the last break point is removed from the function
2384  // and therefore no "original code" is available.
2385  thread_local_.after_break_target_ =
2386  Assembler::target_address_at(addr, *code);
2387  }
2388 }
2389 
2390 
2391 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
2392  HandleScope scope(isolate_);
2393 
2394  // If there are no break points this cannot be break at return, as
2395  // the debugger statement and stack guard bebug break cannot be at
2396  // return.
2397  if (!has_break_points_) {
2398  return false;
2399  }
2400 
2401  PrepareForBreakPoints();
2402 
2403  // Get the executing function in which the debug break occurred.
2404  Handle<JSFunction> function(JSFunction::cast(frame->function()));
2405  Handle<SharedFunctionInfo> shared(function->shared());
2406  if (!EnsureDebugInfo(shared, function)) {
2407  // Return if we failed to retrieve the debug info.
2408  return false;
2409  }
2410  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2411  Handle<Code> code(debug_info->code());
2412 #ifdef DEBUG
2413  // Get the code which is actually executing.
2414  Handle<Code> frame_code(frame->LookupCode());
2415  ASSERT(frame_code.is_identical_to(code));
2416 #endif
2417 
2418  // Find the call address in the running code.
2420 
2421  // Check if the location is at JS return.
2422  RelocIterator it(debug_info->code());
2423  while (!it.done()) {
2424  if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2425  return (it.rinfo()->pc() ==
2427  }
2428  it.next();
2429  }
2430  return false;
2431 }
2432 
2433 
2434 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
2435  FrameDropMode mode,
2436  Object** restarter_frame_function_pointer) {
2437  if (mode != CURRENTLY_SET_MODE) {
2438  thread_local_.frame_drop_mode_ = mode;
2439  }
2440  thread_local_.break_frame_id_ = new_break_frame_id;
2441  thread_local_.restarter_frame_function_pointer_ =
2442  restarter_frame_function_pointer;
2443 }
2444 
2445 
2446 const int Debug::FramePaddingLayout::kInitialSize = 1;
2447 
2448 
2449 // Any even value bigger than kInitialSize as needed for stack scanning.
2450 const int Debug::FramePaddingLayout::kPaddingValue = kInitialSize + 1;
2451 
2452 
2453 bool Debug::IsDebugGlobal(GlobalObject* global) {
2454  return IsLoaded() && global == debug_context()->global_object();
2455 }
2456 
2457 
2458 void Debug::ClearMirrorCache() {
2459  PostponeInterruptsScope postpone(isolate_);
2460  HandleScope scope(isolate_);
2461  ASSERT(isolate_->context() == *Debug::debug_context());
2462 
2463  // Clear the mirror cache.
2464  Handle<String> function_name = isolate_->factory()->InternalizeOneByteString(
2465  STATIC_ASCII_VECTOR("ClearMirrorCache"));
2466  Handle<Object> fun(
2467  isolate_->global_object()->GetPropertyNoExceptionThrown(*function_name),
2468  isolate_);
2469  ASSERT(fun->IsJSFunction());
2470  bool caught_exception;
2471  Execution::TryCall(Handle<JSFunction>::cast(fun),
2472  Handle<JSObject>(Debug::debug_context()->global_object()),
2473  0, NULL, &caught_exception);
2474 }
2475 
2476 
2477 void Debug::CreateScriptCache() {
2478  Heap* heap = isolate_->heap();
2479  HandleScope scope(isolate_);
2480 
2481  // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
2482  // rid of all the cached script wrappers and the second gets rid of the
2483  // scripts which are no longer referenced. The second also sweeps precisely,
2484  // which saves us doing yet another GC to make the heap iterable.
2485  heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache");
2486  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
2487  "Debug::CreateScriptCache");
2488 
2489  ASSERT(script_cache_ == NULL);
2490  script_cache_ = new ScriptCache(isolate_);
2491 
2492  // Scan heap for Script objects.
2493  int count = 0;
2494  HeapIterator iterator(heap);
2495  DisallowHeapAllocation no_allocation;
2496 
2497  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
2498  if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
2499  script_cache_->Add(Handle<Script>(Script::cast(obj)));
2500  count++;
2501  }
2502  }
2503 }
2504 
2505 
2506 void Debug::DestroyScriptCache() {
2507  // Get rid of the script cache if it was created.
2508  if (script_cache_ != NULL) {
2509  delete script_cache_;
2510  script_cache_ = NULL;
2511  }
2512 }
2513 
2514 
2515 void Debug::AddScriptToScriptCache(Handle<Script> script) {
2516  if (script_cache_ != NULL) {
2517  script_cache_->Add(script);
2518  }
2519 }
2520 
2521 
2522 Handle<FixedArray> Debug::GetLoadedScripts() {
2523  // Create and fill the script cache when the loaded scripts is requested for
2524  // the first time.
2525  if (script_cache_ == NULL) {
2526  CreateScriptCache();
2527  }
2528 
2529  // If the script cache is not active just return an empty array.
2530  ASSERT(script_cache_ != NULL);
2531  if (script_cache_ == NULL) {
2532  isolate_->factory()->NewFixedArray(0);
2533  }
2534 
2535  // Perform GC to get unreferenced scripts evicted from the cache before
2536  // returning the content.
2537  isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
2538  "Debug::GetLoadedScripts");
2539 
2540  // Get the scripts from the cache.
2541  return script_cache_->GetScripts();
2542 }
2543 
2544 
2545 void Debug::RecordEvalCaller(Handle<Script> script) {
2546  script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
2547  // For eval scripts add information on the function from which eval was
2548  // called.
2549  StackTraceFrameIterator it(script->GetIsolate());
2550  if (!it.done()) {
2551  script->set_eval_from_shared(it.frame()->function()->shared());
2552  Code* code = it.frame()->LookupCode();
2553  int offset = static_cast<int>(
2554  it.frame()->pc() - code->instruction_start());
2555  script->set_eval_from_instructions_offset(Smi::FromInt(offset));
2556  }
2557 }
2558 
2559 
2560 void Debug::AfterGarbageCollection() {
2561  // Generate events for collected scripts.
2562  if (script_cache_ != NULL) {
2563  script_cache_->ProcessCollectedScripts();
2564  }
2565 }
2566 
2567 
2568 Debugger::Debugger(Isolate* isolate)
2569  : debugger_access_(isolate->debugger_access()),
2570  event_listener_(Handle<Object>()),
2571  event_listener_data_(Handle<Object>()),
2572  compiling_natives_(false),
2573  is_loading_debugger_(false),
2574  live_edit_enabled_(true),
2575  never_unload_debugger_(false),
2576  force_debugger_active_(false),
2577  message_handler_(NULL),
2578  debugger_unload_pending_(false),
2579  host_dispatch_handler_(NULL),
2580  debug_message_dispatch_handler_(NULL),
2581  message_dispatch_helper_thread_(NULL),
2582  host_dispatch_period_(TimeDelta::FromMilliseconds(100)),
2583  agent_(NULL),
2584  command_queue_(isolate->logger(), kQueueInitialSize),
2585  command_received_(0),
2586  event_command_queue_(isolate->logger(), kQueueInitialSize),
2587  isolate_(isolate) {
2588 }
2589 
2590 
2591 Debugger::~Debugger() {}
2592 
2593 
2594 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
2595  int argc,
2596  Handle<Object> argv[],
2597  bool* caught_exception) {
2598  ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2599 
2600  // Create the execution state object.
2601  Handle<String> constructor_str =
2602  isolate_->factory()->InternalizeUtf8String(constructor_name);
2603  ASSERT(!constructor_str.is_null());
2604  Handle<Object> constructor(
2605  isolate_->global_object()->GetPropertyNoExceptionThrown(*constructor_str),
2606  isolate_);
2607  ASSERT(constructor->IsJSFunction());
2608  if (!constructor->IsJSFunction()) {
2609  *caught_exception = true;
2610  return isolate_->factory()->undefined_value();
2611  }
2612  Handle<Object> js_object = Execution::TryCall(
2613  Handle<JSFunction>::cast(constructor),
2614  Handle<JSObject>(isolate_->debug()->debug_context()->global_object()),
2615  argc,
2616  argv,
2617  caught_exception);
2618  return js_object;
2619 }
2620 
2621 
2622 Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
2623  // Create the execution state object.
2624  Handle<Object> break_id = isolate_->factory()->NewNumberFromInt(
2625  isolate_->debug()->break_id());
2626  Handle<Object> argv[] = { break_id };
2627  return MakeJSObject(CStrVector("MakeExecutionState"),
2628  ARRAY_SIZE(argv),
2629  argv,
2630  caught_exception);
2631 }
2632 
2633 
2634 Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
2635  Handle<Object> break_points_hit,
2636  bool* caught_exception) {
2637  // Create the new break event object.
2638  Handle<Object> argv[] = { exec_state, break_points_hit };
2639  return MakeJSObject(CStrVector("MakeBreakEvent"),
2640  ARRAY_SIZE(argv),
2641  argv,
2642  caught_exception);
2643 }
2644 
2645 
2646 Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
2647  Handle<Object> exception,
2648  bool uncaught,
2649  bool* caught_exception) {
2650  Factory* factory = isolate_->factory();
2651  // Create the new exception event object.
2652  Handle<Object> argv[] = { exec_state,
2653  exception,
2654  factory->ToBoolean(uncaught) };
2655  return MakeJSObject(CStrVector("MakeExceptionEvent"),
2656  ARRAY_SIZE(argv),
2657  argv,
2658  caught_exception);
2659 }
2660 
2661 
2662 Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
2663  bool* caught_exception) {
2664  // Create the new function event object.
2665  Handle<Object> argv[] = { function };
2666  return MakeJSObject(CStrVector("MakeNewFunctionEvent"),
2667  ARRAY_SIZE(argv),
2668  argv,
2669  caught_exception);
2670 }
2671 
2672 
2673 Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
2674  bool before,
2675  bool* caught_exception) {
2676  Factory* factory = isolate_->factory();
2677  // Create the compile event object.
2678  Handle<Object> exec_state = MakeExecutionState(caught_exception);
2679  Handle<Object> script_wrapper = GetScriptWrapper(script);
2680  Handle<Object> argv[] = { exec_state,
2681  script_wrapper,
2682  factory->ToBoolean(before) };
2683  return MakeJSObject(CStrVector("MakeCompileEvent"),
2684  ARRAY_SIZE(argv),
2685  argv,
2686  caught_exception);
2687 }
2688 
2689 
2690 Handle<Object> Debugger::MakeScriptCollectedEvent(int id,
2691  bool* caught_exception) {
2692  // Create the script collected event object.
2693  Handle<Object> exec_state = MakeExecutionState(caught_exception);
2694  Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_);
2695  Handle<Object> argv[] = { exec_state, id_object };
2696 
2697  return MakeJSObject(CStrVector("MakeScriptCollectedEvent"),
2698  ARRAY_SIZE(argv),
2699  argv,
2700  caught_exception);
2701 }
2702 
2703 
2704 void Debugger::OnException(Handle<Object> exception, bool uncaught) {
2705  HandleScope scope(isolate_);
2706  Debug* debug = isolate_->debug();
2707 
2708  // Bail out based on state or if there is no listener for this event
2709  if (debug->InDebugger()) return;
2710  if (!Debugger::EventActive(v8::Exception)) return;
2711 
2712  // Bail out if exception breaks are not active
2713  if (uncaught) {
2714  // Uncaught exceptions are reported by either flags.
2715  if (!(debug->break_on_uncaught_exception() ||
2716  debug->break_on_exception())) return;
2717  } else {
2718  // Caught exceptions are reported is activated.
2719  if (!debug->break_on_exception()) return;
2720  }
2721 
2722  // Enter the debugger.
2723  EnterDebugger debugger(isolate_);
2724  if (debugger.FailedToEnter()) return;
2725 
2726  // Clear all current stepping setup.
2727  debug->ClearStepping();
2728  // Create the event data object.
2729  bool caught_exception = false;
2730  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2731  Handle<Object> event_data;
2732  if (!caught_exception) {
2733  event_data = MakeExceptionEvent(exec_state, exception, uncaught,
2734  &caught_exception);
2735  }
2736  // Bail out and don't call debugger if exception.
2737  if (caught_exception) {
2738  return;
2739  }
2740 
2741  // Process debug event.
2742  ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
2743  // Return to continue execution from where the exception was thrown.
2744 }
2745 
2746 
2747 void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
2748  bool auto_continue) {
2749  HandleScope scope(isolate_);
2750 
2751  // Debugger has already been entered by caller.
2752  ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2753 
2754  // Bail out if there is no listener for this event
2755  if (!Debugger::EventActive(v8::Break)) return;
2756 
2757  // Debugger must be entered in advance.
2758  ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2759 
2760  // Create the event data object.
2761  bool caught_exception = false;
2762  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2763  Handle<Object> event_data;
2764  if (!caught_exception) {
2765  event_data = MakeBreakEvent(exec_state, break_points_hit,
2766  &caught_exception);
2767  }
2768  // Bail out and don't call debugger if exception.
2769  if (caught_exception) {
2770  return;
2771  }
2772 
2773  // Process debug event.
2774  ProcessDebugEvent(v8::Break,
2775  Handle<JSObject>::cast(event_data),
2776  auto_continue);
2777 }
2778 
2779 
2780 void Debugger::OnBeforeCompile(Handle<Script> script) {
2781  HandleScope scope(isolate_);
2782 
2783  // Bail out based on state or if there is no listener for this event
2784  if (isolate_->debug()->InDebugger()) return;
2785  if (compiling_natives()) return;
2786  if (!EventActive(v8::BeforeCompile)) return;
2787 
2788  // Enter the debugger.
2789  EnterDebugger debugger(isolate_);
2790  if (debugger.FailedToEnter()) return;
2791 
2792  // Create the event data object.
2793  bool caught_exception = false;
2794  Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception);
2795  // Bail out and don't call debugger if exception.
2796  if (caught_exception) {
2797  return;
2798  }
2799 
2800  // Process debug event.
2801  ProcessDebugEvent(v8::BeforeCompile,
2802  Handle<JSObject>::cast(event_data),
2803  true);
2804 }
2805 
2806 
2807 // Handle debugger actions when a new script is compiled.
2808 void Debugger::OnAfterCompile(Handle<Script> script,
2809  AfterCompileFlags after_compile_flags) {
2810  HandleScope scope(isolate_);
2811  Debug* debug = isolate_->debug();
2812 
2813  // Add the newly compiled script to the script cache.
2814  debug->AddScriptToScriptCache(script);
2815 
2816  // No more to do if not debugging.
2817  if (!IsDebuggerActive()) return;
2818 
2819  // No compile events while compiling natives.
2820  if (compiling_natives()) return;
2821 
2822  // Store whether in debugger before entering debugger.
2823  bool in_debugger = debug->InDebugger();
2824 
2825  // Enter the debugger.
2826  EnterDebugger debugger(isolate_);
2827  if (debugger.FailedToEnter()) return;
2828 
2829  // If debugging there might be script break points registered for this
2830  // script. Make sure that these break points are set.
2831 
2832  // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js).
2833  Handle<String> update_script_break_points_string =
2834  isolate_->factory()->InternalizeOneByteString(
2835  STATIC_ASCII_VECTOR("UpdateScriptBreakPoints"));
2836  Handle<Object> update_script_break_points =
2837  Handle<Object>(
2838  debug->debug_context()->global_object()->GetPropertyNoExceptionThrown(
2839  *update_script_break_points_string),
2840  isolate_);
2841  if (!update_script_break_points->IsJSFunction()) {
2842  return;
2843  }
2844  ASSERT(update_script_break_points->IsJSFunction());
2845 
2846  // Wrap the script object in a proper JS object before passing it
2847  // to JavaScript.
2848  Handle<JSValue> wrapper = GetScriptWrapper(script);
2849 
2850  // Call UpdateScriptBreakPoints expect no exceptions.
2851  bool caught_exception;
2852  Handle<Object> argv[] = { wrapper };
2853  Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
2854  isolate_->js_builtins_object(),
2855  ARRAY_SIZE(argv),
2856  argv,
2857  &caught_exception);
2858  if (caught_exception) {
2859  return;
2860  }
2861  // Bail out based on state or if there is no listener for this event
2862  if (in_debugger && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return;
2863  if (!Debugger::EventActive(v8::AfterCompile)) return;
2864 
2865  // Create the compile state object.
2866  Handle<Object> event_data = MakeCompileEvent(script,
2867  false,
2868  &caught_exception);
2869  // Bail out and don't call debugger if exception.
2870  if (caught_exception) {
2871  return;
2872  }
2873  // Process debug event.
2874  ProcessDebugEvent(v8::AfterCompile,
2875  Handle<JSObject>::cast(event_data),
2876  true);
2877 }
2878 
2879 
2880 void Debugger::OnScriptCollected(int id) {
2881  HandleScope scope(isolate_);
2882 
2883  // No more to do if not debugging.
2884  if (isolate_->debug()->InDebugger()) return;
2885  if (!IsDebuggerActive()) return;
2886  if (!Debugger::EventActive(v8::ScriptCollected)) return;
2887 
2888  // Enter the debugger.
2889  EnterDebugger debugger(isolate_);
2890  if (debugger.FailedToEnter()) return;
2891 
2892  // Create the script collected state object.
2893  bool caught_exception = false;
2894  Handle<Object> event_data = MakeScriptCollectedEvent(id,
2895  &caught_exception);
2896  // Bail out and don't call debugger if exception.
2897  if (caught_exception) {
2898  return;
2899  }
2900 
2901  // Process debug event.
2902  ProcessDebugEvent(v8::ScriptCollected,
2903  Handle<JSObject>::cast(event_data),
2904  true);
2905 }
2906 
2907 
2908 void Debugger::ProcessDebugEvent(v8::DebugEvent event,
2909  Handle<JSObject> event_data,
2910  bool auto_continue) {
2911  HandleScope scope(isolate_);
2912 
2913  // Clear any pending debug break if this is a real break.
2914  if (!auto_continue) {
2915  isolate_->debug()->clear_interrupt_pending(DEBUGBREAK);
2916  }
2917 
2918  // Create the execution state.
2919  bool caught_exception = false;
2920  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2921  if (caught_exception) {
2922  return;
2923  }
2924  // First notify the message handler if any.
2925  if (message_handler_ != NULL) {
2926  NotifyMessageHandler(event,
2927  Handle<JSObject>::cast(exec_state),
2928  event_data,
2929  auto_continue);
2930  }
2931  // Notify registered debug event listener. This can be either a C or
2932  // a JavaScript function. Don't call event listener for v8::Break
2933  // here, if it's only a debug command -- they will be processed later.
2934  if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
2935  CallEventCallback(event, exec_state, event_data, NULL);
2936  }
2937  // Process pending debug commands.
2938  if (event == v8::Break) {
2939  while (!event_command_queue_.IsEmpty()) {
2940  CommandMessage command = event_command_queue_.Get();
2941  if (!event_listener_.is_null()) {
2942  CallEventCallback(v8::BreakForCommand,
2943  exec_state,
2944  event_data,
2945  command.client_data());
2946  }
2947  command.Dispose();
2948  }
2949  }
2950 }
2951 
2952 
2953 void Debugger::CallEventCallback(v8::DebugEvent event,
2954  Handle<Object> exec_state,
2955  Handle<Object> event_data,
2956  v8::Debug::ClientData* client_data) {
2957  if (event_listener_->IsForeign()) {
2958  CallCEventCallback(event, exec_state, event_data, client_data);
2959  } else {
2960  CallJSEventCallback(event, exec_state, event_data);
2961  }
2962 }
2963 
2964 
2965 void Debugger::CallCEventCallback(v8::DebugEvent event,
2966  Handle<Object> exec_state,
2967  Handle<Object> event_data,
2968  v8::Debug::ClientData* client_data) {
2969  Handle<Foreign> callback_obj(Handle<Foreign>::cast(event_listener_));
2970  v8::Debug::EventCallback2 callback =
2971  FUNCTION_CAST<v8::Debug::EventCallback2>(
2972  callback_obj->foreign_address());
2973  EventDetailsImpl event_details(
2974  event,
2975  Handle<JSObject>::cast(exec_state),
2976  Handle<JSObject>::cast(event_data),
2977  event_listener_data_,
2978  client_data);
2979  callback(event_details);
2980 }
2981 
2982 
2983 void Debugger::CallJSEventCallback(v8::DebugEvent event,
2984  Handle<Object> exec_state,
2985  Handle<Object> event_data) {
2986  ASSERT(event_listener_->IsJSFunction());
2987  Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
2988 
2989  // Invoke the JavaScript debug event listener.
2990  Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
2991  exec_state,
2992  event_data,
2993  event_listener_data_ };
2994  bool caught_exception;
2995  Execution::TryCall(fun,
2996  isolate_->global_object(),
2997  ARRAY_SIZE(argv),
2998  argv,
2999  &caught_exception);
3000  // Silently ignore exceptions from debug event listeners.
3001 }
3002 
3003 
3004 Handle<Context> Debugger::GetDebugContext() {
3005  never_unload_debugger_ = true;
3006  EnterDebugger debugger(isolate_);
3007  return isolate_->debug()->debug_context();
3008 }
3009 
3010 
3011 void Debugger::UnloadDebugger() {
3012  Debug* debug = isolate_->debug();
3013 
3014  // Make sure that there are no breakpoints left.
3015  debug->ClearAllBreakPoints();
3016 
3017  // Unload the debugger if feasible.
3018  if (!never_unload_debugger_) {
3019  debug->Unload();
3020  }
3021 
3022  // Clear the flag indicating that the debugger should be unloaded.
3023  debugger_unload_pending_ = false;
3024 }
3025 
3026 
3027 void Debugger::NotifyMessageHandler(v8::DebugEvent event,
3028  Handle<JSObject> exec_state,
3029  Handle<JSObject> event_data,
3030  bool auto_continue) {
3031  v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_);
3032  HandleScope scope(isolate_);
3033 
3034  if (!isolate_->debug()->Load()) return;
3035 
3036  // Process the individual events.
3037  bool sendEventMessage = false;
3038  switch (event) {
3039  case v8::Break:
3040  case v8::BreakForCommand:
3041  sendEventMessage = !auto_continue;
3042  break;
3043  case v8::Exception:
3044  sendEventMessage = true;
3045  break;
3046  case v8::BeforeCompile:
3047  break;
3048  case v8::AfterCompile:
3049  sendEventMessage = true;
3050  break;
3051  case v8::ScriptCollected:
3052  sendEventMessage = true;
3053  break;
3054  case v8::NewFunction:
3055  break;
3056  default:
3057  UNREACHABLE();
3058  }
3059 
3060  // The debug command interrupt flag might have been set when the command was
3061  // added. It should be enough to clear the flag only once while we are in the
3062  // debugger.
3063  ASSERT(isolate_->debug()->InDebugger());
3064  isolate_->stack_guard()->Continue(DEBUGCOMMAND);
3065 
3066  // Notify the debugger that a debug event has occurred unless auto continue is
3067  // active in which case no event is send.
3068  if (sendEventMessage) {
3069  MessageImpl message = MessageImpl::NewEvent(
3070  event,
3071  auto_continue,
3072  Handle<JSObject>::cast(exec_state),
3073  Handle<JSObject>::cast(event_data));
3074  InvokeMessageHandler(message);
3075  }
3076 
3077  // If auto continue don't make the event cause a break, but process messages
3078  // in the queue if any. For script collected events don't even process
3079  // messages in the queue as the execution state might not be what is expected
3080  // by the client.
3081  if ((auto_continue && !HasCommands()) || event == v8::ScriptCollected) {
3082  return;
3083  }
3084 
3085  v8::TryCatch try_catch;
3086 
3087  // DebugCommandProcessor goes here.
3088  v8::Local<v8::Object> cmd_processor;
3089  {
3090  v8::Local<v8::Object> api_exec_state =
3091  v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
3093  isolate, "debugCommandProcessor");
3095  v8::Local<v8::Function>::Cast(api_exec_state->Get(fun_name));
3096 
3097  v8::Handle<v8::Boolean> running = v8::Boolean::New(isolate, auto_continue);
3098  static const int kArgc = 1;
3099  v8::Handle<Value> argv[kArgc] = { running };
3100  cmd_processor = v8::Local<v8::Object>::Cast(
3101  fun->Call(api_exec_state, kArgc, argv));
3102  if (try_catch.HasCaught()) {
3103  PrintLn(try_catch.Exception());
3104  return;
3105  }
3106  }
3107 
3108  bool running = auto_continue;
3109 
3110  // Process requests from the debugger.
3111  while (true) {
3112  // Wait for new command in the queue.
3113  if (Debugger::host_dispatch_handler_) {
3114  // In case there is a host dispatch - do periodic dispatches.
3115  if (!command_received_.WaitFor(host_dispatch_period_)) {
3116  // Timout expired, do the dispatch.
3117  Debugger::host_dispatch_handler_();
3118  continue;
3119  }
3120  } else {
3121  // In case there is no host dispatch - just wait.
3122  command_received_.Wait();
3123  }
3124 
3125  // Get the command from the queue.
3126  CommandMessage command = command_queue_.Get();
3127  isolate_->logger()->DebugTag(
3128  "Got request from command queue, in interactive loop.");
3129  if (!Debugger::IsDebuggerActive()) {
3130  // Delete command text and user data.
3131  command.Dispose();
3132  return;
3133  }
3134 
3135  // Invoke JavaScript to process the debug request.
3136  v8::Local<v8::String> fun_name;
3138  v8::Local<v8::Value> request;
3139  v8::TryCatch try_catch;
3140  fun_name = v8::String::NewFromUtf8(isolate, "processDebugRequest");
3141  fun = v8::Local<v8::Function>::Cast(cmd_processor->Get(fun_name));
3142 
3143  request = v8::String::NewFromTwoByte(isolate, command.text().start(),
3145  command.text().length());
3146  static const int kArgc = 1;
3147  v8::Handle<Value> argv[kArgc] = { request };
3148  v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
3149 
3150  // Get the response.
3151  v8::Local<v8::String> response;
3152  if (!try_catch.HasCaught()) {
3153  // Get response string.
3154  if (!response_val->IsUndefined()) {
3155  response = v8::Local<v8::String>::Cast(response_val);
3156  } else {
3157  response = v8::String::NewFromUtf8(isolate, "");
3158  }
3159 
3160  // Log the JSON request/response.
3161  if (FLAG_trace_debug_json) {
3162  PrintLn(request);
3163  PrintLn(response);
3164  }
3165 
3166  // Get the running state.
3167  fun_name = v8::String::NewFromUtf8(isolate, "isRunning");
3168  fun = v8::Local<v8::Function>::Cast(cmd_processor->Get(fun_name));
3169  static const int kArgc = 1;
3170  v8::Handle<Value> argv[kArgc] = { response };
3171  v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv);
3172  if (!try_catch.HasCaught()) {
3173  running = running_val->ToBoolean()->Value();
3174  }
3175  } else {
3176  // In case of failure the result text is the exception text.
3177  response = try_catch.Exception()->ToString();
3178  }
3179 
3180  // Return the result.
3181  MessageImpl message = MessageImpl::NewResponse(
3182  event,
3183  running,
3184  Handle<JSObject>::cast(exec_state),
3185  Handle<JSObject>::cast(event_data),
3186  Handle<String>(Utils::OpenHandle(*response)),
3187  command.client_data());
3188  InvokeMessageHandler(message);
3189  command.Dispose();
3190 
3191  // Return from debug event processing if either the VM is put into the
3192  // running state (through a continue command) or auto continue is active
3193  // and there are no more commands queued.
3194  if (running && !HasCommands()) {
3195  return;
3196  }
3197  }
3198 }
3199 
3200 
3201 void Debugger::SetEventListener(Handle<Object> callback,
3202  Handle<Object> data) {
3203  HandleScope scope(isolate_);
3204  GlobalHandles* global_handles = isolate_->global_handles();
3205 
3206  // Clear the global handles for the event listener and the event listener data
3207  // object.
3208  if (!event_listener_.is_null()) {
3210  reinterpret_cast<Object**>(event_listener_.location()));
3211  event_listener_ = Handle<Object>();
3212  }
3213  if (!event_listener_data_.is_null()) {
3215  reinterpret_cast<Object**>(event_listener_data_.location()));
3216  event_listener_data_ = Handle<Object>();
3217  }
3218 
3219  // If there is a new debug event listener register it together with its data
3220  // object.
3221  if (!callback->IsUndefined() && !callback->IsNull()) {
3222  event_listener_ = Handle<Object>::cast(
3223  global_handles->Create(*callback));
3224  if (data.is_null()) {
3225  data = isolate_->factory()->undefined_value();
3226  }
3227  event_listener_data_ = Handle<Object>::cast(
3228  global_handles->Create(*data));
3229  }
3230 
3231  ListenersChanged();
3232 }
3233 
3234 
3235 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
3236  LockGuard<RecursiveMutex> with(debugger_access_);
3237 
3238  message_handler_ = handler;
3239  ListenersChanged();
3240  if (handler == NULL) {
3241  // Send an empty command to the debugger if in a break to make JavaScript
3242  // run again if the debugger is closed.
3243  if (isolate_->debug()->InDebugger()) {
3244  ProcessCommand(Vector<const uint16_t>::empty());
3245  }
3246  }
3247 }
3248 
3249 
3250 void Debugger::ListenersChanged() {
3251  if (IsDebuggerActive()) {
3252  // Disable the compilation cache when the debugger is active.
3253  isolate_->compilation_cache()->Disable();
3254  debugger_unload_pending_ = false;
3255  } else {
3256  isolate_->compilation_cache()->Enable();
3257  // Unload the debugger if event listener and message handler cleared.
3258  // Schedule this for later, because we may be in non-V8 thread.
3259  debugger_unload_pending_ = true;
3260  }
3261 }
3262 
3263 
3264 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
3265  TimeDelta period) {
3266  host_dispatch_handler_ = handler;
3267  host_dispatch_period_ = period;
3268 }
3269 
3270 
3271 void Debugger::SetDebugMessageDispatchHandler(
3272  v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) {
3273  LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3274  debug_message_dispatch_handler_ = handler;
3275 
3276  if (provide_locker && message_dispatch_helper_thread_ == NULL) {
3277  message_dispatch_helper_thread_ = new MessageDispatchHelperThread(isolate_);
3278  message_dispatch_helper_thread_->Start();
3279  }
3280 }
3281 
3282 
3283 // Calls the registered debug message handler. This callback is part of the
3284 // public API.
3285 void Debugger::InvokeMessageHandler(MessageImpl message) {
3286  LockGuard<RecursiveMutex> with(debugger_access_);
3287 
3288  if (message_handler_ != NULL) {
3289  message_handler_(message);
3290  }
3291 }
3292 
3293 
3294 // Puts a command coming from the public API on the queue. Creates
3295 // a copy of the command string managed by the debugger. Up to this
3296 // point, the command data was managed by the API client. Called
3297 // by the API client thread.
3298 void Debugger::ProcessCommand(Vector<const uint16_t> command,
3299  v8::Debug::ClientData* client_data) {
3300  // Need to cast away const.
3301  CommandMessage message = CommandMessage::New(
3302  Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
3303  command.length()),
3304  client_data);
3305  isolate_->logger()->DebugTag("Put command on command_queue.");
3306  command_queue_.Put(message);
3307  command_received_.Signal();
3308 
3309  // Set the debug command break flag to have the command processed.
3310  if (!isolate_->debug()->InDebugger()) {
3311  isolate_->stack_guard()->DebugCommand();
3312  }
3313 
3314  MessageDispatchHelperThread* dispatch_thread;
3315  {
3316  LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3317  dispatch_thread = message_dispatch_helper_thread_;
3318  }
3319 
3320  if (dispatch_thread == NULL) {
3321  CallMessageDispatchHandler();
3322  } else {
3323  dispatch_thread->Schedule();
3324  }
3325 }
3326 
3327 
3328 bool Debugger::HasCommands() {
3329  return !command_queue_.IsEmpty();
3330 }
3331 
3332 
3333 void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
3334  CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
3335  event_command_queue_.Put(message);
3336 
3337  // Set the debug command break flag to have the command processed.
3338  if (!isolate_->debug()->InDebugger()) {
3339  isolate_->stack_guard()->DebugCommand();
3340  }
3341 }
3342 
3343 
3344 bool Debugger::IsDebuggerActive() {
3345  LockGuard<RecursiveMutex> with(debugger_access_);
3346 
3347  return message_handler_ != NULL ||
3348  !event_listener_.is_null() ||
3349  force_debugger_active_;
3350 }
3351 
3352 
3353 Handle<Object> Debugger::Call(Handle<JSFunction> fun,
3354  Handle<Object> data,
3355  bool* pending_exception) {
3356  // When calling functions in the debugger prevent it from beeing unloaded.
3357  Debugger::never_unload_debugger_ = true;
3358 
3359  // Enter the debugger.
3360  EnterDebugger debugger(isolate_);
3361  if (debugger.FailedToEnter()) {
3362  return isolate_->factory()->undefined_value();
3363  }
3364 
3365  // Create the execution state.
3366  bool caught_exception = false;
3367  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
3368  if (caught_exception) {
3369  return isolate_->factory()->undefined_value();
3370  }
3371 
3372  Handle<Object> argv[] = { exec_state, data };
3373  Handle<Object> result = Execution::Call(
3374  isolate_,
3375  fun,
3376  Handle<Object>(isolate_->debug()->debug_context_->global_proxy(),
3377  isolate_),
3378  ARRAY_SIZE(argv),
3379  argv,
3380  pending_exception);
3381  return result;
3382 }
3383 
3384 
3385 static void StubMessageHandler2(const v8::Debug::Message& message) {
3386  // Simply ignore message.
3387 }
3388 
3389 
3390 bool Debugger::StartAgent(const char* name, int port,
3391  bool wait_for_connection) {
3392  if (wait_for_connection) {
3393  // Suspend V8 if it is already running or set V8 to suspend whenever
3394  // it starts.
3395  // Provide stub message handler; V8 auto-continues each suspend
3396  // when there is no message handler; we doesn't need it.
3397  // Once become suspended, V8 will stay so indefinitely long, until remote
3398  // debugger connects and issues "continue" command.
3399  Debugger::message_handler_ = StubMessageHandler2;
3401  }
3402 
3403  if (agent_ == NULL) {
3404  agent_ = new DebuggerAgent(isolate_, name, port);
3405  agent_->Start();
3406  }
3407  return true;
3408 }
3409 
3410 
3411 void Debugger::StopAgent() {
3412  if (agent_ != NULL) {
3413  agent_->Shutdown();
3414  agent_->Join();
3415  delete agent_;
3416  agent_ = NULL;
3417  }
3418 }
3419 
3420 
3421 void Debugger::WaitForAgent() {
3422  if (agent_ != NULL)
3423  agent_->WaitUntilListening();
3424 }
3425 
3426 
3427 void Debugger::CallMessageDispatchHandler() {
3429  {
3430  LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3431  handler = Debugger::debug_message_dispatch_handler_;
3432  }
3433  if (handler != NULL) {
3434  handler();
3435  }
3436 }
3437 
3438 
3439 EnterDebugger::EnterDebugger(Isolate* isolate)
3440  : isolate_(isolate),
3441  prev_(isolate_->debug()->debugger_entry()),
3442  it_(isolate_),
3443  has_js_frames_(!it_.done()),
3444  save_(isolate_) {
3445  Debug* debug = isolate_->debug();
3446  ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT));
3447  ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK));
3448 
3449  // Link recursive debugger entry.
3450  debug->set_debugger_entry(this);
3451 
3452  // Store the previous break id and frame id.
3453  break_id_ = debug->break_id();
3454  break_frame_id_ = debug->break_frame_id();
3455 
3456  // Create the new break info. If there is no JavaScript frames there is no
3457  // break frame id.
3458  if (has_js_frames_) {
3459  debug->NewBreak(it_.frame()->id());
3460  } else {
3461  debug->NewBreak(StackFrame::NO_ID);
3462  }
3463 
3464  // Make sure that debugger is loaded and enter the debugger context.
3465  load_failed_ = !debug->Load();
3466  if (!load_failed_) {
3467  // NOTE the member variable save which saves the previous context before
3468  // this change.
3469  isolate_->set_context(*debug->debug_context());
3470  }
3471 }
3472 
3473 
3474 EnterDebugger::~EnterDebugger() {
3475  Debug* debug = isolate_->debug();
3476 
3477  // Restore to the previous break state.
3478  debug->SetBreak(break_frame_id_, break_id_);
3479 
3480  // Check for leaving the debugger.
3481  if (!load_failed_ && prev_ == NULL) {
3482  // Clear mirror cache when leaving the debugger. Skip this if there is a
3483  // pending exception as clearing the mirror cache calls back into
3484  // JavaScript. This can happen if the v8::Debug::Call is used in which
3485  // case the exception should end up in the calling code.
3486  if (!isolate_->has_pending_exception()) {
3487  // Try to avoid any pending debug break breaking in the clear mirror
3488  // cache JavaScript code.
3489  if (isolate_->stack_guard()->IsDebugBreak()) {
3490  debug->set_interrupts_pending(DEBUGBREAK);
3491  isolate_->stack_guard()->Continue(DEBUGBREAK);
3492  }
3493  debug->ClearMirrorCache();
3494  }
3495 
3496  // Request preemption and debug break when leaving the last debugger entry
3497  // if any of these where recorded while debugging.
3498  if (debug->is_interrupt_pending(PREEMPT)) {
3499  // This re-scheduling of preemption is to avoid starvation in some
3500  // debugging scenarios.
3501  debug->clear_interrupt_pending(PREEMPT);
3502  isolate_->stack_guard()->Preempt();
3503  }
3504  if (debug->is_interrupt_pending(DEBUGBREAK)) {
3505  debug->clear_interrupt_pending(DEBUGBREAK);
3506  isolate_->stack_guard()->DebugBreak();
3507  }
3508 
3509  // If there are commands in the queue when leaving the debugger request
3510  // that these commands are processed.
3511  if (isolate_->debugger()->HasCommands()) {
3512  isolate_->stack_guard()->DebugCommand();
3513  }
3514 
3515  // If leaving the debugger with the debugger no longer active unload it.
3516  if (!isolate_->debugger()->IsDebuggerActive()) {
3517  isolate_->debugger()->UnloadDebugger();
3518  }
3519  }
3520 
3521  // Leaving this debugger entry.
3522  debug->set_debugger_entry(prev_);
3523 }
3524 
3525 
3526 MessageImpl MessageImpl::NewEvent(DebugEvent event,
3527  bool running,
3528  Handle<JSObject> exec_state,
3529  Handle<JSObject> event_data) {
3530  MessageImpl message(true, event, running,
3531  exec_state, event_data, Handle<String>(), NULL);
3532  return message;
3533 }
3534 
3535 
3536 MessageImpl MessageImpl::NewResponse(DebugEvent event,
3537  bool running,
3538  Handle<JSObject> exec_state,
3539  Handle<JSObject> event_data,
3540  Handle<String> response_json,
3541  v8::Debug::ClientData* client_data) {
3542  MessageImpl message(false, event, running,
3543  exec_state, event_data, response_json, client_data);
3544  return message;
3545 }
3546 
3547 
3548 MessageImpl::MessageImpl(bool is_event,
3549  DebugEvent event,
3550  bool running,
3551  Handle<JSObject> exec_state,
3552  Handle<JSObject> event_data,
3553  Handle<String> response_json,
3554  v8::Debug::ClientData* client_data)
3555  : is_event_(is_event),
3556  event_(event),
3557  running_(running),
3558  exec_state_(exec_state),
3559  event_data_(event_data),
3560  response_json_(response_json),
3561  client_data_(client_data) {}
3562 
3563 
3564 bool MessageImpl::IsEvent() const {
3565  return is_event_;
3566 }
3567 
3568 
3569 bool MessageImpl::IsResponse() const {
3570  return !is_event_;
3571 }
3572 
3573 
3574 DebugEvent MessageImpl::GetEvent() const {
3575  return event_;
3576 }
3577 
3578 
3579 bool MessageImpl::WillStartRunning() const {
3580  return running_;
3581 }
3582 
3583 
3584 v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
3585  return v8::Utils::ToLocal(exec_state_);
3586 }
3587 
3588 
3589 v8::Isolate* MessageImpl::GetIsolate() const {
3590  return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
3591 }
3592 
3593 
3594 v8::Handle<v8::Object> MessageImpl::GetEventData() const {
3595  return v8::Utils::ToLocal(event_data_);
3596 }
3597 
3598 
3599 v8::Handle<v8::String> MessageImpl::GetJSON() const {
3601  reinterpret_cast<v8::Isolate*>(event_data_->GetIsolate()));
3602 
3603  if (IsEvent()) {
3604  // Call toJSONProtocol on the debug event object.
3605  Handle<Object> fun = GetProperty(event_data_, "toJSONProtocol");
3606  if (!fun->IsJSFunction()) {
3607  return v8::Handle<v8::String>();
3608  }
3609  bool caught_exception;
3610  Handle<Object> json = Execution::TryCall(Handle<JSFunction>::cast(fun),
3611  event_data_,
3612  0, NULL, &caught_exception);
3613  if (caught_exception || !json->IsString()) {
3614  return v8::Handle<v8::String>();
3615  }
3616  return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
3617  } else {
3618  return v8::Utils::ToLocal(response_json_);
3619  }
3620 }
3621 
3622 
3623 v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
3624  Isolate* isolate = event_data_->GetIsolate();
3625  v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
3626  // Isolate::context() may be NULL when "script collected" event occures.
3627  ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected);
3628  return context;
3629 }
3630 
3631 
3632 v8::Debug::ClientData* MessageImpl::GetClientData() const {
3633  return client_data_;
3634 }
3635 
3636 
3637 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
3638  Handle<JSObject> exec_state,
3639  Handle<JSObject> event_data,
3640  Handle<Object> callback_data,
3641  v8::Debug::ClientData* client_data)
3642  : event_(event),
3643  exec_state_(exec_state),
3644  event_data_(event_data),
3645  callback_data_(callback_data),
3646  client_data_(client_data) {}
3647 
3648 
3649 DebugEvent EventDetailsImpl::GetEvent() const {
3650  return event_;
3651 }
3652 
3653 
3654 v8::Handle<v8::Object> EventDetailsImpl::GetExecutionState() const {
3655  return v8::Utils::ToLocal(exec_state_);
3656 }
3657 
3658 
3659 v8::Handle<v8::Object> EventDetailsImpl::GetEventData() const {
3660  return v8::Utils::ToLocal(event_data_);
3661 }
3662 
3663 
3664 v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const {
3665  return GetDebugEventContext(exec_state_->GetIsolate());
3666 }
3667 
3668 
3669 v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const {
3670  return v8::Utils::ToLocal(callback_data_);
3671 }
3672 
3673 
3674 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
3675  return client_data_;
3676 }
3677 
3678 
3679 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
3680  client_data_(NULL) {
3681 }
3682 
3683 
3684 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
3685  v8::Debug::ClientData* data)
3686  : text_(text),
3687  client_data_(data) {
3688 }
3689 
3690 
3691 CommandMessage::~CommandMessage() {
3692 }
3693 
3694 
3695 void CommandMessage::Dispose() {
3696  text_.Dispose();
3697  delete client_data_;
3698  client_data_ = NULL;
3699 }
3700 
3701 
3702 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
3703  v8::Debug::ClientData* data) {
3704  return CommandMessage(command.Clone(), data);
3705 }
3706 
3707 
3708 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
3709  size_(size) {
3710  messages_ = NewArray<CommandMessage>(size);
3711 }
3712 
3713 
3714 CommandMessageQueue::~CommandMessageQueue() {
3715  while (!IsEmpty()) {
3716  CommandMessage m = Get();
3717  m.Dispose();
3718  }
3719  DeleteArray(messages_);
3720 }
3721 
3722 
3723 CommandMessage CommandMessageQueue::Get() {
3724  ASSERT(!IsEmpty());
3725  int result = start_;
3726  start_ = (start_ + 1) % size_;
3727  return messages_[result];
3728 }
3729 
3730 
3731 void CommandMessageQueue::Put(const CommandMessage& message) {
3732  if ((end_ + 1) % size_ == start_) {
3733  Expand();
3734  }
3735  messages_[end_] = message;
3736  end_ = (end_ + 1) % size_;
3737 }
3738 
3739 
3740 void CommandMessageQueue::Expand() {
3741  CommandMessageQueue new_queue(size_ * 2);
3742  while (!IsEmpty()) {
3743  new_queue.Put(Get());
3744  }
3745  CommandMessage* array_to_free = messages_;
3746  *this = new_queue;
3747  new_queue.messages_ = array_to_free;
3748  // Make the new_queue empty so that it doesn't call Dispose on any messages.
3749  new_queue.start_ = new_queue.end_;
3750  // Automatic destructor called on new_queue, freeing array_to_free.
3751 }
3752 
3753 
3754 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
3755  : logger_(logger), queue_(size) {}
3756 
3757 
3758 bool LockingCommandMessageQueue::IsEmpty() const {
3759  LockGuard<Mutex> lock_guard(&mutex_);
3760  return queue_.IsEmpty();
3761 }
3762 
3763 
3764 CommandMessage LockingCommandMessageQueue::Get() {
3765  LockGuard<Mutex> lock_guard(&mutex_);
3766  CommandMessage result = queue_.Get();
3767  logger_->DebugEvent("Get", result.text());
3768  return result;
3769 }
3770 
3771 
3772 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
3773  LockGuard<Mutex> lock_guard(&mutex_);
3774  queue_.Put(message);
3775  logger_->DebugEvent("Put", message.text());
3776 }
3777 
3778 
3779 void LockingCommandMessageQueue::Clear() {
3780  LockGuard<Mutex> lock_guard(&mutex_);
3781  queue_.Clear();
3782 }
3783 
3784 
3785 MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
3786  : Thread("v8:MsgDispHelpr"),
3787  isolate_(isolate), sem_(0),
3788  already_signalled_(false) {
3789 }
3790 
3791 
3792 void MessageDispatchHelperThread::Schedule() {
3793  {
3794  LockGuard<Mutex> lock_guard(&mutex_);
3795  if (already_signalled_) {
3796  return;
3797  }
3798  already_signalled_ = true;
3799  }
3800  sem_.Signal();
3801 }
3802 
3803 
3804 void MessageDispatchHelperThread::Run() {
3805  while (true) {
3806  sem_.Wait();
3807  {
3808  LockGuard<Mutex> lock_guard(&mutex_);
3809  already_signalled_ = false;
3810  }
3811  {
3812  Locker locker(reinterpret_cast<v8::Isolate*>(isolate_));
3813  isolate_->debugger()->CallMessageDispatchHandler();
3814  }
3815  }
3816 }
3817 
3818 #endif // ENABLE_DEBUGGER_SUPPORT
3819 
3820 } } // namespace v8::internal
byte * Address
Definition: globals.h:186
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
static void Destroy(Object **location)
Code * builtin(Name name)
Definition: builtins.h:322
static Object *& Object_at(Address addr)
Definition: v8memory.h:83
Local< Value > Call(Handle< Value > recv, int argc, Handle< Value > argv[])
Definition: api.cc:3996
#define V8PRIxPTR
Definition: globals.h:228
static Handle< Object > TryCall(Handle< JSFunction > func, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *caught_exception)
Definition: execution.cc:199
static Handle< SharedFunctionInfo > CompileScript(Handle< String > source, Handle< Object > script_name, int line_offset, int column_offset, bool is_shared_cross_origin, Handle< Context > context, v8::Extension *extension, ScriptDataImpl **cached_data, CachedDataMode cached_data_mode, NativesFlag is_natives_code)
Definition: compiler.cc:917
static Handle< Code > GetCodeForDebugging(Handle< JSFunction > function)
Definition: compiler.cc:712
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths true
Definition: flags.cc:208
void PrintF(const char *format,...)
Definition: v8utils.cc:40
Local< Value > Exception() const
Definition: api.cc:1923
Local< Value > Get(Handle< Value > key)
Definition: api.cc:3139
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
static Handle< Code > GetUnoptimizedCode(Handle< JSFunction > function)
Definition: compiler.cc:651
static int GetIndex(const char *name)
bool HasCaught() const
Definition: api.cc:1901
static int ExtractArgcFromMinorKey(int minor_key)
Definition: code-stubs.h:1637
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
static const int kPatchDebugBreakSlotReturnOffset
static Vector< const char > GetScriptName(int index)
kSerializedDataOffset Object
Definition: objects-inl.h:5016
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
Definition: flags.cc:665
Builtins * builtins()
Definition: isolate.h:948
DebugEvent
Definition: v8-debug.h:39
const int kMaxInt
Definition: globals.h:248
static Address target_address_at(Address pc, ConstantPoolArray *constant_pool)
V8_INLINE Local< T > GetValue() const
Definition: v8.h:450
void(* DebugMessageDispatchHandler)()
Definition: v8-debug.h:183
static bool EnsureCompiled(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: compiler.cc:687
#define ASSERT(condition)
Definition: checks.h:329
static const int kPatchReturnSequenceAddressOffset
static const int kContextOffset
Definition: frames.h:185
static Script * cast(Object *obj)
void(* MessageHandler2)(const Message &message)
Definition: v8-debug.h:173
unsigned short uint16_t
Definition: unicode.cc:46
static SharedFunctionInfo * cast(Object *obj)
#define CHECK(condition)
Definition: checks.h:75
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:196
#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value)
Definition: isolate.h:137
static Smi * cast(Object *object)
v8::Isolate * GetIsolate()
Definition: api.cc:5233
static Handle< JSMessageObject > MakeMessageObject(Isolate *isolate, const char *type, MessageLocation *loc, Vector< Handle< Object > > args, Handle< JSArray > stack_frames)
Definition: messages.cc:59
uint8_t byte
Definition: globals.h:185
HANDLE HANDLE LPSTACKFRAME64 StackFrame
#define UNREACHABLE()
Definition: checks.h:52
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_string(expose_natives_as
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
Definition: flags.cc:211
V8_INLINE Isolate * GetIsolate() const
Definition: v8.h:449
static void MemCopy(void *dest, const void *src, size_t size)
Definition: platform.h:399
static const int kNoGCFlags
Definition: heap.h:1257
Handle< JSValue > GetScriptWrapper(Handle< Script > script)
Definition: handles.cc:240
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
Entry * Lookup(void *key, uint32_t hash, bool insert, FreeStoreAllocationPolicyallocator=FreeStoreAllocationPolicy())
static void * ClearWeakness(Object **location)
const Register pc
static void DeoptimizeAll(Isolate *isolate)
Definition: deoptimizer.cc:450
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:4662
static const int kMarkerOffset
Definition: frames.h:184
static const int kMakeHeapIterableMask
Definition: heap.h:1264
static Local< String > NewFromTwoByte(Isolate *isolate, const uint16_t *data, NewStringType type=kNormalString, int length=-1)
Definition: api.cc:5443
#define STATIC_ASCII_VECTOR(x)
Definition: utils.h:570
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:308
static V8_INLINE Local< T > Cast(Local< S > that)
Definition: v8.h:372
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
static const int kDebugBreakSlotLength
V8_INLINE P * GetParameter() const
Definition: v8.h:451
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
void(* EventCallback2)(const EventDetails &event_details)
Definition: v8-debug.h:163
void Load(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: shell.cc:171
void(* HostDispatchHandler)()
Definition: v8-debug.h:178
static Handle< Object > Call(Isolate *isolate, Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Definition: execution.cc:153
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:2858
V8_INLINE bool IsEmpty() const
Definition: v8.h:248
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
Object * JSCallerSavedBuffer[kNumJSCallerSaved]
Definition: frames-arm.h:55
static void MakeWeak(Object **location, void *parameter, WeakCallback weak_callback)
static Handle< T > null()
Definition: handles.h:80
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
Definition: assert-scope.h:214
static FixedArray * cast(Object *obj)
bool end_
static const int kBoundFunctionIndex
Definition: objects.h:7534
#define BUILTIN(name)
Definition: builtins.cc:143
HeapObject * obj
static void DebugBreak(Isolate *isolate=NULL)
const Register fp
static void ReportMessage(Isolate *isolate, MessageLocation *loc, Handle< Object > message)
Definition: messages.cc:100
void DeleteArray(T *array)
Definition: allocation.h:91
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
static const int kPatchDebugBreakSlotAddressOffset
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
#define ARRAY_SIZE(a)
Definition: globals.h:333
static V8_INLINE Handle< Boolean > New(Isolate *isolate, bool value)
Definition: v8.h:6129
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
Definition: api.cc:5417
static JSFunction * cast(Object *obj)